mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-29 16:44:10 +02:00
ScsiBus/ScsiDisk enhancement for no_media state.
Ahci enumeration logic tuning for boot performance. Signed-off-by:erictian Reviewed-by:qianouyang, hhuan13 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11820 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
e118a40b9d
commit
cbd2a4b362
@ -1273,12 +1273,12 @@ AhciStartCommand (
|
|||||||
if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {
|
if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {
|
||||||
if ((Capability & BIT24) != 0) {
|
if ((Capability & BIT24) != 0) {
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
|
||||||
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_COL);
|
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_CLO);
|
||||||
|
|
||||||
AhciWaitMemSet (
|
AhciWaitMemSet (
|
||||||
PciIo,
|
PciIo,
|
||||||
Offset,
|
Offset,
|
||||||
EFI_AHCI_PORT_CMD_COL,
|
EFI_AHCI_PORT_CMD_CLO,
|
||||||
0,
|
0,
|
||||||
Timeout
|
Timeout
|
||||||
);
|
);
|
||||||
@ -1816,7 +1816,6 @@ AhciPacketCommandExecute (
|
|||||||
EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
|
EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
|
||||||
EFI_ATA_STATUS_BLOCK AtaStatusBlock;
|
EFI_ATA_STATUS_BLOCK AtaStatusBlock;
|
||||||
BOOLEAN Read;
|
BOOLEAN Read;
|
||||||
UINT8 Retry;
|
|
||||||
|
|
||||||
if (Packet == NULL || Packet->Cdb == NULL) {
|
if (Packet == NULL || Packet->Cdb == NULL) {
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
@ -1860,35 +1859,21 @@ AhciPacketCommandExecute (
|
|||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
//
|
Status = AhciPioTransfer (
|
||||||
// READ_CAPACITY cmd may execute failure. Retry 5 times
|
PciIo,
|
||||||
//
|
AhciRegisters,
|
||||||
if (((UINT8 *)Packet->Cdb)[0] == ATA_CMD_READ_CAPACITY) {
|
Port,
|
||||||
Retry = 5;
|
PortMultiplier,
|
||||||
} else {
|
Packet->Cdb,
|
||||||
Retry = 1;
|
Packet->CdbLength,
|
||||||
}
|
Read,
|
||||||
do {
|
&AtaCommandBlock,
|
||||||
Status = AhciPioTransfer (
|
&AtaStatusBlock,
|
||||||
PciIo,
|
Buffer,
|
||||||
AhciRegisters,
|
Length,
|
||||||
Port,
|
Packet->Timeout,
|
||||||
PortMultiplier,
|
NULL
|
||||||
Packet->Cdb,
|
);
|
||||||
Packet->CdbLength,
|
|
||||||
Read,
|
|
||||||
&AtaCommandBlock,
|
|
||||||
&AtaStatusBlock,
|
|
||||||
Buffer,
|
|
||||||
Length,
|
|
||||||
Packet->Timeout,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Retry--;
|
|
||||||
} while (Retry != 0);
|
|
||||||
}
|
}
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
@ -2165,7 +2150,8 @@ AhciModeInitialization (
|
|||||||
EFI_ATA_DEVICE_TYPE DeviceType;
|
EFI_ATA_DEVICE_TYPE DeviceType;
|
||||||
EFI_ATA_COLLECTIVE_MODE *SupportedModes;
|
EFI_ATA_COLLECTIVE_MODE *SupportedModes;
|
||||||
EFI_ATA_TRANSFER_MODE TransferMode;
|
EFI_ATA_TRANSFER_MODE TransferMode;
|
||||||
|
UINT32 PhyDetectDelay;
|
||||||
|
|
||||||
if (Instance == NULL) {
|
if (Instance == NULL) {
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
@ -2173,7 +2159,7 @@ AhciModeInitialization (
|
|||||||
PciIo = Instance->PciIo;
|
PciIo = Instance->PciIo;
|
||||||
IdeInit = Instance->IdeControllerInit;
|
IdeInit = Instance->IdeControllerInit;
|
||||||
|
|
||||||
Status = AhciReset (PciIo, ATA_ATAPI_TIMEOUT);
|
Status = AhciReset (PciIo, EFI_AHCI_BUS_RESET_TIMEOUT);
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return EFI_DEVICE_ERROR;
|
return EFI_DEVICE_ERROR;
|
||||||
@ -2193,14 +2179,14 @@ AhciModeInitialization (
|
|||||||
// Get the number of command slots per port supported by this HBA.
|
// Get the number of command slots per port supported by this HBA.
|
||||||
//
|
//
|
||||||
MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);
|
MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);
|
||||||
Support64Bit = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);
|
MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);
|
||||||
|
Support64Bit = (BOOLEAN) (((Capability & EFI_AHCI_CAP_S64A) != 0) ? TRUE : FALSE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the bit map of those ports exposed by this HBA.
|
// Get the bit map of those ports exposed by this HBA.
|
||||||
// It indicates which ports that the HBA supports are available for software to use.
|
// It indicates which ports that the HBA supports are available for software to use.
|
||||||
//
|
//
|
||||||
PortImplementBitMap = AhciReadReg(PciIo, EFI_AHCI_PI_OFFSET);
|
PortImplementBitMap = AhciReadReg(PciIo, EFI_AHCI_PI_OFFSET);
|
||||||
MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);
|
|
||||||
|
|
||||||
AhciRegisters = &Instance->AhciRegisters;
|
AhciRegisters = &Instance->AhciRegisters;
|
||||||
Status = AhciCreateTransferDescriptor (PciIo, AhciRegisters);
|
Status = AhciCreateTransferDescriptor (PciIo, AhciRegisters);
|
||||||
@ -2210,191 +2196,227 @@ AhciModeInitialization (
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Port = 0; Port < MaxPortNumber; Port ++) {
|
for (Port = 0; Port < MaxPortNumber; Port ++) {
|
||||||
Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFisPciAddr) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
|
|
||||||
|
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
|
|
||||||
AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
|
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
|
|
||||||
AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Single task envrionment, we only use one command table for all port
|
|
||||||
//
|
|
||||||
Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdListPciAddr);
|
|
||||||
|
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
|
|
||||||
AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
|
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
|
|
||||||
AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
|
|
||||||
|
|
||||||
if ((PortImplementBitMap & (BIT0 << Port)) != 0) {
|
if ((PortImplementBitMap & (BIT0 << Port)) != 0) {
|
||||||
|
IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, Port);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize FIS Base Address Register and Command List Base Address Register for use.
|
||||||
|
//
|
||||||
|
Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFisPciAddr) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
|
||||||
|
AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
|
||||||
|
AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
|
||||||
|
|
||||||
|
Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdListPciAddr);
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
|
||||||
|
AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
|
||||||
|
AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
|
||||||
|
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
|
||||||
|
|
||||||
if ((Capability & EFI_AHCI_PORT_CMD_ASP) != 0) {
|
|
||||||
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_SUD);
|
|
||||||
}
|
|
||||||
Data = AhciReadReg (PciIo, Offset);
|
Data = AhciReadReg (PciIo, Offset);
|
||||||
if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
|
if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
|
||||||
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_POD);
|
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_POD);
|
||||||
}
|
}
|
||||||
|
|
||||||
AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE|EFI_AHCI_PORT_CMD_COL|EFI_AHCI_PORT_CMD_ST));
|
|
||||||
}
|
|
||||||
|
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
|
|
||||||
AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_SCTL_IPM_MASK));
|
|
||||||
|
|
||||||
AhciAndReg (PciIo, Offset,(UINT32) ~(EFI_AHCI_PORT_SCTL_IPM_PSD));
|
|
||||||
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_PSD);
|
|
||||||
|
|
||||||
AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_SCTL_IPM_SSD));
|
|
||||||
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_SSD);
|
|
||||||
|
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;
|
|
||||||
AhciAndReg (PciIo, Offset, 0);
|
|
||||||
|
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
|
|
||||||
AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
if ((Capability & EFI_AHCI_CAP_SSS) != 0) {
|
||||||
// Stall for 100 milliseconds.
|
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_SUD);
|
||||||
//
|
}
|
||||||
MicroSecondDelay(100000);
|
|
||||||
|
|
||||||
IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, Port);
|
|
||||||
|
|
||||||
for (Port = 0; Port < MaxPortNumber; Port ++) {
|
|
||||||
if ((PortImplementBitMap & (BIT0 << Port)) != 0) {
|
|
||||||
|
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
|
|
||||||
Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;
|
|
||||||
|
|
||||||
if (Data == 0) {
|
//
|
||||||
|
// Disable aggressive power management.
|
||||||
|
//
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
|
||||||
|
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);
|
||||||
|
//
|
||||||
|
// Disable the reporting of the corresponding interrupt to system software.
|
||||||
|
//
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;
|
||||||
|
AhciAndReg (PciIo, Offset, 0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Now inform the IDE Controller Init Module.
|
||||||
|
//
|
||||||
|
IdeInit->NotifyPhase (IdeInit, EfiIdeBusBeforeDevicePresenceDetection, Port);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Enable FIS Receive DMA engine for the first D2H FIS.
|
||||||
|
//
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
|
||||||
|
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);
|
||||||
|
Status = AhciWaitMemSet (
|
||||||
|
PciIo,
|
||||||
|
Offset,
|
||||||
|
EFI_AHCI_PORT_CMD_FR,
|
||||||
|
EFI_AHCI_PORT_CMD_FR,
|
||||||
|
EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Found device in the port
|
// Wait no longer than 10 ms to wait the Phy to detect the presence of a device.
|
||||||
|
// It's the requirment from SATA1.0a spec section 5.2.
|
||||||
//
|
//
|
||||||
if (Data == EFI_AHCI_PORT_SSTS_DET_PCE) {
|
PhyDetectDelay = EFI_AHCI_BUS_PHY_DETECT_TIMEOUT;
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
|
||||||
|
do {
|
||||||
|
Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;
|
||||||
|
if ((Data == EFI_AHCI_PORT_SSTS_DET_PCE) || (Data == EFI_AHCI_PORT_SSTS_DET)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MicroSecondDelay (1000);
|
||||||
|
PhyDetectDelay--;
|
||||||
|
} while (PhyDetectDelay > 0);
|
||||||
|
|
||||||
|
if (PhyDetectDelay == 0) {
|
||||||
|
//
|
||||||
|
// No device detected at this port.
|
||||||
|
//
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
|
||||||
|
// and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
|
||||||
|
//
|
||||||
|
PhyDetectDelay = 16 * 1000;
|
||||||
|
do {
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
|
||||||
|
if (AhciReadReg(PciIo, Offset) != 0) {
|
||||||
|
AhciWriteReg (PciIo, Offset, AhciReadReg(PciIo, Offset));
|
||||||
|
}
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
|
||||||
|
|
||||||
|
Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_TFD_MASK;
|
||||||
|
if (Data == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MicroSecondDelay (1000);
|
||||||
|
PhyDetectDelay--;
|
||||||
|
} while (PhyDetectDelay > 0);
|
||||||
|
|
||||||
|
if (PhyDetectDelay == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// When the first D2H register FIS is received, the content of PxSIG register is updated.
|
||||||
|
//
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;
|
||||||
|
Status = AhciWaitMemSet (
|
||||||
|
PciIo,
|
||||||
|
Offset,
|
||||||
|
0x0000FFFF,
|
||||||
|
0x00000101,
|
||||||
|
EFI_TIMER_PERIOD_SECONDS(16)
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Data = AhciReadReg (PciIo, Offset);
|
||||||
|
if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATAPI_DEVICE_SIG) {
|
||||||
|
Status = AhciIdentifyPacket (PciIo, AhciRegisters, Port, 0, &Buffer);
|
||||||
|
|
||||||
Status = AhciWaitMemSet (
|
|
||||||
PciIo,
|
|
||||||
Offset,
|
|
||||||
0x0000FFFF,
|
|
||||||
0x00000101,
|
|
||||||
ATA_ATAPI_TIMEOUT
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
DeviceType = EfiIdeCdrom;
|
||||||
// Now inform the IDE Controller Init Module.
|
} else if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATA_DEVICE_SIG) {
|
||||||
//
|
Status = AhciIdentify (PciIo, AhciRegisters, Port, 0, &Buffer);
|
||||||
IdeInit->NotifyPhase (IdeInit, EfiIdeBusBeforeDevicePresenceDetection, Port);
|
|
||||||
|
|
||||||
Data = AhciReadReg (PciIo, Offset);
|
|
||||||
|
|
||||||
if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATAPI_DEVICE_SIG) {
|
|
||||||
Status = AhciIdentifyPacket (PciIo, AhciRegisters, Port, 0, &Buffer);
|
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceType = EfiIdeCdrom;
|
|
||||||
} else if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATA_DEVICE_SIG) {
|
|
||||||
Status = AhciIdentify (PciIo, AhciRegisters, Port, 0, &Buffer);
|
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_EC_NOT_DETECTED));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceType = EfiIdeHarddisk;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG ((EFI_D_INFO, "port [%d] port mulitplier [%d] has a [%a]\n",
|
|
||||||
Port, 0, DeviceType == EfiIdeCdrom ? "cdrom" : "harddisk"));
|
|
||||||
|
|
||||||
//
|
|
||||||
// If the device is a hard disk, then try to enable S.M.A.R.T feature
|
|
||||||
//
|
|
||||||
if (DeviceType == EfiIdeHarddisk) {
|
|
||||||
AhciAtaSmartSupport (
|
|
||||||
PciIo,
|
|
||||||
AhciRegisters,
|
|
||||||
Port,
|
|
||||||
0,
|
|
||||||
&Buffer,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Submit identify data to IDE controller init driver
|
|
||||||
//
|
|
||||||
IdeInit->SubmitData (IdeInit, Port, 0, &Buffer);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Now start to config ide device parameter and transfer mode.
|
|
||||||
//
|
|
||||||
Status = IdeInit->CalculateMode (
|
|
||||||
IdeInit,
|
|
||||||
Port,
|
|
||||||
0,
|
|
||||||
&SupportedModes
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
DEBUG ((EFI_D_ERROR, "Calculate Mode Fail, Status = %r\n", Status));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set best supported PIO mode on this IDE device
|
|
||||||
//
|
|
||||||
if (SupportedModes->PioMode.Mode <= EfiAtaPioMode2) {
|
|
||||||
TransferMode.ModeCategory = EFI_ATA_MODE_DEFAULT_PIO;
|
|
||||||
} else {
|
|
||||||
TransferMode.ModeCategory = EFI_ATA_MODE_FLOW_PIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
|
|
||||||
// be set together. Only one DMA mode can be set to a device. If setting
|
|
||||||
// DMA mode operation fails, we can continue moving on because we only use
|
|
||||||
// PIO mode at boot time. DMA modes are used by certain kind of OS booting
|
|
||||||
//
|
|
||||||
if (SupportedModes->UdmaMode.Valid) {
|
|
||||||
TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;
|
|
||||||
TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
|
|
||||||
} else if (SupportedModes->MultiWordDmaMode.Valid) {
|
|
||||||
TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;
|
|
||||||
TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode));
|
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
|
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_EC_NOT_DETECTED));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// Found a ATA or ATAPI device, add it into the device list.
|
DeviceType = EfiIdeHarddisk;
|
||||||
//
|
} else {
|
||||||
CreateNewDeviceInfo (Instance, Port, 0, DeviceType, &Buffer);
|
continue;
|
||||||
if (DeviceType == EfiIdeHarddisk) {
|
}
|
||||||
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE));
|
DEBUG ((EFI_D_INFO, "port [%d] port mulitplier [%d] has a [%a]\n",
|
||||||
}
|
Port, 0, DeviceType == EfiIdeCdrom ? "cdrom" : "harddisk"));
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the device is a hard disk, then try to enable S.M.A.R.T feature
|
||||||
|
//
|
||||||
|
if (DeviceType == EfiIdeHarddisk) {
|
||||||
|
AhciAtaSmartSupport (
|
||||||
|
PciIo,
|
||||||
|
AhciRegisters,
|
||||||
|
Port,
|
||||||
|
0,
|
||||||
|
&Buffer,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Submit identify data to IDE controller init driver
|
||||||
|
//
|
||||||
|
IdeInit->SubmitData (IdeInit, Port, 0, &Buffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Now start to config ide device parameter and transfer mode.
|
||||||
|
//
|
||||||
|
Status = IdeInit->CalculateMode (
|
||||||
|
IdeInit,
|
||||||
|
Port,
|
||||||
|
0,
|
||||||
|
&SupportedModes
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "Calculate Mode Fail, Status = %r\n", Status));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set best supported PIO mode on this IDE device
|
||||||
|
//
|
||||||
|
if (SupportedModes->PioMode.Mode <= EfiAtaPioMode2) {
|
||||||
|
TransferMode.ModeCategory = EFI_ATA_MODE_DEFAULT_PIO;
|
||||||
|
} else {
|
||||||
|
TransferMode.ModeCategory = EFI_ATA_MODE_FLOW_PIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
|
||||||
|
// be set together. Only one DMA mode can be set to a device. If setting
|
||||||
|
// DMA mode operation fails, we can continue moving on because we only use
|
||||||
|
// PIO mode at boot time. DMA modes are used by certain kind of OS booting
|
||||||
|
//
|
||||||
|
if (SupportedModes->UdmaMode.Valid) {
|
||||||
|
TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;
|
||||||
|
TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
|
||||||
|
} else if (SupportedModes->MultiWordDmaMode.Valid) {
|
||||||
|
TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;
|
||||||
|
TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode));
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Found a ATA or ATAPI device, add it into the device list.
|
||||||
|
//
|
||||||
|
CreateNewDeviceInfo (Instance, Port, 0, DeviceType, &Buffer);
|
||||||
|
if (DeviceType == EfiIdeHarddisk) {
|
||||||
|
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#define EFI_AHCI_BAR_INDEX 0x05
|
#define EFI_AHCI_BAR_INDEX 0x05
|
||||||
|
|
||||||
#define EFI_AHCI_CAPABILITY_OFFSET 0x0000
|
#define EFI_AHCI_CAPABILITY_OFFSET 0x0000
|
||||||
|
#define EFI_AHCI_CAP_SSS BIT27
|
||||||
|
#define EFI_AHCI_CAP_S64A BIT31
|
||||||
#define EFI_AHCI_GHC_OFFSET 0x0004
|
#define EFI_AHCI_GHC_OFFSET 0x0004
|
||||||
#define EFI_AHCI_GHC_RESET BIT0
|
#define EFI_AHCI_GHC_RESET BIT0
|
||||||
#define EFI_AHCI_GHC_IE BIT1
|
#define EFI_AHCI_GHC_IE BIT1
|
||||||
@ -34,6 +36,19 @@ typedef union {
|
|||||||
UINT64 Uint64;
|
UINT64 Uint64;
|
||||||
} DATA_64;
|
} DATA_64;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Refer SATA1.0a spec section 5.2, the Phy detection time should be less than 10ms.
|
||||||
|
//
|
||||||
|
#define EFI_AHCI_BUS_PHY_DETECT_TIMEOUT 10
|
||||||
|
//
|
||||||
|
// Refer SATA1.0a spec, the FIS enable time should be less than 500ms.
|
||||||
|
//
|
||||||
|
#define EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT EFI_TIMER_PERIOD_MILLISECONDS(500)
|
||||||
|
//
|
||||||
|
// Refer SATA1.0a spec, the bus reset time should be less than 1s.
|
||||||
|
//
|
||||||
|
#define EFI_AHCI_BUS_RESET_TIMEOUT EFI_TIMER_PERIOD_SECONDS(1)
|
||||||
|
|
||||||
#define EFI_AHCI_ATAPI_DEVICE_SIG 0xEB140000
|
#define EFI_AHCI_ATAPI_DEVICE_SIG 0xEB140000
|
||||||
#define EFI_AHCI_ATA_DEVICE_SIG 0x00000000
|
#define EFI_AHCI_ATA_DEVICE_SIG 0x00000000
|
||||||
#define EFI_AHCI_PORT_MULTIPLIER_SIG 0x96690000
|
#define EFI_AHCI_PORT_MULTIPLIER_SIG 0x96690000
|
||||||
@ -103,7 +118,7 @@ typedef union {
|
|||||||
#define EFI_AHCI_PORT_CMD_ST BIT0
|
#define EFI_AHCI_PORT_CMD_ST BIT0
|
||||||
#define EFI_AHCI_PORT_CMD_SUD BIT1
|
#define EFI_AHCI_PORT_CMD_SUD BIT1
|
||||||
#define EFI_AHCI_PORT_CMD_POD BIT2
|
#define EFI_AHCI_PORT_CMD_POD BIT2
|
||||||
#define EFI_AHCI_PORT_CMD_COL BIT3
|
#define EFI_AHCI_PORT_CMD_CLO BIT3
|
||||||
#define EFI_AHCI_PORT_CMD_CR BIT15
|
#define EFI_AHCI_PORT_CMD_CR BIT15
|
||||||
#define EFI_AHCI_PORT_CMD_FRE BIT4
|
#define EFI_AHCI_PORT_CMD_FRE BIT4
|
||||||
#define EFI_AHCI_PORT_CMD_FR BIT14
|
#define EFI_AHCI_PORT_CMD_FR BIT14
|
||||||
|
@ -1026,10 +1026,63 @@ ScsiScanCreateDevice (
|
|||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
SCSI_IO_DEV *ScsiIoDevice;
|
SCSI_IO_DEV *ScsiIoDevice;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
|
||||||
|
EFI_HANDLE DeviceHandle;
|
||||||
|
|
||||||
|
DevicePath = NULL;
|
||||||
|
RemainingDevicePath = NULL;
|
||||||
|
ScsiDevicePath = NULL;
|
||||||
|
ScsiIoDevice = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Build Device Path
|
||||||
|
//
|
||||||
|
if (ScsiBusDev->ExtScsiSupport){
|
||||||
|
Status = ScsiBusDev->ExtScsiInterface->BuildDevicePath (
|
||||||
|
ScsiBusDev->ExtScsiInterface,
|
||||||
|
&TargetId->ScsiId.ExtScsi[0],
|
||||||
|
Lun,
|
||||||
|
&ScsiDevicePath
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (
|
||||||
|
ScsiBusDev->ScsiInterface,
|
||||||
|
TargetId->ScsiId.Scsi,
|
||||||
|
Lun,
|
||||||
|
&ScsiDevicePath
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DevicePath = AppendDevicePathNode (
|
||||||
|
ScsiBusDev->DevicePath,
|
||||||
|
ScsiDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
if (DevicePath == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceHandle = NULL;
|
||||||
|
RemainingDevicePath = DevicePath;
|
||||||
|
Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);
|
||||||
|
if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {
|
||||||
|
//
|
||||||
|
// The device has been started, directly return to fast boot.
|
||||||
|
//
|
||||||
|
Status = EFI_ALREADY_STARTED;
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
|
||||||
ScsiIoDevice = AllocateZeroPool (sizeof (SCSI_IO_DEV));
|
ScsiIoDevice = AllocateZeroPool (sizeof (SCSI_IO_DEV));
|
||||||
if (ScsiIoDevice == NULL) {
|
if (ScsiIoDevice == NULL) {
|
||||||
return EFI_OUT_OF_RESOURCES;
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto ErrorExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;
|
ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;
|
||||||
@ -1053,52 +1106,12 @@ ScsiScanCreateDevice (
|
|||||||
ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;
|
ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;
|
||||||
ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;
|
ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;
|
||||||
|
|
||||||
|
|
||||||
if (!DiscoverScsiDevice (ScsiIoDevice)) {
|
if (!DiscoverScsiDevice (ScsiIoDevice)) {
|
||||||
FreePool (ScsiIoDevice);
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
return EFI_OUT_OF_RESOURCES;
|
goto ErrorExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
ScsiIoDevice->DevicePath = DevicePath;
|
||||||
// Set Device Path
|
|
||||||
//
|
|
||||||
ScsiDevicePath = NULL;
|
|
||||||
if (ScsiIoDevice->ExtScsiSupport){
|
|
||||||
Status = ScsiIoDevice->ExtScsiPassThru->BuildDevicePath (
|
|
||||||
ScsiIoDevice->ExtScsiPassThru,
|
|
||||||
&ScsiIoDevice->Pun.ScsiId.ExtScsi[0],
|
|
||||||
ScsiIoDevice->Lun,
|
|
||||||
&ScsiDevicePath
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (
|
|
||||||
ScsiIoDevice->ScsiPassThru,
|
|
||||||
ScsiIoDevice->Pun.ScsiId.Scsi,
|
|
||||||
ScsiIoDevice->Lun,
|
|
||||||
&ScsiDevicePath
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EFI_ERROR(Status)) {
|
|
||||||
FreePool (ScsiIoDevice);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScsiIoDevice->DevicePath = AppendDevicePathNode (
|
|
||||||
ScsiBusDev->DevicePath,
|
|
||||||
ScsiDevicePath
|
|
||||||
);
|
|
||||||
//
|
|
||||||
// The memory space for ScsiDevicePath is allocated in
|
|
||||||
// ScsiPassThru->BuildDevicePath() function; It is no longer used
|
|
||||||
// after EfiAppendDevicePathNode,so free the memory it occupies.
|
|
||||||
//
|
|
||||||
FreePool (ScsiDevicePath);
|
|
||||||
|
|
||||||
if (ScsiIoDevice->DevicePath == NULL) {
|
|
||||||
FreePool (ScsiIoDevice);
|
|
||||||
return EFI_OUT_OF_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||||
&ScsiIoDevice->Handle,
|
&ScsiIoDevice->Handle,
|
||||||
@ -1109,31 +1122,48 @@ ScsiScanCreateDevice (
|
|||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
FreePool (ScsiIoDevice->DevicePath);
|
goto ErrorExit;
|
||||||
FreePool (ScsiIoDevice);
|
|
||||||
return EFI_OUT_OF_RESOURCES;
|
|
||||||
} else {
|
} else {
|
||||||
if (ScsiBusDev->ExtScsiSupport) {
|
if (ScsiBusDev->ExtScsiSupport) {
|
||||||
gBS->OpenProtocol (
|
gBS->OpenProtocol (
|
||||||
Controller,
|
Controller,
|
||||||
&gEfiExtScsiPassThruProtocolGuid,
|
&gEfiExtScsiPassThruProtocolGuid,
|
||||||
(VOID **) &(ScsiBusDev->ExtScsiInterface),
|
(VOID **) &(ScsiBusDev->ExtScsiInterface),
|
||||||
This->DriverBindingHandle,
|
This->DriverBindingHandle,
|
||||||
ScsiIoDevice->Handle,
|
ScsiIoDevice->Handle,
|
||||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
gBS->OpenProtocol (
|
gBS->OpenProtocol (
|
||||||
Controller,
|
Controller,
|
||||||
&gEfiScsiPassThruProtocolGuid,
|
&gEfiScsiPassThruProtocolGuid,
|
||||||
(VOID **) &(ScsiBusDev->ScsiInterface),
|
(VOID **) &(ScsiBusDev->ScsiInterface),
|
||||||
This->DriverBindingHandle,
|
This->DriverBindingHandle,
|
||||||
ScsiIoDevice->Handle,
|
ScsiIoDevice->Handle,
|
||||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
ErrorExit:
|
||||||
|
|
||||||
|
//
|
||||||
|
// The memory space for ScsiDevicePath is allocated in
|
||||||
|
// ScsiPassThru->BuildDevicePath() function; It is no longer used
|
||||||
|
// after AppendDevicePathNode,so free the memory it occupies.
|
||||||
|
//
|
||||||
|
FreePool (ScsiDevicePath);
|
||||||
|
|
||||||
|
if (DevicePath != NULL) {
|
||||||
|
FreePool (DevicePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ScsiIoDevice != NULL) {
|
||||||
|
FreePool (ScsiIoDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1158,6 +1188,8 @@ DiscoverScsiDevice (
|
|||||||
UINT8 TargetStatus;
|
UINT8 TargetStatus;
|
||||||
EFI_SCSI_SENSE_DATA SenseData;
|
EFI_SCSI_SENSE_DATA SenseData;
|
||||||
EFI_SCSI_INQUIRY_DATA InquiryData;
|
EFI_SCSI_INQUIRY_DATA InquiryData;
|
||||||
|
UINT8 MaxRetry;
|
||||||
|
UINT8 Index;
|
||||||
|
|
||||||
HostAdapterStatus = 0;
|
HostAdapterStatus = 0;
|
||||||
TargetStatus = 0;
|
TargetStatus = 0;
|
||||||
@ -1166,21 +1198,34 @@ DiscoverScsiDevice (
|
|||||||
//
|
//
|
||||||
InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
|
InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
|
||||||
SenseDataLength = (UINT8) sizeof (EFI_SCSI_SENSE_DATA);
|
SenseDataLength = (UINT8) sizeof (EFI_SCSI_SENSE_DATA);
|
||||||
|
ZeroMem (&InquiryData, InquiryDataLength);
|
||||||
|
|
||||||
Status = ScsiInquiryCommand (
|
MaxRetry = 2;
|
||||||
&ScsiIoDevice->ScsiIo,
|
for (Index = 0; Index < MaxRetry; Index++) {
|
||||||
EFI_TIMER_PERIOD_SECONDS (1),
|
Status = ScsiInquiryCommand (
|
||||||
(VOID *) &SenseData,
|
&ScsiIoDevice->ScsiIo,
|
||||||
&SenseDataLength,
|
EFI_TIMER_PERIOD_SECONDS (1),
|
||||||
&HostAdapterStatus,
|
(VOID *) &SenseData,
|
||||||
&TargetStatus,
|
&SenseDataLength,
|
||||||
(VOID *) &InquiryData,
|
&HostAdapterStatus,
|
||||||
&InquiryDataLength,
|
&TargetStatus,
|
||||||
FALSE
|
(VOID *) &InquiryData,
|
||||||
);
|
&InquiryDataLength,
|
||||||
if (EFI_ERROR (Status) && Status != EFI_BAD_BUFFER_SIZE) {
|
FALSE
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
break;
|
||||||
|
} else if ((Status == EFI_BAD_BUFFER_SIZE) ||
|
||||||
|
(Status == EFI_INVALID_PARAMETER) ||
|
||||||
|
(Status == EFI_UNSUPPORTED)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Index == MaxRetry) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Retrieved inquiry data successfully
|
// Retrieved inquiry data successfully
|
||||||
//
|
//
|
||||||
|
@ -166,6 +166,9 @@ ScsiDiskDriverBindingStart (
|
|||||||
UINT8 Index;
|
UINT8 Index;
|
||||||
UINT8 MaxRetry;
|
UINT8 MaxRetry;
|
||||||
BOOLEAN NeedRetry;
|
BOOLEAN NeedRetry;
|
||||||
|
BOOLEAN MustReadCapacity;
|
||||||
|
|
||||||
|
MustReadCapacity = TRUE;
|
||||||
|
|
||||||
ScsiDiskDevice = (SCSI_DISK_DEV *) AllocateZeroPool (sizeof (SCSI_DISK_DEV));
|
ScsiDiskDevice = (SCSI_DISK_DEV *) AllocateZeroPool (sizeof (SCSI_DISK_DEV));
|
||||||
if (ScsiDiskDevice == NULL) {
|
if (ScsiDiskDevice == NULL) {
|
||||||
@ -199,10 +202,12 @@ ScsiDiskDriverBindingStart (
|
|||||||
switch (ScsiDiskDevice->DeviceType) {
|
switch (ScsiDiskDevice->DeviceType) {
|
||||||
case EFI_SCSI_TYPE_DISK:
|
case EFI_SCSI_TYPE_DISK:
|
||||||
ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200;
|
ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200;
|
||||||
|
MustReadCapacity = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EFI_SCSI_TYPE_CDROM:
|
case EFI_SCSI_TYPE_CDROM:
|
||||||
ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800;
|
ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800;
|
||||||
|
MustReadCapacity = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@ -249,7 +254,7 @@ ScsiDiskDriverBindingStart (
|
|||||||
// The second parameter "TRUE" means must
|
// The second parameter "TRUE" means must
|
||||||
// retrieve media capacity
|
// retrieve media capacity
|
||||||
//
|
//
|
||||||
Status = ScsiDiskDetectMedia (ScsiDiskDevice, TRUE, &Temp);
|
Status = ScsiDiskDetectMedia (ScsiDiskDevice, MustReadCapacity, &Temp);
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
//
|
//
|
||||||
// Determine if Block IO should be produced on this controller handle
|
// Determine if Block IO should be produced on this controller handle
|
||||||
@ -710,6 +715,7 @@ ScsiDiskDetectMedia (
|
|||||||
CopyMem (&OldMedia, ScsiDiskDevice->BlkIo.Media, sizeof (OldMedia));
|
CopyMem (&OldMedia, ScsiDiskDevice->BlkIo.Media, sizeof (OldMedia));
|
||||||
*MediaChange = FALSE;
|
*MediaChange = FALSE;
|
||||||
MaxRetry = 3;
|
MaxRetry = 3;
|
||||||
|
Action = ACTION_NO_ACTION;
|
||||||
|
|
||||||
for (Index = 0; Index < MaxRetry; Index++) {
|
for (Index = 0; Index < MaxRetry; Index++) {
|
||||||
Status = ScsiDiskTestUnitReady (
|
Status = ScsiDiskTestUnitReady (
|
||||||
@ -719,7 +725,19 @@ ScsiDiskDetectMedia (
|
|||||||
&NumberOfSenseKeys
|
&NumberOfSenseKeys
|
||||||
);
|
);
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
break;
|
Status = DetectMediaParsingSenseKeys (
|
||||||
|
ScsiDiskDevice,
|
||||||
|
SenseData,
|
||||||
|
NumberOfSenseKeys,
|
||||||
|
&Action
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
} else if (Action == ACTION_RETRY_COMMAND_LATER) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NeedRetry) {
|
if (!NeedRetry) {
|
||||||
@ -731,22 +749,11 @@ ScsiDiskDetectMedia (
|
|||||||
return EFI_DEVICE_ERROR;
|
return EFI_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = DetectMediaParsingSenseKeys (
|
|
||||||
ScsiDiskDevice,
|
|
||||||
SenseData,
|
|
||||||
NumberOfSenseKeys,
|
|
||||||
&Action
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
// ACTION_NO_ACTION: need not read capacity
|
// ACTION_NO_ACTION: need not read capacity
|
||||||
// other action code: need read capacity
|
// other action code: need read capacity
|
||||||
//
|
//
|
||||||
if (Action == ACTION_NO_ACTION) {
|
if (Action == ACTION_READ_CAPACITY) {
|
||||||
NeedReadCapacity = FALSE;
|
|
||||||
} else {
|
|
||||||
NeedReadCapacity = TRUE;
|
NeedReadCapacity = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1205,6 +1212,11 @@ DetectMediaParsingSenseKeys (
|
|||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ScsiDiskIsResetBefore (SenseData, NumberOfSenseKeys)) {
|
||||||
|
*Action = ACTION_RETRY_COMMAND_LATER;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) {
|
if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) {
|
||||||
ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
|
ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
|
||||||
ScsiDiskDevice->BlkIo.Media->LastBlock = 0;
|
ScsiDiskDevice->BlkIo.Media->LastBlock = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user