if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {\r
if ((Capability & BIT24) != 0) {\r
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
- AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_COL);\r
+ AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_CLO);\r
\r
AhciWaitMemSet (\r
PciIo,\r
Offset,\r
- EFI_AHCI_PORT_CMD_COL,\r
+ EFI_AHCI_PORT_CMD_CLO,\r
0,\r
Timeout\r
);\r
EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
EFI_ATA_STATUS_BLOCK AtaStatusBlock;\r
BOOLEAN Read;\r
- UINT8 Retry;\r
\r
if (Packet == NULL || Packet->Cdb == NULL) {\r
return EFI_INVALID_PARAMETER;\r
NULL\r
);\r
} else {\r
- //\r
- // READ_CAPACITY cmd may execute failure. Retry 5 times\r
- //\r
- if (((UINT8 *)Packet->Cdb)[0] == ATA_CMD_READ_CAPACITY) {\r
- Retry = 5;\r
- } else {\r
- Retry = 1;\r
- }\r
- do {\r
- Status = AhciPioTransfer (\r
- PciIo,\r
- AhciRegisters,\r
- Port,\r
- PortMultiplier,\r
- Packet->Cdb,\r
- Packet->CdbLength,\r
- Read,\r
- &AtaCommandBlock,\r
- &AtaStatusBlock,\r
- Buffer,\r
- Length,\r
- Packet->Timeout, \r
- NULL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- break;\r
- }\r
- Retry--;\r
- } while (Retry != 0);\r
+ Status = AhciPioTransfer (\r
+ PciIo,\r
+ AhciRegisters,\r
+ Port,\r
+ PortMultiplier,\r
+ Packet->Cdb,\r
+ Packet->CdbLength,\r
+ Read,\r
+ &AtaCommandBlock,\r
+ &AtaStatusBlock,\r
+ Buffer,\r
+ Length,\r
+ Packet->Timeout, \r
+ NULL\r
+ );\r
}\r
return Status;\r
}\r
EFI_ATA_DEVICE_TYPE DeviceType;\r
EFI_ATA_COLLECTIVE_MODE *SupportedModes;\r
EFI_ATA_TRANSFER_MODE TransferMode;\r
- \r
+ UINT32 PhyDetectDelay;\r
+\r
if (Instance == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
PciIo = Instance->PciIo;\r
IdeInit = Instance->IdeControllerInit;\r
\r
- Status = AhciReset (PciIo, ATA_ATAPI_TIMEOUT); \r
+ Status = AhciReset (PciIo, EFI_AHCI_BUS_RESET_TIMEOUT); \r
\r
if (EFI_ERROR (Status)) {\r
return EFI_DEVICE_ERROR;\r
// Get the number of command slots per port supported by this HBA.\r
//\r
MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);\r
- Support64Bit = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);\r
+ MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);\r
+ Support64Bit = (BOOLEAN) (((Capability & EFI_AHCI_CAP_S64A) != 0) ? TRUE : FALSE);\r
\r
//\r
// Get the bit map of those ports exposed by this HBA.\r
// It indicates which ports that the HBA supports are available for software to use. \r
//\r
PortImplementBitMap = AhciReadReg(PciIo, EFI_AHCI_PI_OFFSET);\r
- MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);\r
\r
AhciRegisters = &Instance->AhciRegisters;\r
Status = AhciCreateTransferDescriptor (PciIo, AhciRegisters);\r
}\r
\r
for (Port = 0; Port < MaxPortNumber; Port ++) { \r
- Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFisPciAddr) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;\r
- \r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;\r
- AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;\r
- AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);\r
- \r
- //\r
- // Single task envrionment, we only use one command table for all port\r
- //\r
- Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdListPciAddr);\r
- \r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;\r
- AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;\r
- AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);\r
- \r
if ((PortImplementBitMap & (BIT0 << Port)) != 0) {\r
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, Port);\r
+\r
+ //\r
+ // Initialize FIS Base Address Register and Command List Base Address Register for use.\r
+ //\r
+ Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFisPciAddr) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;\r
+ AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;\r
+ AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);\r
+\r
+ Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdListPciAddr);\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;\r
+ AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;\r
+ AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);\r
+\r
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
- \r
- if ((Capability & EFI_AHCI_PORT_CMD_ASP) != 0) {\r
- AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_SUD);\r
- }\r
Data = AhciReadReg (PciIo, Offset);\r
if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {\r
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_POD);\r
}\r
- \r
- AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE|EFI_AHCI_PORT_CMD_COL|EFI_AHCI_PORT_CMD_ST));\r
- }\r
- \r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;\r
- AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_SCTL_IPM_MASK));\r
- \r
- AhciAndReg (PciIo, Offset,(UINT32) ~(EFI_AHCI_PORT_SCTL_IPM_PSD));\r
- AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_PSD);\r
- \r
- AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_SCTL_IPM_SSD));\r
- AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_SSD);\r
- \r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;\r
- AhciAndReg (PciIo, Offset, 0);\r
- \r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;\r
- AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));\r
- }\r
\r
- //\r
- // Stall for 100 milliseconds.\r
- //\r
- MicroSecondDelay(100000);\r
- \r
- IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, Port);\r
- \r
- for (Port = 0; Port < MaxPortNumber; Port ++) { \r
- if ((PortImplementBitMap & (BIT0 << Port)) != 0) {\r
- \r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;\r
- Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;\r
+ if ((Capability & EFI_AHCI_CAP_SSS) != 0) {\r
+ AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_SUD);\r
+ }\r
+\r
+ //\r
+ // Disable aggressive power management.\r
+ //\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;\r
+ AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);\r
+ //\r
+ // Disable the reporting of the corresponding interrupt to system software.\r
+ //\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;\r
+ AhciAndReg (PciIo, Offset, 0);\r
\r
- if (Data == 0) {\r
+ //\r
+ // Now inform the IDE Controller Init Module.\r
+ //\r
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBusBeforeDevicePresenceDetection, Port);\r
+\r
+ //\r
+ // Enable FIS Receive DMA engine for the first D2H FIS.\r
+ //\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
+ AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);\r
+ Status = AhciWaitMemSet (\r
+ PciIo, \r
+ Offset,\r
+ EFI_AHCI_PORT_CMD_FR,\r
+ EFI_AHCI_PORT_CMD_FR,\r
+ EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
continue;\r
}\r
+\r
//\r
- // Found device in the port\r
+ // Wait no longer than 10 ms to wait the Phy to detect the presence of a device.\r
+ // It's the requirment from SATA1.0a spec section 5.2.\r
//\r
- if (Data == EFI_AHCI_PORT_SSTS_DET_PCE) {\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;\r
-\r
- Status = AhciWaitMemSet (\r
- PciIo, \r
- Offset,\r
- 0x0000FFFF,\r
- 0x00000101,\r
- ATA_ATAPI_TIMEOUT\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
+ PhyDetectDelay = EFI_AHCI_BUS_PHY_DETECT_TIMEOUT;\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;\r
+ do {\r
+ Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;\r
+ if ((Data == EFI_AHCI_PORT_SSTS_DET_PCE) || (Data == EFI_AHCI_PORT_SSTS_DET)) {\r
+ break;\r
}\r
\r
+ MicroSecondDelay (1000);\r
+ PhyDetectDelay--;\r
+ } while (PhyDetectDelay > 0);\r
+\r
+ if (PhyDetectDelay == 0) {\r
//\r
- // Now inform the IDE Controller Init Module.\r
+ // No device detected at this port.\r
//\r
- IdeInit->NotifyPhase (IdeInit, EfiIdeBusBeforeDevicePresenceDetection, Port);\r
+ continue;\r
+ }\r
\r
- Data = AhciReadReg (PciIo, Offset);\r
+ //\r
+ // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ\r
+ // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.\r
+ //\r
+ PhyDetectDelay = 16 * 1000;\r
+ do {\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;\r
+ if (AhciReadReg(PciIo, Offset) != 0) {\r
+ AhciWriteReg (PciIo, Offset, AhciReadReg(PciIo, Offset));\r
+ }\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
\r
- if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATAPI_DEVICE_SIG) {\r
- Status = AhciIdentifyPacket (PciIo, AhciRegisters, Port, 0, &Buffer);\r
+ Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_TFD_MASK;\r
+ if (Data == 0) {\r
+ break;\r
+ }\r
\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
+ MicroSecondDelay (1000);\r
+ PhyDetectDelay--;\r
+ } while (PhyDetectDelay > 0);\r
+ \r
+ if (PhyDetectDelay == 0) {\r
+ continue;\r
+ }\r
\r
- DeviceType = EfiIdeCdrom;\r
- } else if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATA_DEVICE_SIG) {\r
- Status = AhciIdentify (PciIo, AhciRegisters, Port, 0, &Buffer);\r
+ //\r
+ // When the first D2H register FIS is received, the content of PxSIG register is updated.\r
+ //\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;\r
+ Status = AhciWaitMemSet (\r
+ PciIo, \r
+ Offset,\r
+ 0x0000FFFF,\r
+ 0x00000101,\r
+ EFI_TIMER_PERIOD_SECONDS(16)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
\r
- if (EFI_ERROR (Status)) {\r
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_EC_NOT_DETECTED));\r
- continue;\r
- }\r
+ Data = AhciReadReg (PciIo, Offset);\r
+ if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATAPI_DEVICE_SIG) {\r
+ Status = AhciIdentifyPacket (PciIo, AhciRegisters, Port, 0, &Buffer);\r
\r
- DeviceType = EfiIdeHarddisk;\r
- } else {\r
+ if (EFI_ERROR (Status)) {\r
continue;\r
}\r
\r
- DEBUG ((EFI_D_INFO, "port [%d] port mulitplier [%d] has a [%a]\n", \r
- Port, 0, DeviceType == EfiIdeCdrom ? "cdrom" : "harddisk"));\r
-\r
- //\r
- // If the device is a hard disk, then try to enable S.M.A.R.T feature\r
- //\r
- if (DeviceType == EfiIdeHarddisk) {\r
- AhciAtaSmartSupport (\r
- PciIo,\r
- AhciRegisters,\r
- Port,\r
- 0,\r
- &Buffer,\r
- NULL\r
- );\r
- }\r
-\r
- //\r
- // Submit identify data to IDE controller init driver\r
- //\r
- IdeInit->SubmitData (IdeInit, Port, 0, &Buffer);\r
+ DeviceType = EfiIdeCdrom;\r
+ } else if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATA_DEVICE_SIG) {\r
+ Status = AhciIdentify (PciIo, AhciRegisters, Port, 0, &Buffer);\r
\r
- //\r
- // Now start to config ide device parameter and transfer mode.\r
- //\r
- Status = IdeInit->CalculateMode (\r
- IdeInit,\r
- Port,\r
- 0,\r
- &SupportedModes\r
- );\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Calculate Mode Fail, Status = %r\n", Status));\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_EC_NOT_DETECTED));\r
continue;\r
}\r
\r
- //\r
- // Set best supported PIO mode on this IDE device\r
- //\r
- if (SupportedModes->PioMode.Mode <= EfiAtaPioMode2) {\r
- TransferMode.ModeCategory = EFI_ATA_MODE_DEFAULT_PIO;\r
- } else {\r
- TransferMode.ModeCategory = EFI_ATA_MODE_FLOW_PIO;\r
- }\r
+ DeviceType = EfiIdeHarddisk;\r
+ } else {\r
+ continue;\r
+ }\r
+ DEBUG ((EFI_D_INFO, "port [%d] port mulitplier [%d] has a [%a]\n", \r
+ Port, 0, DeviceType == EfiIdeCdrom ? "cdrom" : "harddisk"));\r
\r
- TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);\r
- \r
- //\r
- // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't\r
- // be set together. Only one DMA mode can be set to a device. If setting\r
- // DMA mode operation fails, we can continue moving on because we only use\r
- // PIO mode at boot time. DMA modes are used by certain kind of OS booting\r
- //\r
- if (SupportedModes->UdmaMode.Valid) {\r
- TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;\r
- TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);\r
- } else if (SupportedModes->MultiWordDmaMode.Valid) {\r
- TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;\r
- TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode; \r
- }\r
+ //\r
+ // If the device is a hard disk, then try to enable S.M.A.R.T feature\r
+ //\r
+ if (DeviceType == EfiIdeHarddisk) {\r
+ AhciAtaSmartSupport (\r
+ PciIo,\r
+ AhciRegisters,\r
+ Port,\r
+ 0,\r
+ &Buffer,\r
+ NULL\r
+ );\r
+ }\r
\r
- Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode));\r
+ //\r
+ // Submit identify data to IDE controller init driver\r
+ //\r
+ IdeInit->SubmitData (IdeInit, Port, 0, &Buffer);\r
\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
- continue;\r
- }\r
- //\r
- // Found a ATA or ATAPI device, add it into the device list.\r
- //\r
- CreateNewDeviceInfo (Instance, Port, 0, DeviceType, &Buffer);\r
- if (DeviceType == EfiIdeHarddisk) {\r
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE));\r
- }\r
+ //\r
+ // Now start to config ide device parameter and transfer mode.\r
+ //\r
+ Status = IdeInit->CalculateMode (\r
+ IdeInit,\r
+ Port,\r
+ 0,\r
+ &SupportedModes\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Calculate Mode Fail, Status = %r\n", Status));\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Set best supported PIO mode on this IDE device\r
+ //\r
+ if (SupportedModes->PioMode.Mode <= EfiAtaPioMode2) {\r
+ TransferMode.ModeCategory = EFI_ATA_MODE_DEFAULT_PIO;\r
+ } else {\r
+ TransferMode.ModeCategory = EFI_ATA_MODE_FLOW_PIO;\r
+ }\r
+\r
+ TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);\r
+\r
+ //\r
+ // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't\r
+ // be set together. Only one DMA mode can be set to a device. If setting\r
+ // DMA mode operation fails, we can continue moving on because we only use\r
+ // PIO mode at boot time. DMA modes are used by certain kind of OS booting\r
+ //\r
+ if (SupportedModes->UdmaMode.Valid) {\r
+ TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;\r
+ TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);\r
+ } else if (SupportedModes->MultiWordDmaMode.Valid) {\r
+ TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;\r
+ TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode; \r
+ }\r
+\r
+ Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode));\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Found a ATA or ATAPI device, add it into the device list.\r
+ //\r
+ CreateNewDeviceInfo (Instance, Port, 0, DeviceType, &Buffer);\r
+ if (DeviceType == EfiIdeHarddisk) {\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE));\r
}\r
}\r
}\r
+\r
return EFI_SUCCESS;\r
}\r
\r
EFI_STATUS Status;\r
SCSI_IO_DEV *ScsiIoDevice;\r
EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
+ EFI_HANDLE DeviceHandle;\r
+\r
+ DevicePath = NULL;\r
+ RemainingDevicePath = NULL;\r
+ ScsiDevicePath = NULL;\r
+ ScsiIoDevice = NULL;\r
+\r
+ //\r
+ // Build Device Path\r
+ //\r
+ if (ScsiBusDev->ExtScsiSupport){\r
+ Status = ScsiBusDev->ExtScsiInterface->BuildDevicePath (\r
+ ScsiBusDev->ExtScsiInterface,\r
+ &TargetId->ScsiId.ExtScsi[0],\r
+ Lun,\r
+ &ScsiDevicePath\r
+ );\r
+ } else {\r
+ Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (\r
+ ScsiBusDev->ScsiInterface,\r
+ TargetId->ScsiId.Scsi,\r
+ Lun,\r
+ &ScsiDevicePath\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DevicePath = AppendDevicePathNode (\r
+ ScsiBusDev->DevicePath,\r
+ ScsiDevicePath\r
+ );\r
+\r
+ if (DevicePath == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
+ }\r
+\r
+ DeviceHandle = NULL;\r
+ RemainingDevicePath = DevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);\r
+ if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {\r
+ //\r
+ // The device has been started, directly return to fast boot.\r
+ //\r
+ Status = EFI_ALREADY_STARTED;\r
+ goto ErrorExit;\r
+ }\r
\r
ScsiIoDevice = AllocateZeroPool (sizeof (SCSI_IO_DEV));\r
if (ScsiIoDevice == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
}\r
\r
ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;\r
ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;\r
ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;\r
\r
-\r
if (!DiscoverScsiDevice (ScsiIoDevice)) {\r
- FreePool (ScsiIoDevice);\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
}\r
\r
- //\r
- // Set Device Path\r
- //\r
- ScsiDevicePath = NULL;\r
- if (ScsiIoDevice->ExtScsiSupport){\r
- Status = ScsiIoDevice->ExtScsiPassThru->BuildDevicePath (\r
- ScsiIoDevice->ExtScsiPassThru,\r
- &ScsiIoDevice->Pun.ScsiId.ExtScsi[0],\r
- ScsiIoDevice->Lun,\r
- &ScsiDevicePath\r
- );\r
- } else {\r
- Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (\r
- ScsiIoDevice->ScsiPassThru,\r
- ScsiIoDevice->Pun.ScsiId.Scsi,\r
- ScsiIoDevice->Lun,\r
- &ScsiDevicePath\r
- );\r
- }\r
-\r
- if (EFI_ERROR(Status)) {\r
- FreePool (ScsiIoDevice);\r
- return Status;\r
- }\r
-\r
- ScsiIoDevice->DevicePath = AppendDevicePathNode (\r
- ScsiBusDev->DevicePath,\r
- ScsiDevicePath\r
- );\r
- //\r
- // The memory space for ScsiDevicePath is allocated in\r
- // ScsiPassThru->BuildDevicePath() function; It is no longer used\r
- // after EfiAppendDevicePathNode,so free the memory it occupies.\r
- //\r
- FreePool (ScsiDevicePath);\r
-\r
- if (ScsiIoDevice->DevicePath == NULL) {\r
- FreePool (ScsiIoDevice);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ ScsiIoDevice->DevicePath = DevicePath;\r
\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&ScsiIoDevice->Handle,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
- FreePool (ScsiIoDevice->DevicePath);\r
- FreePool (ScsiIoDevice);\r
- return EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
} else {\r
if (ScsiBusDev->ExtScsiSupport) {\r
gBS->OpenProtocol (\r
- Controller,\r
- &gEfiExtScsiPassThruProtocolGuid,\r
- (VOID **) &(ScsiBusDev->ExtScsiInterface),\r
- This->DriverBindingHandle,\r
- ScsiIoDevice->Handle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
+ Controller,\r
+ &gEfiExtScsiPassThruProtocolGuid,\r
+ (VOID **) &(ScsiBusDev->ExtScsiInterface),\r
+ This->DriverBindingHandle,\r
+ ScsiIoDevice->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
} else {\r
gBS->OpenProtocol (\r
- Controller,\r
- &gEfiScsiPassThruProtocolGuid,\r
- (VOID **) &(ScsiBusDev->ScsiInterface),\r
- This->DriverBindingHandle,\r
- ScsiIoDevice->Handle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
+ Controller,\r
+ &gEfiScsiPassThruProtocolGuid,\r
+ (VOID **) &(ScsiBusDev->ScsiInterface),\r
+ This->DriverBindingHandle,\r
+ ScsiIoDevice->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
}\r
}\r
return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+ \r
+ //\r
+ // The memory space for ScsiDevicePath is allocated in\r
+ // ScsiPassThru->BuildDevicePath() function; It is no longer used\r
+ // after AppendDevicePathNode,so free the memory it occupies.\r
+ //\r
+ FreePool (ScsiDevicePath);\r
+\r
+ if (DevicePath != NULL) {\r
+ FreePool (DevicePath);\r
+ }\r
+\r
+ if (ScsiIoDevice != NULL) {\r
+ FreePool (ScsiIoDevice);\r
+ }\r
+\r
+ return Status;\r
}\r
\r
\r
UINT8 TargetStatus;\r
EFI_SCSI_SENSE_DATA SenseData;\r
EFI_SCSI_INQUIRY_DATA InquiryData;\r
+ UINT8 MaxRetry;\r
+ UINT8 Index;\r
\r
HostAdapterStatus = 0;\r
TargetStatus = 0;\r
//\r
InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);\r
SenseDataLength = (UINT8) sizeof (EFI_SCSI_SENSE_DATA);\r
+ ZeroMem (&InquiryData, InquiryDataLength);\r
+\r
+ MaxRetry = 2;\r
+ for (Index = 0; Index < MaxRetry; Index++) {\r
+ Status = ScsiInquiryCommand (\r
+ &ScsiIoDevice->ScsiIo,\r
+ EFI_TIMER_PERIOD_SECONDS (1),\r
+ (VOID *) &SenseData,\r
+ &SenseDataLength,\r
+ &HostAdapterStatus,\r
+ &TargetStatus,\r
+ (VOID *) &InquiryData,\r
+ &InquiryDataLength,\r
+ FALSE\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ } else if ((Status == EFI_BAD_BUFFER_SIZE) || \r
+ (Status == EFI_INVALID_PARAMETER) ||\r
+ (Status == EFI_UNSUPPORTED)) {\r
+ return FALSE;\r
+ }\r
+ }\r
\r
- Status = ScsiInquiryCommand (\r
- &ScsiIoDevice->ScsiIo,\r
- EFI_TIMER_PERIOD_SECONDS (1),\r
- (VOID *) &SenseData,\r
- &SenseDataLength,\r
- &HostAdapterStatus,\r
- &TargetStatus,\r
- (VOID *) &InquiryData,\r
- &InquiryDataLength,\r
- FALSE\r
- );\r
- if (EFI_ERROR (Status) && Status != EFI_BAD_BUFFER_SIZE) {\r
+ if (Index == MaxRetry) {\r
return FALSE;\r
}\r
+ \r
//\r
// Retrieved inquiry data successfully\r
//\r