EFI_IDENTIFY_DATA *AtaIdentifyPointer;\r
UINT32 Capacity;\r
UINT8 DeviceSelect;\r
+ UINTN Retry;\r
\r
//\r
// AtaIdentifyPointer is used for accommodating returned IDENTIFY data of\r
// and receive data from device\r
//\r
DeviceSelect = (UINT8) ((IdeDev->Device) << 4);\r
- Status = AtaPioDataIn (\r
- IdeDev,\r
- (VOID *) AtaIdentifyPointer,\r
- sizeof (EFI_IDENTIFY_DATA),\r
- ATA_CMD_IDENTIFY_DRIVE,\r
- DeviceSelect,\r
- 0,\r
- 0,\r
- 0,\r
- 0\r
- );\r
- //\r
- // If ATA Identify command succeeds, then according to the received\r
- // IDENTIFY data,\r
- // identify the device type ( ATA or not ).\r
- // If ATA device, fill the information in IdeDev.\r
- // If not ATA device, return IDE_DEVICE_ERROR\r
- //\r
- if (!EFI_ERROR (Status)) {\r
-\r
- IdeDev->pIdData = AtaIdentifyPointer;\r
\r
+ \r
+ Retry = 3;\r
+ while (Retry > 0) { \r
+ Status = AtaPioDataIn (\r
+ IdeDev,\r
+ (VOID *) AtaIdentifyPointer,\r
+ sizeof (EFI_IDENTIFY_DATA),\r
+ ATA_CMD_IDENTIFY_DRIVE,\r
+ DeviceSelect,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0\r
+ );\r
//\r
- // Print ATA Module Name\r
+ // If ATA Identify command succeeds, then according to the received\r
+ // IDENTIFY data,\r
+ // identify the device type ( ATA or not ).\r
+ // If ATA device, fill the information in IdeDev.\r
+ // If not ATA device, return IDE_DEVICE_ERROR\r
//\r
- PrintAtaModuleName (IdeDev);\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ IdeDev->pIdData = AtaIdentifyPointer;\r
\r
- //\r
- // bit 15 of pAtaIdentify->config is used to identify whether device is\r
- // ATA device or ATAPI device.\r
- // if 0, means ATA device; if 1, means ATAPI device.\r
- //\r
- if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) {\r
//\r
- // Detect if support S.M.A.R.T. If yes, enable it as default\r
+ // Print ATA Module Name\r
//\r
- AtaSMARTSupport (IdeDev);\r
+ PrintAtaModuleName (IdeDev);\r
\r
//\r
- // Check whether this device needs 48-bit addressing (ATAPI-6 ata device)\r
+ // bit 15 of pAtaIdentify->config is used to identify whether device is\r
+ // ATA device or ATAPI device.\r
+ // if 0, means ATA device; if 1, means ATAPI device.\r
//\r
- Status = AtaAtapi6Identify (IdeDev);\r
- if (!EFI_ERROR (Status)) {\r
+ if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) {\r
//\r
- // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify()\r
+ // Detect if support S.M.A.R.T. If yes, enable it as default\r
//\r
- return EFI_SUCCESS;\r
- }\r
- //\r
- // This is a hard disk <= 120GB capacity, treat it as normal hard disk\r
- //\r
- IdeDev->Type = IdeHardDisk;\r
+ AtaSMARTSupport (IdeDev);\r
\r
- //\r
- // Block Media Information:\r
- // Media->LogicalPartition , Media->WriteCaching will be filled\r
- // in the DiscoverIdeDevcie() function.\r
- //\r
- IdeDev->BlkIo.Media->IoAlign = 4;\r
- IdeDev->BlkIo.Media->MediaId = 1;\r
- IdeDev->BlkIo.Media->RemovableMedia = FALSE;\r
- IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
- IdeDev->BlkIo.Media->ReadOnly = FALSE;\r
- IdeDev->BlkIo.Media->BlockSize = 0x200;\r
+ //\r
+ // Check whether this device needs 48-bit addressing (ATAPI-6 ata device)\r
+ //\r
+ Status = AtaAtapi6Identify (IdeDev);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify()\r
+ //\r
+ return EFI_SUCCESS;\r
+ } else if (Status == EFI_DEVICE_ERROR) {\r
+ //\r
+ // Some disk with big capacity (>200GB) is slow when being identified\r
+ // and will return all zero for word83.\r
+ // We try twice at first. If it fails, we do a SoftRest and try again.\r
+ //\r
+ Retry--;\r
+ if (Retry == 1) {\r
+ //\r
+ // Do a SoftRest before the third attempt.\r
+ //\r
+ AtaSoftReset (IdeDev);\r
+ }\r
+ continue;\r
+ }\r
+ //\r
+ // This is a hard disk <= 120GB capacity, treat it as normal hard disk\r
+ //\r
+ IdeDev->Type = IdeHardDisk;\r
\r
- //\r
- // Calculate device capacity\r
- //\r
- Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) |\r
+ //\r
+ // Block Media Information:\r
+ // Media->LogicalPartition , Media->WriteCaching will be filled\r
+ // in the DiscoverIdeDevcie() function.\r
+ //\r
+ IdeDev->BlkIo.Media->IoAlign = 4;\r
+ IdeDev->BlkIo.Media->MediaId = 1;\r
+ IdeDev->BlkIo.Media->RemovableMedia = FALSE;\r
+ IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
+ IdeDev->BlkIo.Media->ReadOnly = FALSE;\r
+ IdeDev->BlkIo.Media->BlockSize = 0x200;\r
+\r
+ //\r
+ // Calculate device capacity\r
+ //\r
+ Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) |\r
AtaIdentifyPointer->AtaData.user_addressable_sectors_lo ;\r
- IdeDev->BlkIo.Media->LastBlock = Capacity - 1;\r
+ IdeDev->BlkIo.Media->LastBlock = Capacity - 1;\r
\r
- return EFI_SUCCESS;\r
+ return EFI_SUCCESS;\r
+ }\r
\r
}\r
+ break;\r
}\r
\r
gBS->FreePool (AtaIdentifyPointer);\r
and 48-bit addressing must be used\r
\r
@retval EFI_UNSUPPORTED The disk dosn't not support Atapi6 or it supports but\r
- the capacity is below 120G, 48bit addressing is not\r
- needed\r
+ the capacity is below 120G, 48bit addressing is not needed\r
+\r
+ @retval EFI_DEVICE_ERROR The identify data in IdeDev is incorrect\r
\r
@note\r
This function must be called after DEVICE_IDENTITY command has been\r
\r
Atapi6IdentifyStruct = IdeDev->pIdData;\r
\r
+ if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & (BIT15 | BIT14)) != 0x4000) {\r
+ //\r
+ // Per ATA-6 spec, word83: bit15 is zero and bit14 is one\r
+ //\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & BIT10) == 0) {\r
//\r
// The device dosn't support 48 bit addressing\r
}\r
\r
//\r
- // Channel and device differential\r
+ // Select device\r
//\r
Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
\r
//\r
- // Enable interrupt to support UDMA and Select device\r
+ // Enable interrupt to support UDMA\r
//\r
DeviceControl = 0;\r
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
\r
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
-\r
if (IdePrimary == IdeDev->Channel) {\r
IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
}\r
}\r
\r
+ //\r
+ // Read BMIS register and clear ERROR and INTR bit\r
+ //\r
+ IdeDev->PciIo->Io.Read (\r
+ IdeDev->PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ IoPortForBmis,\r
+ 1,\r
+ &RegisterValue\r
+ );\r
+ \r
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
+ \r
+ IdeDev->PciIo->Io.Write (\r
+ IdeDev->PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ IoPortForBmis,\r
+ 1,\r
+ &RegisterValue\r
+ );\r
+\r
+ Status = EFI_SUCCESS;\r
+ \r
RemainBlockNum = NumberOfBlocks;\r
while (RemainBlockNum > 0) {\r
\r
&RegisterValue\r
);\r
\r
- //\r
- // Read BMIS register and clear ERROR and INTR bit\r
- //\r
- IdeDev->PciIo->Io.Read (\r
- IdeDev->PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- IoPortForBmis,\r
- 1,\r
- &RegisterValue\r
- );\r
-\r
- RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
-\r
- IdeDev->PciIo->Io.Write (\r
- IdeDev->PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- IoPortForBmis,\r
- 1,\r
- &RegisterValue\r
- );\r
-\r
if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) {\r
Status = AtaCommandIssueExt (\r
IdeDev,\r
// it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
// So set the variable Count to 2000, for about 2 second timeout time.\r
//\r
+ Status = EFI_SUCCESS;\r
Count = 2000;\r
while (TRUE) {\r
\r
);\r
if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {\r
if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {\r
- //\r
- // Clear START bit of BMIC register before return EFI_DEVICE_ERROR\r
- //\r
- IdeDev->PciIo->Io.Read (\r
- IdeDev->PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- IoPortForBmic,\r
- 1,\r
- &RegisterValue\r
- );\r
-\r
- RegisterValue &= ~((UINT8)BMIC_START);\r
-\r
- IdeDev->PciIo->Io.Write (\r
- IdeDev->PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- IoPortForBmic,\r
- 1,\r
- &RegisterValue\r
- );\r
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
- IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
- return EFI_DEVICE_ERROR;\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
}\r
break;\r
}\r
IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
//\r
+ // Read BMIS register and clear ERROR and INTR bit\r
+ //\r
+ IdeDev->PciIo->Io.Read (\r
+ IdeDev->PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ IoPortForBmis,\r
+ 1,\r
+ &RegisterValue\r
+ );\r
+\r
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
+\r
+ IdeDev->PciIo->Io.Write (\r
+ IdeDev->PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ IoPortForBmis,\r
+ 1,\r
+ &RegisterValue\r
+ );\r
+ //\r
// Read Status Register of IDE device to clear interrupt\r
//\r
RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);\r
return EFI_DEVICE_ERROR;\r
}\r
\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
StartLba += NumberOfBlocks;\r
}\r
DeviceControl |= ATA_CTLREG_IEN_L;\r
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
\r
- return EFI_SUCCESS;\r
+ return Status;\r
}\r
+\r