1. Changed device detect method to use ATA/ATAPI device signature;

2. Enhancements to better support SATA CDROM;
3. Fixed UDMA operation for buffer above 4G memory issue;
4. Fixed maximal block setting for ATAPI read sector operation to comply with spec;
5. Some minor fixes.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1739 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
jtang12 2006-10-13 05:51:59 +00:00
parent c51cec2560
commit a98f11c5b9
7 changed files with 1100 additions and 983 deletions

View File

@ -988,6 +988,10 @@ AtaSoftReset (
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
//
// SRST should assert for at least 5 us, we use 10 us for
// better compatibility
//
gBS->Stall (10); gBS->Stall (10);
// //
@ -996,6 +1000,11 @@ AtaSoftReset (
DeviceControl = 0; DeviceControl = 0;
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
//
// Wait for at least 2 ms to check BSY status, we use 10 ms
// for better compatibility
//
gBS->Stall(10000);
// //
// slave device needs at most 31s to clear BSY // slave device needs at most 31s to clear BSY
// //
@ -1114,13 +1123,9 @@ AtaBlkIoReadBlocks (
} else { } else {
// //
// For ATA-3 compatible device, use ATA-3 read block mechanism // For ATA-3 compatible device, use ATA-3 read block mechanism
// Notice DMA operation can only handle 32bit address
// //
if ((UINTN) Buffer <= 0xFFFFFFFF) {
Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
} if (EFI_ERROR (Status)) {
if (EFI_ERROR (Status) || ((UINTN) Buffer > 0xFFFFFFFF)) {
Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
} }
} }
@ -1241,7 +1246,7 @@ AtaBlkIoWriteBlocks (
// For ATA-3 compatible device, use ATA-3 write block mechanism // For ATA-3 compatible device, use ATA-3 write block mechanism
// //
Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
if (EFI_ERROR (Status) || ((UINTN) Buffer > 0xFFFFFFFF)) { if (EFI_ERROR (Status)) {
Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
} }
} }
@ -2154,6 +2159,11 @@ AtaUdmaReadExt (
UINT8 *PrdBuffer; UINT8 *PrdBuffer;
UINTN RemainBlockNum; UINTN RemainBlockNum;
UINT8 DeviceControl; UINT8 DeviceControl;
UINT32 Count;
UINTN PageCount;
VOID *Map;
EFI_PHYSICAL_ADDRESS MemPage;
EFI_PHYSICAL_ADDRESS DeviceAddress;
// //
// Channel and device differential. Select device. // Channel and device differential. Select device.
@ -2207,7 +2217,20 @@ AtaUdmaReadExt (
// //
// Build PRD table // Build PRD table
// //
PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD))); MemPage = 0xFFFFFFFF;
PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiBootServicesData,
PageCount,
&MemPage
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));
PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);
// //
// To make sure PRD is allocated in one 64K page // To make sure PRD is allocated in one 64K page
@ -2225,7 +2248,19 @@ AtaUdmaReadExt (
// //
// Build the PRD table // Build the PRD table
// //
PrdBuffer = DataBuffer; Status = IdeDev->PciIo->Map (
IdeDev->PciIo,
EfiPciIoOperationBusMasterWrite,
DataBuffer,
&ByteCount,
&DeviceAddress,
&Map
);
if (EFI_ERROR (Status)) {
gBS->FreePages (MemPage, PageCount);
return EFI_OUT_OF_RESOURCES;
}
PrdBuffer = (VOID *) ((UINTN) DeviceAddress);
TempPrdAddr = UsedPrdAddr; TempPrdAddr = UsedPrdAddr;
while (TRUE) { while (TRUE) {
@ -2316,7 +2351,8 @@ AtaUdmaReadExt (
StartLba StartLba
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
gBS->FreePool (PrdAddr); gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
@ -2345,7 +2381,11 @@ AtaUdmaReadExt (
// //
// Check the INTERRUPT and ERROR bit of BMIS // Check the INTERRUPT and ERROR bit of BMIS
// Max transfer number of sectors for one command is 65536(32Mbyte),
// it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
// So set the variable Count to 2000, for about 2 second timeout time.
// //
Count = 2000;
while (TRUE) { while (TRUE) {
IdeDev->PciIo->Io.Read ( IdeDev->PciIo->Io.Read (
@ -2356,21 +2396,49 @@ AtaUdmaReadExt (
1, 1,
&RegisterValue &RegisterValue
); );
if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) { if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {
if (RegisterValue & BMIS_ERROR) { if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {
gBS->FreePool (PrdAddr); //
// Clear START bit of BMIC register before return EFI_DEVICE_ERROR
//
IdeDev->PciIo->Io.Read (
IdeDev->PciIo,
EfiPciIoWidthUint8,
EFI_PCI_IO_PASS_THROUGH_BAR,
IoPortForBmic,
1,
&RegisterValue
);
RegisterValue &= ~((UINT8)BMIC_START);
IdeDev->PciIo->Io.Write (
IdeDev->PciIo,
EfiPciIoWidthUint8,
EFI_PCI_IO_PASS_THROUGH_BAR,
IoPortForBmic,
1,
&RegisterValue
);
gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
break; break;
} }
gBS->Stall (1000); gBS->Stall (1000);
Count --;
} }
gBS->FreePool (PrdAddr); gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
// //
// Set START bit of BMIC register // Read Status Register of IDE device to clear interrupt
//
RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);
//
// Clear START bit of BMIC register
// //
IdeDev->PciIo->Io.Read ( IdeDev->PciIo->Io.Read (
IdeDev->PciIo, IdeDev->PciIo,
@ -2400,6 +2468,13 @@ AtaUdmaReadExt (
StartLba += NumberOfBlocks; StartLba += NumberOfBlocks;
} }
//
// Disable interrupt of Select device
//
IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);
DeviceControl |= IEN_L;
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -2448,6 +2523,11 @@ AtaUdmaRead (
UINT8 *PrdBuffer; UINT8 *PrdBuffer;
UINTN RemainBlockNum; UINTN RemainBlockNum;
UINT8 DeviceControl; UINT8 DeviceControl;
UINT32 Count;
UINTN PageCount;
VOID *Map;
EFI_PHYSICAL_ADDRESS MemPage;
EFI_PHYSICAL_ADDRESS DeviceAddress;
// //
// Channel and device differential // Channel and device differential
@ -2501,7 +2581,20 @@ AtaUdmaRead (
// //
// Build PRD table // Build PRD table
// //
PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD))); MemPage = 0xFFFFFFFF;
PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiBootServicesData,
PageCount,
&MemPage
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));
PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);
// //
// To make sure PRD is allocated in one 64K page // To make sure PRD is allocated in one 64K page
// //
@ -2518,7 +2611,19 @@ AtaUdmaRead (
// //
// Build the PRD table // Build the PRD table
// //
PrdBuffer = DataBuffer; Status = IdeDev->PciIo->Map (
IdeDev->PciIo,
EfiPciIoOperationBusMasterWrite,
DataBuffer,
&ByteCount,
&DeviceAddress,
&Map
);
if (EFI_ERROR (Status)) {
gBS->FreePages (MemPage, PageCount);
return EFI_OUT_OF_RESOURCES;
}
PrdBuffer = (UINT8 *) ((UINTN) DeviceAddress);
TempPrdAddr = UsedPrdAddr; TempPrdAddr = UsedPrdAddr;
while (TRUE) { while (TRUE) {
@ -2609,7 +2714,8 @@ AtaUdmaRead (
StartLba StartLba
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
gBS->FreePool (PrdAddr); gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
@ -2638,7 +2744,11 @@ AtaUdmaRead (
// //
// Check the INTERRUPT and ERROR bit of BMIS // Check the INTERRUPT and ERROR bit of BMIS
// Max transfer number of sectors for one command is 65536(32Mbyte),
// it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
// So set the variable Count to 2000, for about 2 second timeout time.
// //
Count = 2000;
while (TRUE) { while (TRUE) {
IdeDev->PciIo->Io.Read ( IdeDev->PciIo->Io.Read (
@ -2649,21 +2759,49 @@ AtaUdmaRead (
1, 1,
&RegisterValue &RegisterValue
); );
if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) { if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {
if (RegisterValue & BMIS_ERROR) { if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {
gBS->FreePool (PrdAddr); //
// Clear START bit of BMIC register before return EFI_DEVICE_ERROR
//
IdeDev->PciIo->Io.Read (
IdeDev->PciIo,
EfiPciIoWidthUint8,
EFI_PCI_IO_PASS_THROUGH_BAR,
IoPortForBmic,
1,
&RegisterValue
);
RegisterValue &= ~((UINT8)BMIC_START);
IdeDev->PciIo->Io.Write (
IdeDev->PciIo,
EfiPciIoWidthUint8,
EFI_PCI_IO_PASS_THROUGH_BAR,
IoPortForBmic,
1,
&RegisterValue
);
gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
break; break;
} }
gBS->Stall (1000); gBS->Stall (1000);
Count --;
} }
gBS->FreePool (PrdAddr); gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
// //
// Set START bit of BMIC register // Read Status Register of IDE device to clear interrupt
//
RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);
//
// Clear START bit of BMIC register
// //
IdeDev->PciIo->Io.Read ( IdeDev->PciIo->Io.Read (
IdeDev->PciIo, IdeDev->PciIo,
@ -2693,6 +2831,13 @@ AtaUdmaRead (
StartLba += NumberOfBlocks; StartLba += NumberOfBlocks;
} }
//
// Disable interrupt of Select device
//
IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);
DeviceControl |= IEN_L;
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -2741,6 +2886,11 @@ AtaUdmaWriteExt (
UINT8 *PrdBuffer; UINT8 *PrdBuffer;
UINTN RemainBlockNum; UINTN RemainBlockNum;
UINT8 DeviceControl; UINT8 DeviceControl;
UINT32 Count;
UINTN PageCount;
VOID *Map;
EFI_PHYSICAL_ADDRESS MemPage;
EFI_PHYSICAL_ADDRESS DeviceAddress;
// //
// Channel and device differential // Channel and device differential
@ -2794,7 +2944,20 @@ AtaUdmaWriteExt (
// //
// Build PRD table // Build PRD table
// //
PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD))); MemPage = 0xFFFFFFFF;
PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiBootServicesData,
PageCount,
&MemPage
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));
PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);
// //
// To make sure PRD is allocated in one 64K page // To make sure PRD is allocated in one 64K page
// //
@ -2811,7 +2974,19 @@ AtaUdmaWriteExt (
// //
// Build the PRD table // Build the PRD table
// //
PrdBuffer = DataBuffer; Status = IdeDev->PciIo->Map (
IdeDev->PciIo,
EfiPciIoOperationBusMasterRead,
DataBuffer,
&ByteCount,
&DeviceAddress,
&Map
);
if (EFI_ERROR (Status)) {
gBS->FreePages (MemPage, PageCount);
return EFI_OUT_OF_RESOURCES;
}
PrdBuffer = (UINT8 *) ((UINTN) DeviceAddress);
TempPrdAddr = UsedPrdAddr; TempPrdAddr = UsedPrdAddr;
while (TRUE) { while (TRUE) {
@ -2904,7 +3079,8 @@ AtaUdmaWriteExt (
StartLba StartLba
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
gBS->FreePool (PrdAddr); gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
@ -2933,7 +3109,11 @@ AtaUdmaWriteExt (
// //
// Check the INTERRUPT and ERROR bit of BMIS // Check the INTERRUPT and ERROR bit of BMIS
// Max transfer number of sectors for one command is 65536(32Mbyte),
// it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
// So set the variable Count to 2000, for about 2 second timeout time.
// //
Count = 2000;
while (TRUE) { while (TRUE) {
IdeDev->PciIo->Io.Read ( IdeDev->PciIo->Io.Read (
@ -2944,21 +3124,49 @@ AtaUdmaWriteExt (
1, 1,
&RegisterValue &RegisterValue
); );
if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) { if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {
if (RegisterValue & BMIS_ERROR) { if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {
gBS->FreePool (PrdAddr); //
// Clear START bit of BMIC register before return EFI_DEVICE_ERROR
//
IdeDev->PciIo->Io.Read (
IdeDev->PciIo,
EfiPciIoWidthUint8,
EFI_PCI_IO_PASS_THROUGH_BAR,
IoPortForBmic,
1,
&RegisterValue
);
RegisterValue &= ~((UINT8)BMIC_START);
IdeDev->PciIo->Io.Write (
IdeDev->PciIo,
EfiPciIoWidthUint8,
EFI_PCI_IO_PASS_THROUGH_BAR,
IoPortForBmic,
1,
&RegisterValue
);
gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
break; break;
} }
gBS->Stall (1000); gBS->Stall (1000);
Count --;
} }
gBS->FreePool (PrdAddr); gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
// //
// Set START bit of BMIC register // Read Status Register of IDE device to clear interrupt
//
RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);
//
// Clear START bit of BMIC register
// //
IdeDev->PciIo->Io.Read ( IdeDev->PciIo->Io.Read (
IdeDev->PciIo, IdeDev->PciIo,
@ -2984,6 +3192,13 @@ AtaUdmaWriteExt (
StartLba += NumberOfBlocks; StartLba += NumberOfBlocks;
} }
//
// Disable interrupt of Select device
//
IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);
DeviceControl |= IEN_L;
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -3036,6 +3251,11 @@ AtaUdmaWrite (
UINT8 *PrdBuffer; UINT8 *PrdBuffer;
UINTN RemainBlockNum; UINTN RemainBlockNum;
UINT8 DeviceControl; UINT8 DeviceControl;
UINT32 Count;
UINTN PageCount;
VOID *Map;
EFI_PHYSICAL_ADDRESS MemPage;
EFI_PHYSICAL_ADDRESS DeviceAddress;
// //
// Channel and device differential // Channel and device differential
@ -3089,7 +3309,20 @@ AtaUdmaWrite (
// //
// Build PRD table // Build PRD table
// //
PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD))); MemPage = 0xFFFFFFFF;
PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiBootServicesData,
PageCount,
&MemPage
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));
PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);
// //
// To make sure PRD is allocated in one 64K page // To make sure PRD is allocated in one 64K page
@ -3107,7 +3340,19 @@ AtaUdmaWrite (
// //
// Build the PRD table // Build the PRD table
// //
PrdBuffer = DataBuffer; Status = IdeDev->PciIo->Map (
IdeDev->PciIo,
EfiPciIoOperationBusMasterRead,
DataBuffer,
&ByteCount,
&DeviceAddress,
&Map
);
if (EFI_ERROR (Status)) {
gBS->FreePages (MemPage, PageCount);
return EFI_OUT_OF_RESOURCES;
}
PrdBuffer = (UINT8 *) ((UINTN) DeviceAddress);
TempPrdAddr = UsedPrdAddr; TempPrdAddr = UsedPrdAddr;
while (TRUE) { while (TRUE) {
@ -3200,7 +3445,8 @@ AtaUdmaWrite (
StartLba StartLba
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
gBS->FreePool (PrdAddr); gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
@ -3229,7 +3475,11 @@ AtaUdmaWrite (
// //
// Check the INTERRUPT and ERROR bit of BMIS // Check the INTERRUPT and ERROR bit of BMIS
// Max transfer number of sectors for one command is 65536(32Mbyte),
// it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
// So set the variable Count to 2000, for about 2 second timeout time.
// //
Count = 2000;
while (TRUE) { while (TRUE) {
IdeDev->PciIo->Io.Read ( IdeDev->PciIo->Io.Read (
@ -3240,21 +3490,50 @@ AtaUdmaWrite (
1, 1,
&RegisterValue &RegisterValue
); );
if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) { if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {
if (RegisterValue & BMIS_ERROR) { if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {
gBS->FreePool (PrdAddr); //
// Clear START bit of BMIC register before return EFI_DEVICE_ERROR
//
IdeDev->PciIo->Io.Read (
IdeDev->PciIo,
EfiPciIoWidthUint8,
EFI_PCI_IO_PASS_THROUGH_BAR,
IoPortForBmic,
1,
&RegisterValue
);
RegisterValue &= ~((UINT8)BMIC_START);
IdeDev->PciIo->Io.Write (
IdeDev->PciIo,
EfiPciIoWidthUint8,
EFI_PCI_IO_PASS_THROUGH_BAR,
IoPortForBmic,
1,
&RegisterValue
);
gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
break; break;
} }
gBS->Stall (1000); gBS->Stall (1000);
Count --;
} }
gBS->FreePool (PrdAddr); gBS->FreePages (MemPage, PageCount);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
// //
// Set START bit of BMIC register // Read Status Register of IDE device to clear interrupt
//
RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);
//
// Clear START bit of BMIC register
// //
IdeDev->PciIo->Io.Read ( IdeDev->PciIo->Io.Read (
IdeDev->PciIo, IdeDev->PciIo,
@ -3280,5 +3559,12 @@ AtaUdmaWrite (
StartLba += NumberOfBlocks; StartLba += NumberOfBlocks;
} }
//
// Disable interrupt of Select device
//
IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);
DeviceControl |= IEN_L;
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
return EFI_SUCCESS; return EFI_SUCCESS;
} }

View File

@ -784,6 +784,15 @@ PioReadWriteData (
ActualWordCount += WordCount; ActualWordCount += WordCount;
} }
if (Read) {
//
// In the case where the drive wants to send more data than we need to read,
// the DRQ bit will be set and cause delays from DRQClear2().
// We need to read data from the drive until it clears DRQ so we can move on.
//
AtapiReadPendingData (IdeDev);
}
// //
// After data transfer is completed, normally, DRQ bit should clear. // After data transfer is completed, normally, DRQ bit should clear.
// //
@ -802,25 +811,25 @@ PioReadWriteData (
Sends out ATAPI Test Unit Ready Packet Command to the specified device Sends out ATAPI Test Unit Ready Packet Command to the specified device
to find out whether device is accessible. to find out whether device is accessible.
@param[in] *IdeDev @param[in] *IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used
pointer pointing to IDE_BLK_IO_DEV data structure, used
to record all the information of the IDE device. to record all the information of the IDE device.
@param[in] *SenseCount Sense count for this packet command
@retval EFI_SUCCESS @retval EFI_SUCCESS Device is accessible.
device is accessible. @retval EFI_DEVICE_ERROR Device is not accessible.
@retval EFI_DEVICE_ERROR
device is not accessible.
**/ **/
EFI_STATUS EFI_STATUS
AtapiTestUnitReady ( AtapiTestUnitReady (
IN IDE_BLK_IO_DEV *IdeDev IN IDE_BLK_IO_DEV *IdeDev,
OUT UINTN *SenseCount
) )
{ {
ATAPI_PACKET_COMMAND Packet; ATAPI_PACKET_COMMAND Packet;
EFI_STATUS Status; EFI_STATUS Status;
*SenseCount = 0;
// //
// fill command packet // fill command packet
// //
@ -831,7 +840,17 @@ AtapiTestUnitReady (
// send command packet // send command packet
// //
Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT); Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT);
if (EFI_ERROR (Status)) {
return Status; return Status;
}
Status = AtapiRequestSense (IdeDev, SenseCount);
if (EFI_ERROR (Status)) {
*SenseCount = 0;
return Status;
}
return EFI_SUCCESS;
} }
/** /**
@ -927,7 +946,7 @@ AtapiRequestSense (
// //
// Ptr is word-based pointer // Ptr is word-based pointer
// //
Ptr += sizeof (REQUEST_SENSE_DATA) / 2; Ptr += (sizeof (REQUEST_SENSE_DATA) + 1) >> 1;
} else { } else {
// //
@ -951,30 +970,28 @@ AtapiRequestSense (
if the Read Capacity Command failed, the Sense data must be requested if the Read Capacity Command failed, the Sense data must be requested
and be analyzed to determine if the Read Capacity Command should retry. and be analyzed to determine if the Read Capacity Command should retry.
@param[in] *IdeDev @param[in] *IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used
pointer pointing to IDE_BLK_IO_DEV data structure, used
to record all the information of the IDE device. to record all the information of the IDE device.
@param[in] SenseCount Sense count for this packet command
@retval EFI_SUCCESS @retval EFI_SUCCESS Read Capacity Command finally completes successfully.
Read Capacity Command finally completes successfully. @retval EFI_DEVICE_ERROR Read Capacity Command failed because of device error.
@retval EFI_DEVICE_ERROR @note Parameter "IdeDev" will be updated in this function.
Read Capacity Command failed because of device error.
@note
parameter "IdeDev" will be updated in this function.
TODO: EFI_NOT_READY - add return value to function comment TODO: EFI_NOT_READY - add return value to function comment
**/ **/
EFI_STATUS EFI_STATUS
AtapiReadCapacity ( AtapiReadCapacity (
IN IDE_BLK_IO_DEV *IdeDev IN IDE_BLK_IO_DEV *IdeDev,
OUT UINTN *SenseCount
) )
{ {
// //
// status returned by Read Capacity Packet Command // status returned by Read Capacity Packet Command
// //
EFI_STATUS Status; EFI_STATUS Status;
EFI_STATUS SenseStatus;
ATAPI_PACKET_COMMAND Packet; ATAPI_PACKET_COMMAND Packet;
// //
@ -983,6 +1000,8 @@ AtapiReadCapacity (
READ_CAPACITY_DATA Data; READ_CAPACITY_DATA Data;
READ_FORMAT_CAPACITY_DATA FormatData; READ_FORMAT_CAPACITY_DATA FormatData;
*SenseCount = 0;
ZeroMem (&Data, sizeof (Data)); ZeroMem (&Data, sizeof (Data));
ZeroMem (&FormatData, sizeof (FormatData)); ZeroMem (&FormatData, sizeof (FormatData));
@ -1014,6 +1033,15 @@ AtapiReadCapacity (
); );
} }
if (Status == EFI_TIMEOUT) {
*SenseCount = 0;
return Status;
}
SenseStatus = AtapiRequestSense (IdeDev, SenseCount);
if (!EFI_ERROR (SenseStatus)) {
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
if (IdeDev->Type == IdeCdRom) { if (IdeDev->Type == IdeCdRom) {
@ -1076,11 +1104,12 @@ AtapiReadCapacity (
} }
} }
}
return EFI_SUCCESS; return EFI_SUCCESS;
} else { } else {
*SenseCount = 0;
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
} }
@ -1120,239 +1149,157 @@ AtapiDetectMedia (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
EFI_STATUS ReadCapacityStatus; EFI_STATUS CleanStateStatus;
EFI_BLOCK_IO_MEDIA OldMediaInfo; EFI_BLOCK_IO_MEDIA OldMediaInfo;
UINTN SenseCounts;
UINTN RetryIndex;
UINTN RetryTimes; UINTN RetryTimes;
UINTN MaximumRetryTimes; UINTN RetryNotReady;
UINTN ReadyWaitFactor; UINTN SenseCount;
BOOLEAN NeedRetry; SENSE_RESULT SResult;
//
// a flag used to determine whether need to perform Read Capacity command.
//
BOOLEAN NeedReadCapacity;
BOOLEAN WriteProtected; BOOLEAN WriteProtected;
// CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (EFI_BLOCK_IO_MEDIA));
// init
//
CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (OldMediaInfo));
// OldMediaInfo = *(IdeDev->BlkIo.Media);
*MediaChange = FALSE; *MediaChange = FALSE;
ReadCapacityStatus = EFI_DEVICE_ERROR; //
// Retry for SenseDeviceNotReadyNeedRetry.
// Each retry takes 1s and we limit the upper boundary to
// 120 times about 2 min.
//
RetryNotReady = 120;
// //
// if there is no media, or media is not changed, // Do Test Unit Ready
// the request sense command will detect faster than read capacity command.
// read capacity command can be bypassed, thus improve performance.
// //
DoTUR:
//
// Retry 5 times
//
RetryTimes = 5;
while (RetryTimes != 0) {
// Status = AtapiTestUnitReady (IdeDev, &SenseCount);
// Test Unit Ready command is used to detect whether device is accessible,
// the device will produce corresponding Sense data.
//
for (RetryIndex = 0; RetryIndex < 2; RetryIndex++) {
Status = AtapiTestUnitReady (IdeDev);
if (!EFI_ERROR (Status)) {
//
// skip the loop if test unit command succeeds.
//
break;
}
Status = AtapiSoftReset (IdeDev);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
AtaSoftReset (IdeDev); //
// Test Unit Ready error without sense data.
// For some devices, this means there's extra data
// that has not been read, so we read these extra
// data out before going on.
//
CleanStateStatus = AtapiReadPendingData (IdeDev);
if (EFI_ERROR (CleanStateStatus)) {
//
// Busy wait failed, try again
//
RetryTimes--;
} }
}
SenseCounts = 0;
NeedReadCapacity = TRUE;
// //
// at most retry 5 times // Try again without counting down RetryTimes
// //
MaximumRetryTimes = 5; continue;
RetryTimes = 1; } else {
for (RetryIndex = 0; ParseSenseData (IdeDev, SenseCount, &SResult);
(RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes);
RetryIndex++) {
Status = AtapiRequestSense (IdeDev, &SenseCounts);
if (!EFI_ERROR (Status)) {
//
// if first time there is no Sense Key, no need to read capacity any more
//
if (!HaveSenseKey (IdeDev->SenseData, SenseCounts) &&
(IdeDev->BlkIo.Media->MediaPresent)) {
if (RetryIndex == 0) {
NeedReadCapacity = FALSE;
}
switch (SResult) {
case SenseNoSenseKey:
if (IdeDev->BlkIo.Media->MediaPresent) {
goto Done;
} else { } else {
// //
// No Media // Media present but the internal structure need refreshed.
// Try Read Capacity
// //
if (IsNoMedia (IdeDev->SenseData, SenseCounts)) { goto DoRC;
NeedReadCapacity = FALSE;
IdeDev->BlkIo.Media->MediaPresent = FALSE;
IdeDev->BlkIo.Media->LastBlock = 0;
} else {
//
// Media Changed
//
if (IsMediaChange (IdeDev->SenseData, SenseCounts)) {
NeedReadCapacity = TRUE;
IdeDev->BlkIo.Media->MediaId++;
} }
//
// Media Error
//
if (IsMediaError (IdeDev->SenseData, SenseCounts)) {
return EFI_DEVICE_ERROR;
}
}
}
} else {
//
// retry once more, if request sense command met errors.
//
RetryTimes++;
}
}
if (NeedReadCapacity) {
//
// at most retry 5 times
//
MaximumRetryTimes = 5;
//
// initial retry twice
//
RetryTimes = 2;
ReadyWaitFactor = 2;
for (RetryIndex = 0;
(RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes);
RetryIndex++) {
ReadCapacityStatus = AtapiReadCapacity (IdeDev);
SenseCounts = 0;
if (!EFI_ERROR (ReadCapacityStatus)) {
//
// Read Capacity succeeded
//
break; break;
} else { case SenseDeviceNotReadyNeedRetry:
if (--RetryNotReady == 0) {
if (ReadCapacityStatus == EFI_NOT_READY) {
//
// If device not ready, wait here... waiting time increases by retry
// times.
//
gBS->Stall (ReadyWaitFactor * 2000 * STALL_1_MILLI_SECOND);
ReadyWaitFactor++;
//
// retry once more
//
RetryTimes++;
continue;
}
//
// Other errors returned, requery sense data
//
Status = AtapiRequestSense (IdeDev, &SenseCounts);
//
// If Request Sense data failed, reset the device and retry.
//
if (EFI_ERROR (Status)) {
Status = AtapiSoftReset (IdeDev);
//
// if ATAPI soft reset fail,
// use stronger reset mechanism -- ATA soft reset.
//
if (EFI_ERROR (Status)) {
AtaSoftReset (IdeDev);
}
//
// retry once more
//
RetryTimes++;
continue;
}
//
// No Media
//
if (IsNoMedia (IdeDev->SenseData, SenseCounts)) {
IdeDev->BlkIo.Media->MediaPresent = FALSE;
IdeDev->BlkIo.Media->LastBlock = 0;
return EFI_NO_MEDIA;
}
if (IsMediaError (IdeDev->SenseData, SenseCounts)) {
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
//
// Media Changed
//
if (IsMediaChange (IdeDev->SenseData, SenseCounts)) {
IdeDev->BlkIo.Media->MediaId++;
}
if (!IsDriveReady (IdeDev->SenseData, SenseCounts, &NeedRetry)) {
//
// Drive not ready: if NeedRetry, then retry once more;
// else return error
//
if (NeedRetry) {
//
// Stall 1 second to wait for drive becoming ready
//
gBS->Stall (1000 * STALL_1_MILLI_SECOND); gBS->Stall (1000 * STALL_1_MILLI_SECOND);
continue;
break;
case SenseNoMedia:
IdeDev->BlkIo.Media->MediaPresent = FALSE;
IdeDev->BlkIo.Media->LastBlock = 0;
goto Done;
break;
case SenseDeviceNotReadyNoRetry:
case SenseMediaError:
return EFI_DEVICE_ERROR;
case SenseMediaChange:
IdeDev->BlkIo.Media->MediaId++;
goto DoRC;
break;
default:
RetryTimes--;
break;
}
}
}
return EFI_DEVICE_ERROR;
// //
// reset retry variable to zero, // Do Read Capacity
// to make it retry for "drive in progress of becoming ready".
// //
RetryIndex = 0; DoRC:
RetryTimes = 5;
while (RetryTimes != 0) {
Status = AtapiReadCapacity (IdeDev, &SenseCount);
if (EFI_ERROR (Status)) {
RetryTimes--;
continue; continue;
} else { } else {
AtapiSoftReset (IdeDev);
ParseSenseData (IdeDev, SenseCount, &SResult);
switch (SResult) {
case SenseNoSenseKey:
goto Done;
break;
case SenseDeviceNotReadyNeedRetry:
//
// We use Test Unit Ready to retry which
// is faster.
//
goto DoTUR;
break;
case SenseNoMedia:
IdeDev->BlkIo.Media->MediaPresent = FALSE;
IdeDev->BlkIo.Media->LastBlock = 0;
goto Done;
break;
case SenseDeviceNotReadyNoRetry:
case SenseMediaError:
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
case SenseMediaChange:
IdeDev->BlkIo.Media->MediaId++;
continue;
break;
default:
RetryTimes--;
break;
} }
} }
//
// if read capacity fail not for above reasons, retry once more
//
RetryTimes++;
} }
}
//
// tell whether the readcapacity process is successful or not in the end
//
if (EFI_ERROR (ReadCapacityStatus)) {
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
}
}
Done:
// //
// the following code is to check the write-protected for LS120 media // the following code is to check the write-protected for LS120 media
// //
@ -1423,8 +1370,11 @@ AtapiDetectMedia (
); );
} }
if (IdeDev->BlkIo.Media->MediaPresent) {
return EFI_SUCCESS; return EFI_SUCCESS;
} else {
return EFI_NO_MEDIA;
}
} }
/** /**
@ -1490,7 +1440,7 @@ AtapiReadSectors (
// //
// limit the data bytes that can be transferred by one Read(10) Command // limit the data bytes that can be transferred by one Read(10) Command
// //
MaxBlock = (UINT16) (65536 / BlockSize); MaxBlock = 65535;
BlocksRemaining = NumberOfBlocks; BlocksRemaining = NumberOfBlocks;
@ -2037,259 +1987,114 @@ AtapiBlkIoWriteBlocks (
} }
//
// The following functions are a set of helper functions,
// which are used to parse sense key returned by the device.
//
/** /**
TODO: Add function description This function is used to parse sense data. Only the first
sense data is honoured.
@param SenseData TODO: add argument description @param[in] IdeDev Indicates the calling context.
@param SenseCounts TODO: add argument description @param[in] SenseCount Count of sense data.
@param[out] Result The parsed result.
TODO: add return values @retval EFI_SUCCESS Successfully parsed.
@retval EFI_INVALID_PARAMETER Count of sense data is zero.
**/ **/
BOOLEAN EFI_STATUS
IsNoMedia ( ParseSenseData (
IN REQUEST_SENSE_DATA *SenseData, IN IDE_BLK_IO_DEV *IdeDev,
IN UINTN SenseCounts IN UINTN SenseCount,
OUT SENSE_RESULT *Result
) )
{ {
REQUEST_SENSE_DATA *SensePointer; REQUEST_SENSE_DATA *SenseData;
UINTN Index;
BOOLEAN NoMedia;
NoMedia = FALSE; if (SenseCount == 0) {
SensePointer = SenseData; return EFI_INVALID_PARAMETER;
for (Index = 0; Index < SenseCounts; Index++) {
//
// Sense Key is SK_NOT_READY (0x2),
// Additional Sense Code is ASC_NO_MEDIA (0x3A)
//
if ((SensePointer->sense_key == SK_NOT_READY) &&
(SensePointer->addnl_sense_code == ASC_NO_MEDIA)) {
NoMedia = TRUE;
} }
SensePointer++; //
// Only use the first sense data
//
SenseData = IdeDev->SenseData;
*Result = SenseOtherSense;
switch (SenseData->sense_key) {
case SK_NO_SENSE:
*Result = SenseNoSenseKey;
break;
case SK_NOT_READY:
switch (SenseData->addnl_sense_code) {
case ASC_NO_MEDIA:
*Result = SenseNoMedia;
break;
case ASC_MEDIA_UPSIDE_DOWN:
*Result = SenseMediaError;
break;
case ASC_NOT_READY:
if (SenseData->addnl_sense_code_qualifier == ASCQ_IN_PROGRESS) {
*Result = SenseDeviceNotReadyNeedRetry;
} else {
*Result = SenseDeviceNotReadyNoRetry;
} }
break;
return NoMedia; }
} break;
case SK_UNIT_ATTENTION:
/** if (SenseData->addnl_sense_code == ASC_MEDIA_CHANGE) {
Test if the device meets a media error after media changed *Result = SenseMediaChange;
}
@param[in] *SenseData break;
pointer pointing to ATAPI device sense data list.
@param[in] SenseCounts
sense data number of the list
@retval TRUE Device meets a media error
@retval FALSE No media error
**/
BOOLEAN
IsMediaError (
IN REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts
)
{
REQUEST_SENSE_DATA *SensePointer;
UINTN Index;
BOOLEAN IsError;
IsError = FALSE;
SensePointer = SenseData;
for (Index = 0; Index < SenseCounts; Index++) {
switch (SensePointer->sense_key) {
case SK_MEDIUM_ERROR: case SK_MEDIUM_ERROR:
// switch (SenseData->addnl_sense_code) {
// Sense Key is SK_MEDIUM_ERROR (0x3)
//
switch (SensePointer->addnl_sense_code) {
case ASC_MEDIA_ERR1: case ASC_MEDIA_ERR1:
case ASC_MEDIA_ERR2: case ASC_MEDIA_ERR2:
case ASC_MEDIA_ERR3: case ASC_MEDIA_ERR3:
case ASC_MEDIA_ERR4: case ASC_MEDIA_ERR4:
IsError = TRUE; *Result = SenseMediaError;
break;
}
break; break;
default: default:
break; break;
} }
break; return EFI_SUCCESS;
case SK_NOT_READY:
//
// Sense Key is SK_NOT_READY (0x2)
//
switch (SensePointer->addnl_sense_code) {
//
// Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
//
case ASC_MEDIA_UPSIDE_DOWN:
IsError = TRUE;
break;
default:
break;
}
break;
default:
break;
}
SensePointer++;
}
return IsError;
} }
/** /**
TODO: Add function description This function reads the pending data in the device.
@param SenseData TODO: add argument description @param[in] IdeDev Indicates the calling context.
@param SenseCounts TODO: add argument description
TODO: add return values @retval EFI_SUCCESS Successfully read.
@retval EFI_NOT_READY The BSY is set avoiding reading.
**/ **/
BOOLEAN EFI_STATUS
IsMediaChange ( AtapiReadPendingData (
IN REQUEST_SENSE_DATA *SenseData, IN IDE_BLK_IO_DEV *IdeDev
IN UINTN SenseCounts
) )
{ {
REQUEST_SENSE_DATA *SensePointer; UINT8 AltRegister;
UINTN Index; UINT16 TempWordBuffer;
BOOLEAN IsMediaChange;
IsMediaChange = FALSE; AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
SensePointer = SenseData; if ((AltRegister & BSY) == BSY) {
return EFI_NOT_READY;
for (Index = 0; Index < SenseCounts; Index++) {
//
// Sense Key is SK_UNIT_ATTENTION (0x6)
//
if ((SensePointer->sense_key == SK_UNIT_ATTENTION) &&
(SensePointer->addnl_sense_code == ASC_MEDIA_CHANGE)) {
IsMediaChange = TRUE;
} }
if ((AltRegister & (BSY | DRQ)) == DRQ) {
SensePointer++; TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus);
while ((TempWordBuffer & (BSY | DRQ)) == DRQ) {
IDEReadPortWMultiple (
IdeDev->PciIo,
IdeDev->IoPort->Data,
1,
&TempWordBuffer
);
TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus);
} }
return IsMediaChange;
}
/**
TODO: Add function description
@param SenseData TODO: add argument description
@param SenseCounts TODO: add argument description
@param NeedRetry TODO: add argument description
TODO: add return values
**/
BOOLEAN
IsDriveReady (
IN REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts,
OUT BOOLEAN *NeedRetry
)
{
REQUEST_SENSE_DATA *SensePointer;
UINTN Index;
BOOLEAN IsReady;
IsReady = TRUE;
*NeedRetry = FALSE;
SensePointer = SenseData;
for (Index = 0; Index < SenseCounts; Index++) {
switch (SensePointer->sense_key) {
case SK_NOT_READY:
//
// Sense Key is SK_NOT_READY (0x2)
//
switch (SensePointer->addnl_sense_code) {
case ASC_NOT_READY:
//
// Additional Sense Code is ASC_NOT_READY (0x4)
//
switch (SensePointer->addnl_sense_code_qualifier) {
case ASCQ_IN_PROGRESS:
//
// Additional Sense Code Qualifier is ASCQ_IN_PROGRESS (0x1)
//
IsReady = FALSE;
*NeedRetry = TRUE;
break;
default:
IsReady = FALSE;
*NeedRetry = FALSE;
break;
} }
break; return EFI_SUCCESS;
default:
break;
}
break;
default:
break;
}
SensePointer++;
}
return IsReady;
}
/**
TODO: Add function description
@param SenseData TODO: add argument description
@param SenseCounts TODO: add argument description
TODO: add return values
**/
BOOLEAN
HaveSenseKey (
IN REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts
)
{
BOOLEAN Have;
Have = TRUE;
//
// if first sense key in the Sense Data Array is SK_NO_SENSE,
// it indicates there is no more sense key in the Sense Data Array.
//
if (SenseData->sense_key == SK_NO_SENSE) {
Have = FALSE;
}
return Have;
} }
/** /**

View File

@ -12,8 +12,11 @@
#include "idebus.h" #include "idebus.h"
BOOLEAN ChannelDeviceDetected = FALSE;
BOOLEAN SlaveDeviceExist = FALSE; BOOLEAN SlaveDeviceExist = FALSE;
UINT8 SlaveDeviceType = INVALID_DEVICE_TYPE;
BOOLEAN MasterDeviceExist = FALSE; BOOLEAN MasterDeviceExist = FALSE;
UINT8 MasterDeviceType = INVALID_DEVICE_TYPE;
/** /**
TODO: Add function description TODO: Add function description
@ -464,57 +467,6 @@ ReassignIdeResources (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
/**
Read SATA registers to detect SATA disks
@param IdeDev The BLK_IO private data which specifies the IDE device
**/
EFI_STATUS
CheckPowerMode (
IDE_BLK_IO_DEV *IdeDev
)
// TODO: EFI_NOT_FOUND - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_NOT_FOUND - add return value to function comment
{
UINT8 ErrorRegister;
EFI_STATUS Status;
IDEWritePortB (
IdeDev->PciIo,
IdeDev->IoPort->Head,
(UINT8) ((IdeDev->Device << 4) | 0xe0)
);
//
// Wait 31 seconds for BSY clear. BSY should be in clear state if there exists
// a device (initial state). Normally, BSY is also in clear state if there is
// no device
//
Status = WaitForBSYClear (IdeDev, 31000);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
//
// select device, read error register
//
IDEWritePortB (
IdeDev->PciIo,
IdeDev->IoPort->Head,
(UINT8) ((IdeDev->Device << 4) | 0xe0)
);
Status = DRDYReady (IdeDev, 200);
ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
if ((ErrorRegister == 0x01) || (ErrorRegister == 0x81)) {
return EFI_SUCCESS;
} else {
return EFI_NOT_FOUND;
}
}
// //
// DiscoverIdeDevice // DiscoverIdeDevice
// //
@ -533,44 +485,67 @@ DiscoverIdeDevice (
// TODO: EFI_SUCCESS - add return value to function comment // TODO: EFI_SUCCESS - add return value to function comment
{ {
EFI_STATUS Status; EFI_STATUS Status;
BOOLEAN SataFlag;
SataFlag = FALSE;
//
// This extra detection is for SATA disks
//
Status = CheckPowerMode (IdeDev);
if (Status == EFI_SUCCESS) {
SataFlag = TRUE;
}
// //
// If a channel has not been checked, check it now. Then set it to "checked" state // If a channel has not been checked, check it now. Then set it to "checked" state
// After this step, all devices in this channel have been checked. // After this step, all devices in this channel have been checked.
// //
if (ChannelDeviceDetected == FALSE) {
Status = DetectIDEController (IdeDev); Status = DetectIDEController (IdeDev);
if (EFI_ERROR (Status)) {
if ((EFI_ERROR (Status)) && !SataFlag) {
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
} }
}
Status = EFI_NOT_FOUND;
// //
// Device exists. test if it is an ATA device // Device exists. test if it is an ATA device.
// Prefer the result from DetectIDEController,
// if failed, try another device type to handle
// devices that not follow the spec.
// //
if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) {
if (MasterDeviceType == ATA_DEVICE_TYPE) {
Status = ATAIdentify (IdeDev); Status = ATAIdentify (IdeDev);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
// Status = ATAPIIdentify (IdeDev);
// if not ATA device, test if it is an ATAPI device if (!EFI_ERROR (Status)) {
// MasterDeviceType = ATAPI_DEVICE_TYPE;
}
}
} else {
Status = ATAPIIdentify (IdeDev); Status = ATAPIIdentify (IdeDev);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
// Status = ATAIdentify (IdeDev);
// if not ATAPI device either, return error. if (!EFI_ERROR (Status)) {
// MasterDeviceType = ATA_DEVICE_TYPE;
}
}
}
}
if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) {
if (SlaveDeviceType == ATA_DEVICE_TYPE) {
Status = ATAIdentify (IdeDev);
if (EFI_ERROR (Status)) {
Status = ATAPIIdentify (IdeDev);
if (!EFI_ERROR (Status)) {
SlaveDeviceType = ATAPI_DEVICE_TYPE;
}
}
} else {
Status = ATAPIIdentify (IdeDev);
if (EFI_ERROR (Status)) {
Status = ATAIdentify (IdeDev);
if (!EFI_ERROR (Status)) {
SlaveDeviceType = ATA_DEVICE_TYPE;
}
}
}
}
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
} }
}
// //
// Init Block I/O interface // Init Block I/O interface
// //
@ -595,6 +570,26 @@ DiscoverIdeDevice (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
/**
This interface is used to initialize all state data related to the detection of one
channel.
@retval EFI_SUCCESS Completed Successfully.
**/
EFI_STATUS
InitializeIDEChannelData (
VOID
)
{
ChannelDeviceDetected = FALSE;
MasterDeviceExist = FALSE;
MasterDeviceType = 0xff;
SlaveDeviceExist = FALSE;
SlaveDeviceType = 0xff;
return EFI_SUCCESS;
}
/** /**
This function is called by DiscoverIdeDevice(). It is used for detect This function is called by DiscoverIdeDevice(). It is used for detect
whether the IDE device exists in the specified Channel as the specified whether the IDE device exists in the specified Channel as the specified
@ -633,31 +628,12 @@ DetectIDEController (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINT8 ErrorReg; UINT8 SectorCountReg;
UINT8 StatusReg; UINT8 LBALowReg;
UINT8 LBAMidReg;
UINT8 LBAHighReg;
UINT8 InitStatusReg; UINT8 InitStatusReg;
EFI_STATUS DeviceStatus; UINT8 StatusReg;
//
// Slave device has been detected with master device.
//
if ((IdeDev->Device) == 1) {
if (SlaveDeviceExist) {
//
// If master not exists but slave exists, slave have to wait a while
//
if (!MasterDeviceExist) {
//
// if single slave can't be detected, add delay 4s here.
//
gBS->Stall (4000000);
}
return EFI_SUCCESS;
} else {
return EFI_NOT_FOUND;
}
}
// //
// Select slave device // Select slave device
@ -675,7 +651,7 @@ DetectIDEController (
InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
// //
// Select master back // Select Master back
// //
IDEWritePortB ( IDEWritePortB (
IdeDev->PciIo, IdeDev->PciIo,
@ -683,6 +659,7 @@ DetectIDEController (
(UINT8) ((0 << 4) | 0xe0) (UINT8) ((0 << 4) | 0xe0)
); );
gBS->Stall (100); gBS->Stall (100);
// //
// Send ATA Device Execut Diagnostic command. // Send ATA Device Execut Diagnostic command.
// This command should work no matter DRDY is ready or not // This command should work no matter DRDY is ready or not
@ -690,88 +667,124 @@ DetectIDEController (
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90); IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90);
Status = WaitForBSYClear (IdeDev, 3500); Status = WaitForBSYClear (IdeDev, 3500);
if (EFI_ERROR (Status)) {
ErrorReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status));
return Status;
}
// //
// Master Error register is 0x01. D0 passed, D1 passed or not present. // Read device signature
// Master Error register is 0x81. D0 passed, D1 failed. Return.
// Master Error register is other value. D0 failed, D1 passed or not present..
// //
if (ErrorReg == 0x01) { //
// Select Master
//
IDEWritePortB (
IdeDev->PciIo,
IdeDev->IoPort->Head,
(UINT8) ((0 << 4) | 0xe0)
);
gBS->Stall (100);
SectorCountReg = IDEReadPortB (
IdeDev->PciIo,
IdeDev->IoPort->SectorCount
);
LBALowReg = IDEReadPortB (
IdeDev->PciIo,
IdeDev->IoPort->SectorNumber
);
LBAMidReg = IDEReadPortB (
IdeDev->PciIo,
IdeDev->IoPort->CylinderLsb
);
LBAHighReg = IDEReadPortB (
IdeDev->PciIo,
IdeDev->IoPort->CylinderMsb
);
if ((SectorCountReg == 0x1) &&
(LBALowReg == 0x1) &&
(LBAMidReg == 0x0) &&
(LBAHighReg == 0x0)) {
MasterDeviceExist = TRUE; MasterDeviceExist = TRUE;
DeviceStatus = EFI_SUCCESS; MasterDeviceType = ATA_DEVICE_TYPE;
} else if (ErrorReg == 0x81) {
MasterDeviceExist = TRUE;
DeviceStatus = EFI_SUCCESS;
SlaveDeviceExist = FALSE;
return DeviceStatus;
} else { } else {
MasterDeviceExist = FALSE; if ((LBAMidReg == 0x14) &&
DeviceStatus = EFI_NOT_FOUND; (LBAHighReg == 0xeb)) {
MasterDeviceExist = TRUE;
MasterDeviceType = ATAPI_DEVICE_TYPE;
}
} }
// //
// Master Error register is not 0x81, Go on check Slave // For some Hard Drive, it takes some time to get
// // the right signature when operating in single slave mode.
// We stall 20ms to work around this.
//
// Stall 20ms to wait for slave device ready if master device not exists
// //
if (!MasterDeviceExist) { if (!MasterDeviceExist) {
gBS->Stall (20000); gBS->Stall (20000);
} }
// //
// select slave // Select Slave
// //
IDEWritePortB ( IDEWritePortB (
IdeDev->PciIo, IdeDev->PciIo,
IdeDev->IoPort->Head, IdeDev->IoPort->Head,
(UINT8) ((1 << 4) | 0xe0) (UINT8) ((1 << 4) | 0xe0)
); );
gBS->Stall (100);
gBS->Stall (300); SectorCountReg = IDEReadPortB (
ErrorReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); IdeDev->PciIo,
IdeDev->IoPort->SectorCount
// );
// Slave Error register is not 0x01, D1 failed. Return. LBALowReg = IDEReadPortB (
// IdeDev->PciIo,
if (ErrorReg != 0x01) { IdeDev->IoPort->SectorNumber
SlaveDeviceExist = FALSE; );
return DeviceStatus; LBAMidReg = IDEReadPortB (
} IdeDev->PciIo,
IdeDev->IoPort->CylinderLsb
StatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); );
LBAHighReg = IDEReadPortB (
// IdeDev->PciIo,
// Most ATAPI devices don't set DRDY bit, so test with a slow but accurate IdeDev->IoPort->CylinderMsb
// "ATAPI TEST UNIT READY" command );
// StatusReg = IDEReadPortB (
if (((StatusReg & DRDY) == 0) && ((InitStatusReg & DRDY) == 0)) { IdeDev->PciIo,
Status = AtapiTestUnitReady (IdeDev); IdeDev->IoPort->Reg.Status
);
// if ((SectorCountReg == 0x1) &&
// Still fail, Slave doesn't exist. (LBALowReg == 0x1) &&
// (LBAMidReg == 0x0) &&
if (EFI_ERROR (Status)) { (LBAHighReg == 0x0)) {
SlaveDeviceExist = FALSE;
return DeviceStatus;
}
}
//
// Error reg is 0x01 and DRDY is ready,
// or ATAPI test unit ready success,
// or init Slave status DRDY is ready
// Slave exists.
//
SlaveDeviceExist = TRUE; SlaveDeviceExist = TRUE;
SlaveDeviceType = ATA_DEVICE_TYPE;
} else {
if ((LBAMidReg == 0x14) &&
(LBAHighReg == 0xeb)) {
SlaveDeviceExist = TRUE;
SlaveDeviceType = ATAPI_DEVICE_TYPE;
}
}
return DeviceStatus; //
// When single master is plugged, slave device
// will be wrongly detected. Here's the workaround
// for ATA devices by detecting DRY bit in status
// register.
// NOTE: This workaround doesn't apply to ATAPI.
//
if (MasterDeviceExist && SlaveDeviceExist &&
(StatusReg & DRDY) == 0 &&
(InitStatusReg & DRDY) == 0 &&
MasterDeviceType == SlaveDeviceType &&
SlaveDeviceType != ATAPI_DEVICE_TYPE) {
SlaveDeviceExist = FALSE;
}
//
// Indicate this channel has been detected
//
ChannelDeviceDetected = TRUE;
return EFI_SUCCESS;
} }
/** /**
@ -1251,7 +1264,7 @@ DRDYReady (
} }
} }
gBS->Stall (15); gBS->Stall (30);
Delay--; Delay--;
} while (Delay); } while (Delay);
@ -1432,6 +1445,11 @@ ReleaseIdeResources (
gBS->FreePool (IdeBlkIoDevice->DevicePath); gBS->FreePool (IdeBlkIoDevice->DevicePath);
} }
if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) {
gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent);
IdeBlkIoDevice->ExitBootServiceEvent = NULL;
}
gBS->FreePool (IdeBlkIoDevice); gBS->FreePool (IdeBlkIoDevice);
IdeBlkIoDevice = NULL; IdeBlkIoDevice = NULL;
@ -1553,8 +1571,14 @@ AtaNonDataCommandIn (
// //
// Wait for command completion // Wait for command completion
// For ATA_SMART_CMD, we may need more timeout to let device
// adjust internal states.
// //
if (AtaCommand == ATA_SMART_CMD) {
Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT);
} else {
Status = WaitForBSYClear (IdeDev, ATATIMEOUT); Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
}
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
@ -1716,12 +1740,11 @@ SetDriveParameters (
// //
// Send Init drive parameters // Send Init drive parameters
// //
Status = AtaPioDataIn ( Status = AtaNonDataCommandIn (
IdeDev, IdeDev,
NULL,
0,
INIT_DRIVE_PARAM_CMD, INIT_DRIVE_PARAM_CMD,
(UINT8) (DeviceSelect + DriveParameters->Heads), (UINT8) (DeviceSelect + DriveParameters->Heads),
0,
DriveParameters->Sector, DriveParameters->Sector,
0, 0,
0, 0,
@ -1731,18 +1754,16 @@ SetDriveParameters (
// //
// Send Set Multiple parameters // Send Set Multiple parameters
// //
Status = AtaPioDataIn ( Status = AtaNonDataCommandIn (
IdeDev, IdeDev,
NULL,
0,
SET_MULTIPLE_MODE_CMD, SET_MULTIPLE_MODE_CMD,
DeviceSelect, DeviceSelect,
0,
DriveParameters->MultipleSector, DriveParameters->MultipleSector,
0, 0,
0, 0,
0 0
); );
return Status; return Status;
} }
@ -1769,13 +1790,13 @@ EnableInterrupt (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
/** /**
Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
@param[in] Event Pointer to this event @param[in] Event Pointer to this event
@param[in] Context Event hanlder private data @param[in] Context Event hanlder private data
**/ **/
VOID VOID
EFIAPI EFIAPI

View File

@ -198,6 +198,19 @@ DiscoverIdeDevice (
) )
; ;
/**
This interface is used to initialize all state data related to the
detection of one channel.
@retval EFI_SUCCESS Completed successfully.
**/
EFI_STATUS
InitializeIDEChannelData (
VOID
)
;
/** /**
TODO: Add function description TODO: Add function description
@ -661,6 +674,7 @@ PioReadWriteData (
/** /**
TODO: Add function description TODO: Add function description
@param IdeDev TODO: add argument description
@param IdeDev TODO: add argument description @param IdeDev TODO: add argument description
TODO: add return values TODO: add return values
@ -668,7 +682,8 @@ PioReadWriteData (
**/ **/
EFI_STATUS EFI_STATUS
AtapiTestUnitReady ( AtapiTestUnitReady (
IN IDE_BLK_IO_DEV *IdeDev IN IDE_BLK_IO_DEV *IdeDev,
OUT UINTN *SenseCount
) )
; ;
@ -691,6 +706,7 @@ AtapiRequestSense (
/** /**
TODO: Add function description TODO: Add function description
@param IdeDev TODO: add argument description
@param IdeDev TODO: add argument description @param IdeDev TODO: add argument description
TODO: add return values TODO: add return values
@ -698,7 +714,8 @@ AtapiRequestSense (
**/ **/
EFI_STATUS EFI_STATUS
AtapiReadCapacity ( AtapiReadCapacity (
IN IDE_BLK_IO_DEV *IdeDev IN IDE_BLK_IO_DEV *IdeDev,
OUT UINTN *SenseCount
) )
; ;
@ -819,82 +836,32 @@ AtapiBlkIoWriteBlocks (
/** /**
TODO: Add function description TODO: Add function description
@param SenseData TODO: add argument description @param IdeDev TODO: add argument description
@param SenseCounts TODO: add argument description @param SenseCount TODO: add argument description
@param Result TODO: add argument description
TODO: add return values TODO: add return values
**/ **/
BOOLEAN EFI_STATUS
IsNoMedia ( ParseSenseData (
IN REQUEST_SENSE_DATA *SenseData, IN IDE_BLK_IO_DEV *IdeDev,
IN UINTN SenseCounts IN UINTN SenseCount,
OUT SENSE_RESULT *Result
) )
; ;
/** /**
TODO: Add function description TODO: Add function description
@param SenseData TODO: add argument description @param IdeDev TODO: add argument description
@param SenseCounts TODO: add argument description
TODO: add return values TODO: add return values
**/ **/
BOOLEAN EFI_STATUS
IsMediaError ( AtapiReadPendingData (
IN REQUEST_SENSE_DATA *SenseData, IN IDE_BLK_IO_DEV *IdeDev
IN UINTN SenseCounts
)
;
/**
TODO: Add function description
@param SenseData TODO: add argument description
@param SenseCounts TODO: add argument description
TODO: add return values
**/
BOOLEAN
IsMediaChange (
IN REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts
)
;
/**
TODO: Add function description
@param SenseData TODO: add argument description
@param SenseCounts TODO: add argument description
@param NeedRetry TODO: add argument description
TODO: add return values
**/
BOOLEAN
IsDriveReady (
IN REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts,
OUT BOOLEAN *NeedRetry
)
;
/**
TODO: Add function description
@param SenseData TODO: add argument description
@param SenseCounts TODO: add argument description
TODO: add return values
**/
BOOLEAN
HaveSenseKey (
IN REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts
) )
; ;
@ -1304,6 +1271,7 @@ EnableInterrupt (
IN IDE_BLK_IO_DEV *IdeDev IN IDE_BLK_IO_DEV *IdeDev
) )
; ;
/** /**
Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.

View File

@ -183,7 +183,6 @@ IDEBusDriverBindingStart (
UINTN DataSize; UINTN DataSize;
UINT32 Attributes; UINT32 Attributes;
IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
EFI_EVENT Event;
// //
// Local variables declaration for IdeControllerInit support // Local variables declaration for IdeControllerInit support
@ -417,6 +416,12 @@ IDEBusDriverBindingStart (
EfiIdeBusBeforeDevicePresenceDetection, EfiIdeBusBeforeDevicePresenceDetection,
IdeChannel IdeChannel
); );
//
// Prepare to detect IDE device of this channel
//
InitializeIDEChannelData ();
// //
// -- 1st inner loop --- Master/Slave ------------ Step14 // -- 1st inner loop --- Master/Slave ------------ Step14
// //
@ -488,6 +493,15 @@ IDEBusDriverBindingStart (
IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData; IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;
IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr; IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;
//
// Report Status code: is about to detect IDE drive
//
REPORT_STATUS_CODE_WITH_DEVICE_PATH (
EFI_PROGRESS_CODE,
(EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),
IdeBlkIoDevicePtr->DevicePath
);
// //
// Discover device, now! // Discover device, now!
// //
@ -523,7 +537,6 @@ IDEBusDriverBindingStart (
// Submit identify data to IDE controller init driver // Submit identify data to IDE controller init driver
// //
CopyMem (&IdentifyData, IdeBlkIoDevicePtr->pIdData, sizeof (IdentifyData)); CopyMem (&IdentifyData, IdeBlkIoDevicePtr->pIdData, sizeof (IdentifyData));
// IdentifyData = *IdeBlkIoDevicePtr->pIdData;
IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE; IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;
IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData); IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);
} else { } else {
@ -706,10 +719,9 @@ IDEBusDriverBindingStart (
EFI_TPL_NOTIFY, EFI_TPL_NOTIFY,
ClearInterrupt, ClearInterrupt,
IdeBlkIoDevicePtr, IdeBlkIoDevicePtr,
&Event &IdeBlkIoDevicePtr->ExitBootServiceEvent
); );
// //
// end of 2nd inner loop ---- // end of 2nd inner loop ----
// //
@ -1028,7 +1040,8 @@ IDEBlkIoReset (
// //
// for ATA device, using ATA reset method // for ATA device, using ATA reset method
// //
if (IdeBlkIoDevice->Type == IdeHardDisk) { if (IdeBlkIoDevice->Type == IdeHardDisk ||
IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
return AtaSoftReset (IdeBlkIoDevice); return AtaSoftReset (IdeBlkIoDevice);
} }

View File

@ -28,6 +28,10 @@
#define MAX_IDE_CHANNELS 2 #define MAX_IDE_CHANNELS 2
#define MAX_IDE_DRIVES 2 #define MAX_IDE_DRIVES 2
#define INVALID_DEVICE_TYPE 0xff
#define ATA_DEVICE_TYPE 0x00
#define ATAPI_DEVICE_TYPE 0x01
typedef struct { typedef struct {
BOOLEAN HaveScannedDevice[MAX_IDE_DEVICE]; BOOLEAN HaveScannedDevice[MAX_IDE_DEVICE];
BOOLEAN DeviceFound[MAX_IDE_DEVICE]; BOOLEAN DeviceFound[MAX_IDE_DEVICE];
@ -67,6 +71,11 @@ typedef struct {
UINT8 SenseDataNumber; UINT8 SenseDataNumber;
UINT8 *Cache; UINT8 *Cache;
//
// ExitBootService Event, it is used to clear pending IDE interrupt
//
EFI_EVENT ExitBootServiceEvent;
EFI_UNICODE_STRING_TABLE *ControllerNameTable; EFI_UNICODE_STRING_TABLE *ControllerNameTable;
} IDE_BLK_IO_DEV; } IDE_BLK_IO_DEV;

View File

@ -76,6 +76,16 @@ typedef enum {
IdeUnknown IdeUnknown
} IDE_DEVICE_TYPE; } IDE_DEVICE_TYPE;
typedef enum {
SenseNoSenseKey,
SenseDeviceNotReadyNoRetry,
SenseDeviceNotReadyNeedRetry,
SenseNoMedia,
SenseMediaChange,
SenseMediaError,
SenseOtherSense
} SENSE_RESULT;
// //
// IDE Registers // IDE Registers
// //
@ -234,6 +244,11 @@ typedef struct {
// //
#define ATAPILONGTIMEOUT 5000 #define ATAPILONGTIMEOUT 5000
//
// 10 seconds
//
#define ATASMARTTIMEOUT 10000
// //
// ATA Commands Code // ATA Commands Code
// //