mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-19 03:34:23 +02:00
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:
parent
c51cec2560
commit
a98f11c5b9
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user