From cbd2a4b3628d3242620bb5353e4b466bc435ca87 Mon Sep 17 00:00:00 2001 From: erictian Date: Tue, 14 Jun 2011 02:11:34 +0000 Subject: 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 --- MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c | 191 +++++++++++++++++---------- MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c | 40 ++++-- 2 files changed, 144 insertions(+), 87 deletions(-) (limited to 'MdeModulePkg/Bus/Scsi') diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c index e6d963672e..bfb36df828 100644 --- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c +++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c @@ -1026,10 +1026,63 @@ ScsiScanCreateDevice ( EFI_STATUS Status; SCSI_IO_DEV *ScsiIoDevice; 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)); if (ScsiIoDevice == NULL) { - return EFI_OUT_OF_RESOURCES; + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; } ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE; @@ -1053,52 +1106,12 @@ ScsiScanCreateDevice ( ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice; ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand; - if (!DiscoverScsiDevice (ScsiIoDevice)) { - FreePool (ScsiIoDevice); - return EFI_OUT_OF_RESOURCES; + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; } - // - // 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; - } + ScsiIoDevice->DevicePath = DevicePath; Status = gBS->InstallMultipleProtocolInterfaces ( &ScsiIoDevice->Handle, @@ -1109,31 +1122,48 @@ ScsiScanCreateDevice ( NULL ); if (EFI_ERROR (Status)) { - FreePool (ScsiIoDevice->DevicePath); - FreePool (ScsiIoDevice); - return EFI_OUT_OF_RESOURCES; + goto ErrorExit; } else { if (ScsiBusDev->ExtScsiSupport) { gBS->OpenProtocol ( - Controller, - &gEfiExtScsiPassThruProtocolGuid, - (VOID **) &(ScsiBusDev->ExtScsiInterface), - This->DriverBindingHandle, - ScsiIoDevice->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); + Controller, + &gEfiExtScsiPassThruProtocolGuid, + (VOID **) &(ScsiBusDev->ExtScsiInterface), + This->DriverBindingHandle, + ScsiIoDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); } else { gBS->OpenProtocol ( - Controller, - &gEfiScsiPassThruProtocolGuid, - (VOID **) &(ScsiBusDev->ScsiInterface), - This->DriverBindingHandle, - ScsiIoDevice->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); + Controller, + &gEfiScsiPassThruProtocolGuid, + (VOID **) &(ScsiBusDev->ScsiInterface), + This->DriverBindingHandle, + ScsiIoDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); } } 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; EFI_SCSI_SENSE_DATA SenseData; EFI_SCSI_INQUIRY_DATA InquiryData; + UINT8 MaxRetry; + UINT8 Index; HostAdapterStatus = 0; TargetStatus = 0; @@ -1166,21 +1198,34 @@ DiscoverScsiDevice ( // InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA); SenseDataLength = (UINT8) sizeof (EFI_SCSI_SENSE_DATA); + ZeroMem (&InquiryData, InquiryDataLength); + + MaxRetry = 2; + for (Index = 0; Index < MaxRetry; Index++) { + Status = ScsiInquiryCommand ( + &ScsiIoDevice->ScsiIo, + EFI_TIMER_PERIOD_SECONDS (1), + (VOID *) &SenseData, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus, + (VOID *) &InquiryData, + &InquiryDataLength, + FALSE + ); + if (!EFI_ERROR (Status)) { + break; + } else if ((Status == EFI_BAD_BUFFER_SIZE) || + (Status == EFI_INVALID_PARAMETER) || + (Status == EFI_UNSUPPORTED)) { + return FALSE; + } + } - Status = ScsiInquiryCommand ( - &ScsiIoDevice->ScsiIo, - EFI_TIMER_PERIOD_SECONDS (1), - (VOID *) &SenseData, - &SenseDataLength, - &HostAdapterStatus, - &TargetStatus, - (VOID *) &InquiryData, - &InquiryDataLength, - FALSE - ); - if (EFI_ERROR (Status) && Status != EFI_BAD_BUFFER_SIZE) { + if (Index == MaxRetry) { return FALSE; } + // // Retrieved inquiry data successfully // diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c index f0e10997da..e9a7788faf 100644 --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c @@ -166,6 +166,9 @@ ScsiDiskDriverBindingStart ( UINT8 Index; UINT8 MaxRetry; BOOLEAN NeedRetry; + BOOLEAN MustReadCapacity; + + MustReadCapacity = TRUE; ScsiDiskDevice = (SCSI_DISK_DEV *) AllocateZeroPool (sizeof (SCSI_DISK_DEV)); if (ScsiDiskDevice == NULL) { @@ -199,10 +202,12 @@ ScsiDiskDriverBindingStart ( switch (ScsiDiskDevice->DeviceType) { case EFI_SCSI_TYPE_DISK: ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200; + MustReadCapacity = TRUE; break; case EFI_SCSI_TYPE_CDROM: ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800; + MustReadCapacity = FALSE; break; } // @@ -249,7 +254,7 @@ ScsiDiskDriverBindingStart ( // The second parameter "TRUE" means must // retrieve media capacity // - Status = ScsiDiskDetectMedia (ScsiDiskDevice, TRUE, &Temp); + Status = ScsiDiskDetectMedia (ScsiDiskDevice, MustReadCapacity, &Temp); if (!EFI_ERROR (Status)) { // // Determine if Block IO should be produced on this controller handle @@ -710,6 +715,7 @@ ScsiDiskDetectMedia ( CopyMem (&OldMedia, ScsiDiskDevice->BlkIo.Media, sizeof (OldMedia)); *MediaChange = FALSE; MaxRetry = 3; + Action = ACTION_NO_ACTION; for (Index = 0; Index < MaxRetry; Index++) { Status = ScsiDiskTestUnitReady ( @@ -719,7 +725,19 @@ ScsiDiskDetectMedia ( &NumberOfSenseKeys ); 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) { @@ -731,22 +749,11 @@ ScsiDiskDetectMedia ( return EFI_DEVICE_ERROR; } - Status = DetectMediaParsingSenseKeys ( - ScsiDiskDevice, - SenseData, - NumberOfSenseKeys, - &Action - ); - if (EFI_ERROR (Status)) { - return Status; - } // // ACTION_NO_ACTION: need not read capacity // other action code: need read capacity // - if (Action == ACTION_NO_ACTION) { - NeedReadCapacity = FALSE; - } else { + if (Action == ACTION_READ_CAPACITY) { NeedReadCapacity = TRUE; } @@ -1205,6 +1212,11 @@ DetectMediaParsingSenseKeys ( return EFI_SUCCESS; } + if (ScsiDiskIsResetBefore (SenseData, NumberOfSenseKeys)) { + *Action = ACTION_RETRY_COMMAND_LATER; + return EFI_SUCCESS; + } + if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) { ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE; ScsiDiskDevice->BlkIo.Media->LastBlock = 0; -- cgit v1.2.3