/** @file\r
SCSI disk driver that layers on every SCSI IO protocol in the system.\r
\r
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
\r
**/\r
\r
-#include <Uefi.h>\r
-\r
-\r
-#include <Protocol/ScsiIo.h>\r
-#include <Protocol/ComponentName.h>\r
-#include <Protocol/BlockIo.h>\r
-#include <Protocol/DriverBinding.h>\r
-#include <Protocol/ScsiPassThruExt.h>\r
-\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiDriverEntryPoint.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/ScsiLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
\r
#include "ScsiDisk.h"\r
\r
NULL\r
};\r
\r
+EFI_DISK_INFO_PROTOCOL gScsiDiskInfoProtocolTemplate = {\r
+ EFI_DISK_INFO_SCSI_INTERFACE_GUID,\r
+ ScsiDiskInfoInquiry,\r
+ ScsiDiskInfoIdentify,\r
+ ScsiDiskInfoSenseData,\r
+ ScsiDiskInfoWhichIde\r
+};\r
+\r
/**\r
- The user Entry Point for module ScsiDisk. The user code starts with this function.\r
+ The user Entry Point for module ScsiDisk.\r
+\r
+ The user code starts with this function.\r
\r
- @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
- @param[in] SystemTable A pointer to the EFI System Table.\r
+ @param ImageHandle The firmware allocated handle for the EFI image. \r
+ @param SystemTable A pointer to the EFI System Table.\r
\r
@retval EFI_SUCCESS The entry point is executed successfully.\r
@retval other Some error occurs when executing this entry point.\r
return Status;\r
}\r
\r
+/**\r
+ Test to see if this driver supports ControllerHandle.\r
+\r
+ This service is called by the EFI boot service ConnectController(). In order\r
+ to make drivers as small as possible, there are a few calling restrictions for\r
+ this service. ConnectController() must follow these calling restrictions.\r
+ If any other agent wishes to call Supported() it must also follow these\r
+ calling restrictions.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ControllerHandle Handle of device to test\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS This driver supports this device\r
+ @retval EFI_ALREADY_STARTED This driver is already running on this device\r
+ @retval other This driver does not support this device\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
ScsiDiskDriverBindingSupported (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
- that has ScsiIoProtocol installed will be supported.\r
-\r
-Arguments:\r
-\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to test\r
- RemainingDevicePath - Not used\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - This driver supports this device.\r
- EFI_UNSUPPORTED - This driver does not support this device.\r
- \r
- \r
---*/\r
{\r
EFI_STATUS Status;\r
EFI_SCSI_IO_PROTOCOL *ScsiIo;\r
return Status;\r
}\r
\r
+\r
+/**\r
+ Start this driver on ControllerHandle.\r
+\r
+ This service is called by the EFI boot service ConnectController(). In order\r
+ to make drivers as small as possible, there are a few calling restrictions for\r
+ this service. ConnectController() must follow these calling restrictions. If\r
+ any other agent wishes to call Start() it must also follow these calling\r
+ restrictions.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ControllerHandle Handle of device to bind driver to\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS This driver is added to ControllerHandle\r
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
+ @retval other This driver does not support this device\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
ScsiDiskDriverBindingStart (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Start SCSI Disk Driver, and attach BlockIoProtocol to it.\r
- \r
-Arguments:\r
-\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to test\r
- RemainingDevicePath - Not used\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - This driver supports this device.\r
- EFI_UNSUPPORTED - This driver does not support this device.\r
- \r
- \r
---*/\r
{\r
EFI_STATUS Status;\r
EFI_SCSI_IO_PROTOCOL *ScsiIo;\r
UINT8 MaxRetry;\r
BOOLEAN NeedRetry;\r
\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (SCSI_DISK_DEV),\r
- (VOID **) &ScsiDiskDevice\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ ScsiDiskDevice = (SCSI_DISK_DEV *) AllocateZeroPool (sizeof (SCSI_DISK_DEV));\r
+ if (ScsiDiskDevice == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- ZeroMem (ScsiDiskDevice, sizeof (SCSI_DISK_DEV));\r
-\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiScsiIoProtocolGuid,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
);\r
if (EFI_ERROR (Status)) {\r
- gBS->FreePool (ScsiDiskDevice);\r
+ FreePool (ScsiDiskDevice);\r
return Status;\r
}\r
\r
// The Sense Data Array's initial size is 6\r
//\r
ScsiDiskDevice->SenseDataNumber = 6;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber,\r
- (VOID **) &(ScsiDiskDevice->SenseData)\r
- );\r
- if (EFI_ERROR (Status)) {\r
+ ScsiDiskDevice->SenseData = (EFI_SCSI_SENSE_DATA *) AllocateZeroPool (\r
+ sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber\r
+ );\r
+ if (ScsiDiskDevice->SenseData == NULL) {\r
gBS->CloseProtocol (\r
Controller,\r
&gEfiScsiIoProtocolGuid,\r
This->DriverBindingHandle,\r
Controller\r
);\r
- gBS->FreePool (ScsiDiskDevice);\r
- return Status;\r
+ FreePool (ScsiDiskDevice);\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- ZeroMem (\r
- ScsiDiskDevice->SenseData,\r
- sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber\r
- );\r
-\r
//\r
- // Retrive device information\r
+ // Retrieve device information\r
//\r
MaxRetry = 2;\r
for (Index = 0; Index < MaxRetry; Index++) {\r
}\r
\r
if (!NeedRetry) {\r
- gBS->FreePool (ScsiDiskDevice->SenseData);\r
+ FreePool (ScsiDiskDevice->SenseData);\r
gBS->CloseProtocol (\r
Controller,\r
&gEfiScsiIoProtocolGuid,\r
This->DriverBindingHandle,\r
Controller\r
);\r
- gBS->FreePool (ScsiDiskDevice);\r
+ FreePool (ScsiDiskDevice);\r
return EFI_DEVICE_ERROR;\r
}\r
}\r
//\r
Status = ScsiDiskDetectMedia (ScsiDiskDevice, TRUE, &Temp);\r
if (!EFI_ERROR (Status)) {\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Controller,\r
- &gEfiBlockIoProtocolGuid,\r
- &ScsiDiskDevice->BlkIo,\r
- NULL\r
- );\r
+ //\r
+ // Determine if Block IO should be produced on this controller handle\r
+ //\r
+ if (DetermineInstallBlockIo(Controller)) {\r
+ InitializeInstallDiskInfo(ScsiDiskDevice, Controller);\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Controller,\r
+ &gEfiBlockIoProtocolGuid,\r
+ &ScsiDiskDevice->BlkIo,\r
+ &gEfiDiskInfoProtocolGuid,\r
+ &ScsiDiskDevice->DiskInfo,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ ScsiDiskDevice->ControllerNameTable = NULL;\r
+ AddUnicodeString2 (\r
+ "eng",\r
+ gScsiDiskComponentName.SupportedLanguages,\r
+ &ScsiDiskDevice->ControllerNameTable,\r
+ L"SCSI Disk Device",\r
+ TRUE\r
+ );\r
+ AddUnicodeString2 (\r
+ "en",\r
+ gScsiDiskComponentName2.SupportedLanguages,\r
+ &ScsiDiskDevice->ControllerNameTable,\r
+ L"SCSI Disk Device",\r
+ FALSE\r
+ );\r
+ return EFI_SUCCESS;\r
+ }\r
+ } \r
}\r
\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePool (ScsiDiskDevice->SenseData);\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiScsiIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- gBS->FreePool (ScsiDiskDevice);\r
- return Status;\r
- }\r
+ gBS->FreePool (ScsiDiskDevice->SenseData);\r
+ gBS->FreePool (ScsiDiskDevice);\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiScsiIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ return Status;\r
+ \r
+}\r
\r
- ScsiDiskDevice->ControllerNameTable = NULL;\r
- AddUnicodeString2 (\r
- "eng",\r
- gScsiDiskComponentName.SupportedLanguages,\r
- &ScsiDiskDevice->ControllerNameTable,\r
- L"SCSI Disk Device",\r
- TRUE\r
- );\r
- AddUnicodeString2 (\r
- "en",\r
- gScsiDiskComponentName2.SupportedLanguages,\r
- &ScsiDiskDevice->ControllerNameTable,\r
- L"SCSI Disk Device",\r
- FALSE\r
- );\r
\r
+/**\r
+ Stop this driver on ControllerHandle.\r
\r
- return EFI_SUCCESS;\r
+ This service is called by the EFI boot service DisconnectController().\r
+ In order to make drivers as small as possible, there are a few calling\r
+ restrictions for this service. DisconnectController() must follow these\r
+ calling restrictions. If any other agent wishes to call Stop() it must\r
+ also follow these calling restrictions.\r
+ \r
+ @param This Protocol instance pointer.\r
+ @param ControllerHandle Handle of device to stop driver on\r
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
+ children is zero stop the entire bus driver.\r
+ @param ChildHandleBuffer List of Child Handles to Stop.\r
\r
-}\r
+ @retval EFI_SUCCESS This driver is removed ControllerHandle\r
+ @retval other This driver was not removed from this device\r
\r
+**/\r
EFI_STATUS\r
EFIAPI\r
ScsiDiskDriverBindingStop (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE Controller,\r
IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Stop this driver on ControllerHandle. Support stoping any child handles\r
- created by this driver.\r
-\r
-Arguments:\r
-\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to stop driver on\r
- NumberOfChildren - Number of Children in the ChildHandleBuffer\r
- ChildHandleBuffer - List of handles for the children we need to stop.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS\r
- EFI_DEVICE_ERROR\r
- others\r
- \r
---*/\r
{\r
EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
SCSI_DISK_DEV *ScsiDiskDevice;\r
}\r
\r
ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (BlkIo);\r
- Status = gBS->UninstallProtocolInterface (\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
Controller,\r
&gEfiBlockIoProtocolGuid,\r
- &ScsiDiskDevice->BlkIo\r
+ &ScsiDiskDevice->BlkIo,\r
+ &gEfiDiskInfoProtocolGuid,\r
+ &ScsiDiskDevice->DiskInfo,\r
+ NULL\r
);\r
if (!EFI_ERROR (Status)) {\r
gBS->CloseProtocol (\r
return Status;\r
}\r
\r
+/**\r
+ Reset SCSI Disk.\r
+\r
\r
+ @param This The pointer of EFI_BLOCK_IO_PROTOCOL\r
+ @param ExtendedVerification The flag about if extend verificate\r
+\r
+ @retval EFI_SUCCESS The device was reset.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
+ not be reset.\r
+ @return EFI_STATUS is returned from EFI_SCSI_IO_PROTOCOL.ResetDevice().\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
ScsiDiskReset (\r
IN EFI_BLOCK_IO_PROTOCOL *This,\r
IN BOOLEAN ExtendedVerification\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Reset SCSI Disk \r
-\r
-Arguments:\r
-\r
- This - The pointer of EFI_BLOCK_IO_PROTOCOL\r
- ExtendedVerification - The flag about if extend verificate\r
-\r
-Returns:\r
-\r
- EFI_STATUS\r
-\r
---*/\r
{\r
EFI_TPL OldTpl;\r
SCSI_DISK_DEV *ScsiDiskDevice;\r
return Status;\r
}\r
\r
+/**\r
+ The function is to Read Block from SCSI Disk.\r
+\r
+ @param This The pointer of EFI_BLOCK_IO_PROTOCOL.\r
+ @param MediaId The Id of Media detected\r
+ @param Lba The logic block address\r
+ @param BufferSize The size of Buffer\r
+ @param Buffer The buffer to fill the read out data\r
+\r
+ @retval EFI_SUCCESS Successfully to read out block.\r
+ @retval EFI_DEVICE_ERROR Fail to detect media.\r
+ @retval EFI_NO_MEDIA Media is not present.\r
+ @retval EFI_MEDIA_CHANGED Media has changed.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
ScsiDiskReadBlocks (\r
IN EFI_BLOCK_IO_PROTOCOL *This,\r
IN UINT32 MediaId,\r
- IN EFI_LBA LBA,\r
+ IN EFI_LBA Lba,\r
IN UINTN BufferSize,\r
OUT VOID *Buffer\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- The function is to Read Block from SCSI Disk\r
-\r
-Arguments:\r
-\r
- This - The pointer of EFI_BLOCK_IO_PROTOCOL\r
- MediaId - The Id of Media detected\r
- LBA - The logic block address\r
- BufferSize - The size of Buffer\r
- Buffer - The buffer to fill the read out data\r
-\r
-Returns:\r
-\r
- EFI_INVALID_PARAMETER - Invalid parameter passed in.\r
- EFI_SUCCESS - Successfully to read out block.\r
- EFI_DEVICE_ERROR - Fail to detect media.\r
- EFI_NO_MEDIA - Media is not present.\r
- EFI_MEDIA_CHANGED - Media has changed.\r
- EFI_BAD_BUFFER_SIZE - The buffer size is not multiple of BlockSize.\r
-\r
---*/\r
{\r
SCSI_DISK_DEV *ScsiDiskDevice;\r
EFI_BLOCK_IO_MEDIA *Media;\r
EFI_TPL OldTpl;\r
\r
MediaChange = FALSE;\r
- if (!Buffer) {\r
+ if (Buffer == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This);\r
\r
- if (!IsDeviceFixed (ScsiDiskDevice)) {\r
+ if (!IS_DEVICE_FIXED(ScsiDiskDevice)) {\r
\r
Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
\r
- if (LBA > Media->LastBlock) {\r
+ if (Lba > Media->LastBlock) {\r
Status = EFI_INVALID_PARAMETER;\r
goto Done;\r
}\r
\r
- if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {\r
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {\r
Status = EFI_INVALID_PARAMETER;\r
goto Done;\r
}\r
// If all the parameters are valid, then perform read sectors command\r
// to transfer data from device to host.\r
//\r
- Status = ScsiDiskReadSectors (ScsiDiskDevice, Buffer, LBA, NumberOfBlocks);\r
+ Status = ScsiDiskReadSectors (ScsiDiskDevice, Buffer, Lba, NumberOfBlocks);\r
\r
Done:\r
gBS->RestoreTPL (OldTpl);\r
return Status;\r
}\r
\r
+/**\r
+ The function is to Write Block to SCSI Disk.\r
+\r
+ @param This The pointer of EFI_BLOCK_IO_PROTOCOL\r
+ @param MediaId The Id of Media detected\r
+ @param Lba The logic block address\r
+ @param BufferSize The size of Buffer\r
+ @param Buffer The buffer to fill the read out data\r
+\r
+ @retval EFI_SUCCESS Successfully to read out block.\r
+ @retval EFI_WRITE_PROTECTED The device can not be written to.\r
+ @retval EFI_DEVICE_ERROR Fail to detect media.\r
+ @retval EFI_NO_MEDIA Media is not present.\r
+ @retval EFI_MEDIA_CHNAGED Media has changed.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
ScsiDiskWriteBlocks (\r
IN EFI_BLOCK_IO_PROTOCOL *This,\r
IN UINT32 MediaId,\r
- IN EFI_LBA LBA,\r
+ IN EFI_LBA Lba,\r
IN UINTN BufferSize,\r
IN VOID *Buffer\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- The function is to Write Block to SCSI Disk\r
-\r
-Arguments:\r
-\r
- This - The pointer of EFI_BLOCK_IO_PROTOCOL\r
- MediaId - The Id of Media detected\r
- LBA - The logic block address\r
- BufferSize - The size of Buffer\r
- Buffer - The buffer to fill the read out data\r
-\r
-Returns:\r
-\r
- EFI_INVALID_PARAMETER - Invalid parameter passed in.\r
- EFI_SUCCESS - Successfully to read out block.\r
- EFI_DEVICE_ERROR - Fail to detect media.\r
- EFI_NO_MEDIA - Media is not present.\r
- EFI_MEDIA_CHANGED - Media has changed.\r
- EFI_BAD_BUFFER_SIZE - The buffer size is not multiple of BlockSize.\r
-\r
---*/\r
{\r
SCSI_DISK_DEV *ScsiDiskDevice;\r
EFI_BLOCK_IO_MEDIA *Media;\r
EFI_TPL OldTpl;\r
\r
MediaChange = FALSE;\r
- if (!Buffer) {\r
+ if (Buffer == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This);\r
\r
- if (!IsDeviceFixed (ScsiDiskDevice)) {\r
+ if (!IS_DEVICE_FIXED(ScsiDiskDevice)) {\r
\r
Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
\r
- if (LBA > Media->LastBlock) {\r
+ if (Lba > Media->LastBlock) {\r
Status = EFI_INVALID_PARAMETER;\r
goto Done;\r
}\r
\r
- if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {\r
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {\r
Status = EFI_INVALID_PARAMETER;\r
goto Done;\r
}\r
// if all the parameters are valid, then perform read sectors command\r
// to transfer data from device to host.\r
//\r
- Status = ScsiDiskWriteSectors (ScsiDiskDevice, Buffer, LBA, NumberOfBlocks);\r
+ Status = ScsiDiskWriteSectors (ScsiDiskDevice, Buffer, Lba, NumberOfBlocks);\r
\r
Done:\r
gBS->RestoreTPL (OldTpl);\r
return Status;\r
}\r
\r
+/**\r
+ Flush Block to Disk.\r
+\r
+ EFI_SUCCESS is returned directly.\r
+\r
+ @param This The pointer of EFI_BLOCK_IO_PROTOCOL\r
+\r
+ @retval EFI_SUCCESS All outstanding data was written to the device\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
ScsiDiskFlushBlocks (\r
IN EFI_BLOCK_IO_PROTOCOL *This\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Flush Block to Disk\r
-\r
-Arguments:\r
-\r
- This - The pointer of EFI_BLOCK_IO_PROTOCOL\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS \r
-\r
---*/\r
{\r
//\r
// return directly\r
return EFI_SUCCESS;\r
}\r
\r
-EFI_STATUS\r
-ScsiDiskDetectMedia (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- BOOLEAN MustReadCapacity,\r
- BOOLEAN *MediaChange\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Dectect Device and read out capacity ,if error occurs, parse the sense key.\r
\r
-Arguments:\r
-\r
- ScsiDiskDevice - The pointer of SCSI_DISK_DEV\r
- MustReadCapacity - The flag about reading device capacity\r
- MediaChange - The pointer of flag indicates if media has changed \r
+/**\r
+ Detect Device and read out capacity ,if error occurs, parse the sense key.\r
\r
-Returns:\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+ @param MustReadCapacity The flag about reading device capacity\r
+ @param MediaChange The pointer of flag indicates if media has changed \r
\r
- EFI_DEVICE_ERROR - Indicates that error occurs\r
- EFI_SUCCESS - Successfully to detect media\r
+ @retval EFI_DEVICE_ERROR Indicates that error occurs\r
+ @retval EFI_SUCCESS Successfully to detect media\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+ScsiDiskDetectMedia (\r
+ IN SCSI_DISK_DEV *ScsiDiskDevice,\r
+ IN BOOLEAN MustReadCapacity,\r
+ OUT BOOLEAN *MediaChange\r
+ )\r
{\r
EFI_STATUS Status;\r
EFI_STATUS ReadCapacityStatus;\r
return EFI_SUCCESS;\r
}\r
\r
-EFI_STATUS\r
-ScsiDiskInquiryDevice (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- BOOLEAN *NeedRetry\r
- )\r
-/*++\r
-\r
-Routine Description:\r
\r
- Send out Inquiry command to Device\r
-\r
-Arguments:\r
-\r
- ScsiDiskDevice - The pointer of SCSI_DISK_DEV\r
- NeedRetry - Indicates if needs try again when error happens\r
+/**\r
+ Send out Inquiry command to Device.\r
\r
-Returns:\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+ @param NeedRetry Indicates if needs try again when error happens\r
\r
- EFI_DEVICE_ERROR - Indicates that error occurs\r
- EFI_SUCCESS - Successfully to detect media\r
+ @retval EFI_DEVICE_ERROR Indicates that error occurs\r
+ @retval EFI_SUCCESS Successfully to detect media\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+ScsiDiskInquiryDevice (\r
+ IN OUT SCSI_DISK_DEV *ScsiDiskDevice,\r
+ OUT BOOLEAN *NeedRetry\r
+ )\r
{\r
UINT32 InquiryDataLength;\r
UINT8 SenseDataLength;\r
\r
Status = ScsiInquiryCommand (\r
ScsiDiskDevice->ScsiIo,\r
- EFI_SCSI_STALL_SECONDS (1),\r
+ EFI_TIMER_PERIOD_SECONDS (1),\r
NULL,\r
&SenseDataLength,\r
&HostAdapterStatus,\r
}\r
\r
//\r
- // if goes here, meant SubmitInquiryCommand() failed.\r
+ // if goes here, meant ScsiInquiryCommand() failed.\r
// if ScsiDiskRequestSenseKeys() succeeds at last,\r
- // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE)\r
+ // better retry ScsiInquiryCommand(). (by setting *NeedRetry = TRUE)\r
//\r
MaxRetry = 3;\r
for (Index = 0; Index < MaxRetry; Index++) {\r
return EFI_DEVICE_ERROR;\r
}\r
\r
-EFI_STATUS\r
-ScsiDiskTestUnitReady (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- BOOLEAN *NeedRetry,\r
- EFI_SCSI_SENSE_DATA **SenseDataArray,\r
- UINTN *NumberOfSenseKeys\r
- )\r
- /*++\r
-\r
-Routine Description:\r
+/**\r
+ To test device.\r
\r
When Test Unit Ready command succeeds, retrieve Sense Keys via Request Sense;\r
When Test Unit Ready command encounters any error caused by host adapter or\r
target, return error without retrieving Sense Keys.\r
- \r
-Arguments:\r
\r
- ScsiDiskDevice - The pointer of SCSI_DISK_DEV\r
- NeedRetry - The pointer of flag indicates try again\r
- SenseDataArray - The pointer of an array of sense data\r
- NumberOfSenseKeys - The pointer of the number of sense data array\r
- \r
-Returns:\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+ @param NeedRetry The pointer of flag indicates try again\r
+ @param SenseDataArray The pointer of an array of sense data\r
+ @param NumberOfSenseKeys The pointer of the number of sense data array\r
\r
- EFI_DEVICE_ERROR - Indicates that error occurs\r
- EFI_SUCCESS - Successfully to test unit\r
+ @retval EFI_DEVICE_ERROR Indicates that error occurs\r
+ @retval EFI_SUCCESS Successfully to test unit\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+ScsiDiskTestUnitReady (\r
+ IN SCSI_DISK_DEV *ScsiDiskDevice,\r
+ OUT BOOLEAN *NeedRetry,\r
+ OUT EFI_SCSI_SENSE_DATA **SenseDataArray,\r
+ OUT UINTN *NumberOfSenseKeys\r
+ )\r
{\r
EFI_STATUS Status;\r
UINT8 SenseDataLength;\r
//\r
Status = ScsiTestUnitReadyCommand (\r
ScsiDiskDevice->ScsiIo,\r
- EFI_SCSI_STALL_SECONDS (1),\r
+ EFI_TIMER_PERIOD_SECONDS (1),\r
NULL,\r
&SenseDataLength,\r
&HostAdapterStatus,\r
return EFI_DEVICE_ERROR;\r
}\r
\r
-EFI_STATUS\r
-DetectMediaParsingSenseKeys (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- EFI_SCSI_SENSE_DATA *SenseData,\r
- UINTN NumberOfSenseKeys,\r
- UINTN *Action\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
+/**\r
Parsing Sense Keys which got from request sense command.\r
- \r
-Arguments:\r
-\r
- ScsiDiskDevice - The pointer of SCSI_DISK_DEV\r
- SenseData - The pointer of EFI_SCSI_SENSE_DATA\r
- NumberOfSenseKeys - The number of sense key \r
- Action - The pointer of action which indicates what is need to do next\r
\r
-Returns:\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+ @param SenseData The pointer of EFI_SCSI_SENSE_DATA\r
+ @param NumberOfSenseKeys The number of sense key \r
+ @param Action The pointer of action which indicates what is need to do next\r
\r
- EFI_DEVICE_ERROR - Indicates that error occurs\r
- EFI_SUCCESS - Successfully to complete the parsing\r
+ @retval EFI_DEVICE_ERROR Indicates that error occurs\r
+ @retval EFI_SUCCESS Successfully to complete the parsing\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+DetectMediaParsingSenseKeys (\r
+ OUT SCSI_DISK_DEV *ScsiDiskDevice,\r
+ IN EFI_SCSI_SENSE_DATA *SenseData,\r
+ IN UINTN NumberOfSenseKeys,\r
+ OUT UINTN *Action\r
+ )\r
{\r
BOOLEAN RetryLater;\r
\r
return EFI_SUCCESS;\r
}\r
\r
-EFI_STATUS\r
-ScsiDiskReadCapacity (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- BOOLEAN *NeedRetry,\r
- EFI_SCSI_SENSE_DATA **SenseDataArray,\r
- UINTN *NumberOfSenseKeys\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Send read capacity command to device and get the device parameter\r
-\r
-Arguments:\r
\r
- ScsiDiskDevice - The pointer of SCSI_DISK_DEV\r
- NeedRetry - The pointer of flag indicates if need a retry\r
- SenseDataArray - The pointer of an array of sense data\r
- NumberOfSenseKeys - The number of sense key\r
+/**\r
+ Send read capacity command to device and get the device parameter.\r
\r
-Returns:\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+ @param NeedRetry The pointer of flag indicates if need a retry\r
+ @param SenseDataArray The pointer of an array of sense data\r
+ @param NumberOfSenseKeys The number of sense key\r
\r
- EFI_DEVICE_ERROR - Indicates that error occurs\r
- EFI_SUCCESS - Successfully to read capacity\r
+ @retval EFI_DEVICE_ERROR Indicates that error occurs\r
+ @retval EFI_SUCCESS Successfully to read capacity\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+ScsiDiskReadCapacity (\r
+ IN OUT SCSI_DISK_DEV *ScsiDiskDevice,\r
+ OUT BOOLEAN *NeedRetry,\r
+ OUT EFI_SCSI_SENSE_DATA **SenseDataArray,\r
+ OUT UINTN *NumberOfSenseKeys\r
+ )\r
{\r
- EFI_SCSI_DISK_CAPACITY_DATA CapacityData;\r
- UINT32 DataLength;\r
- UINT8 HostAdapterStatus;\r
- UINT8 TargetStatus;\r
- EFI_STATUS CommandStatus;\r
- EFI_STATUS Status;\r
- UINT8 Index;\r
- UINT8 MaxRetry;\r
- UINT8 SenseDataLength;\r
-\r
- SenseDataLength = 0;\r
- ZeroMem (&CapacityData, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));\r
- DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);\r
+ UINT8 HostAdapterStatus;\r
+ UINT8 TargetStatus;\r
+ EFI_STATUS CommandStatus;\r
+ EFI_STATUS Status;\r
+ UINT8 Index;\r
+ UINT8 MaxRetry;\r
+ UINT8 SenseDataLength;\r
+ UINT8 ScsiVersion;\r
+ UINT32 DataLength10;\r
+ UINT32 DataLength16;\r
+ EFI_SCSI_DISK_CAPACITY_DATA CapacityData10;\r
+ EFI_SCSI_DISK_CAPACITY_DATA16 CapacityData16;\r
+\r
+\r
+ SenseDataLength = 0;\r
+ DataLength10 = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);\r
+ DataLength16 = sizeof (EFI_SCSI_DISK_CAPACITY_DATA16);\r
+ ZeroMem (&CapacityData10, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));\r
+ ZeroMem (&CapacityData16, sizeof (EFI_SCSI_DISK_CAPACITY_DATA16));\r
\r
*NumberOfSenseKeys = 0;\r
*NeedRetry = FALSE;\r
- //\r
- // submit Read Capacity Command. in this call,not request sense data\r
- //\r
- CommandStatus = ScsiReadCapacityCommand (\r
- ScsiDiskDevice->ScsiIo,\r
- EFI_SCSI_STALL_SECONDS (1),\r
- NULL,\r
- &SenseDataLength,\r
- &HostAdapterStatus,\r
- &TargetStatus,\r
- (VOID *) &CapacityData,\r
- &DataLength,\r
- FALSE\r
- );\r
- //\r
+ ScsiVersion = (UINT8)(ScsiDiskDevice->InquiryData.Version & 0x03);\r
+\r
+ if (ScsiVersion < SCSI_COMMAND_VERSION_3) {\r
+ //\r
+ // submit Read Capacity(10) Command. in this call,not request sense data\r
+ //\r
+ CommandStatus = ScsiReadCapacityCommand (\r
+ ScsiDiskDevice->ScsiIo,\r
+ EFI_TIMER_PERIOD_SECONDS(1),\r
+ NULL,\r
+ &SenseDataLength,\r
+ &HostAdapterStatus,\r
+ &TargetStatus,\r
+ (VOID *) &CapacityData10,\r
+ &DataLength10,\r
+ FALSE\r
+ );\r
+ } else {\r
+ //\r
+ // submit Read Capacity(16) Command to get parameter LogicalBlocksPerPhysicalBlock\r
+ // and LowestAlignedLba\r
+ //\r
+ CommandStatus = ScsiReadCapacity16Command (\r
+ ScsiDiskDevice->ScsiIo,\r
+ EFI_TIMER_PERIOD_SECONDS (1),\r
+ NULL,\r
+ &SenseDataLength,\r
+ &HostAdapterStatus,\r
+ &TargetStatus,\r
+ (VOID *) &CapacityData16,\r
+ &DataLength16,\r
+ FALSE\r
+ );\r
+ }\r
+ //\r
// no need to check HostAdapterStatus and TargetStatus\r
//\r
if (CommandStatus == EFI_SUCCESS) {\r
- GetMediaInfo (ScsiDiskDevice, &CapacityData);\r
+ GetMediaInfo (ScsiDiskDevice, &CapacityData10,&CapacityData16);\r
return EFI_SUCCESS;\r
\r
} else if (CommandStatus == EFI_NOT_READY) {\r
}\r
\r
//\r
- // if goes here, meant SubmitReadCapacityCommand() failed.\r
+ // if goes here, meant ScsiReadCapacityCommand() failed.\r
// if ScsiDiskRequestSenseKeys() succeeds at last,\r
- // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE)\r
+ // better retry ScsiReadCapacityCommand(). (by setting *NeedRetry = TRUE)\r
//\r
MaxRetry = 3;\r
for (Index = 0; Index < MaxRetry; Index++) {\r
return EFI_DEVICE_ERROR;\r
}\r
\r
-EFI_STATUS\r
-CheckHostAdapterStatus (\r
- UINT8 HostAdapterStatus\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check the HostAdapter status\r
- \r
-Arguments:\r
-\r
- HostAdapterStatus - Host Adapter status\r
+/**\r
+ Check the HostAdapter status and re-interpret it in EFI_STATUS.\r
\r
-Returns:\r
+ @param HostAdapterStatus Host Adapter status\r
\r
- EFI_SUCCESS \r
- EFI_TIMEOUT \r
- EFI_NOT_READY \r
- EFI_DEVICE_ERROR \r
+ @retval EFI_SUCCESS Host adapter is OK.\r
+ @retval EFI_TIMEOUT Timeout.\r
+ @retval EFI_NOT_READY Adapter NOT ready.\r
+ @retval EFI_DEVICE_ERROR Adapter device error.\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+CheckHostAdapterStatus (\r
+ IN UINT8 HostAdapterStatus\r
+ )\r
{\r
switch (HostAdapterStatus) {\r
case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK:\r
}\r
}\r
\r
-EFI_STATUS\r
-CheckTargetStatus (\r
- UINT8 TargetStatus\r
- )\r
-/*++\r
-\r
-Routine Description:\r
\r
- Check the target status\r
- \r
-Arguments:\r
-\r
- TargetStatus - Target status\r
+/**\r
+ Check the target status and re-interpret it in EFI_STATUS.\r
\r
-Returns:\r
+ @param TargetStatus Target status\r
\r
- EFI_NOT_READY \r
- EFI_DEVICE_ERROR \r
- EFI_SUCCESS\r
+ @retval EFI_NOT_READY Device is NOT ready.\r
+ @retval EFI_DEVICE_ERROR \r
+ @retval EFI_SUCCESS\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+CheckTargetStatus (\r
+ IN UINT8 TargetStatus\r
+ )\r
{\r
switch (TargetStatus) {\r
case EFI_EXT_SCSI_STATUS_TARGET_GOOD:\r
}\r
}\r
\r
-EFI_STATUS\r
-ScsiDiskRequestSenseKeys (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- BOOLEAN *NeedRetry,\r
- EFI_SCSI_SENSE_DATA **SenseDataArray,\r
- UINTN *NumberOfSenseKeys,\r
- BOOLEAN AskResetIfError\r
- )\r
-/*++\r
-\r
-Routine Description:\r
\r
+/**\r
Retrieve all sense keys from the device.\r
- When encountering error during the process,\r
- if retrieve sense keys before error encounterred,\r
- return the sense keys with return status set to EFI_SUCCESS,\r
- and NeedRetry set to FALSE; otherwize, return the proper return\r
- status.\r
-\r
-Arguments:\r
-\r
- ScsiDiskDevice - The pointer of SCSI_DISK_DEV\r
- NeedRetry - The pointer of flag indicates if need a retry\r
- SenseDataArray - The pointer of an array of sense data\r
- NumberOfSenseKeys - The number of sense key\r
- AskResetIfError - The flag indicates if need reset when error occurs\r
- \r
-Returns:\r
\r
- EFI_DEVICE_ERROR - Indicates that error occurs\r
- EFI_SUCCESS - Successfully to request sense key\r
+ When encountering error during the process, if retrieve sense keys before\r
+ error encountered, it returns the sense keys with return status set to EFI_SUCCESS,\r
+ and NeedRetry set to FALSE; otherwize, return the proper return status.\r
+\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+ @param NeedRetry The pointer of flag indicates if need a retry\r
+ @param SenseDataArray The pointer of an array of sense data\r
+ @param NumberOfSenseKeys The number of sense key\r
+ @param AskResetIfError The flag indicates if need reset when error occurs\r
\r
---*/\r
+ @retval EFI_DEVICE_ERROR Indicates that error occurs\r
+ @retval EFI_SUCCESS Successfully to request sense key\r
+\r
+**/\r
+EFI_STATUS\r
+ScsiDiskRequestSenseKeys (\r
+ IN OUT SCSI_DISK_DEV *ScsiDiskDevice,\r
+ OUT BOOLEAN *NeedRetry,\r
+ OUT EFI_SCSI_SENSE_DATA **SenseDataArray,\r
+ OUT UINTN *NumberOfSenseKeys,\r
+ IN BOOLEAN AskResetIfError\r
+ )\r
{\r
EFI_SCSI_SENSE_DATA *PtrSenseData;\r
UINT8 SenseDataLength;\r
for (SenseReq = TRUE; SenseReq;) {\r
Status = ScsiRequestSenseCommand (\r
ScsiDiskDevice->ScsiIo,\r
- EFI_SCSI_STALL_SECONDS (2),\r
+ EFI_TIMER_PERIOD_SECONDS (2),\r
PtrSenseData,\r
&SenseDataLength,\r
&HostAdapterStatus,\r
return EFI_SUCCESS;\r
}\r
\r
+\r
+/**\r
+ Get information from media read capacity command.\r
+\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+ @param Capacity10 The pointer of EFI_SCSI_DISK_CAPACITY_DATA\r
+ @param Capacity16 The pointer of EFI_SCSI_DISK_CAPACITY_DATA16\r
+\r
+**/\r
VOID\r
GetMediaInfo (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- EFI_SCSI_DISK_CAPACITY_DATA *Capacity\r
+ IN OUT SCSI_DISK_DEV *ScsiDiskDevice,\r
+ IN EFI_SCSI_DISK_CAPACITY_DATA *Capacity10,\r
+ IN EFI_SCSI_DISK_CAPACITY_DATA16 *Capacity16\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get information from media read capacity command\r
+{\r
+ UINT8 ScsiVersion;\r
+ UINT8 *Ptr;\r
\r
-Arguments:\r
+ ScsiVersion = (UINT8)(ScsiDiskDevice->InquiryData.Version & 0x03);\r
+ ScsiDiskDevice->BlkIo.Media->LowestAlignedLba = 0;\r
+ ScsiDiskDevice->BlkIo.Media->LogicalBlocksPerPhysicalBlock = 1;\r
+ \r
\r
- ScsiDiskDevice - The pointer of SCSI_DISK_DEV\r
- Capacity - The pointer of EFI_SCSI_DISK_CAPACITY_DATA\r
+ if (ScsiVersion < SCSI_COMMAND_VERSION_3) {\r
+ ScsiDiskDevice->BlkIo.Media->LastBlock = (Capacity10->LastLba3 << 24) |\r
+ (Capacity10->LastLba2 << 16) |\r
+ (Capacity10->LastLba1 << 8) |\r
+ Capacity10->LastLba0;\r
+ \r
+ ScsiDiskDevice->BlkIo.Media->BlockSize = (Capacity10->BlockSize3 << 24) |\r
+ (Capacity10->BlockSize2 << 16) | \r
+ (Capacity10->BlockSize1 << 8) |\r
+ Capacity10->BlockSize0;\r
+ ScsiDiskDevice->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; \r
+ } else {\r
\r
-Returns:\r
+ Ptr = (UINT8*)&ScsiDiskDevice->BlkIo.Media->LastBlock;\r
+ *Ptr++ = Capacity16->LastLba0;\r
+ *Ptr++ = Capacity16->LastLba1;\r
+ *Ptr++ = Capacity16->LastLba2;\r
+ *Ptr++ = Capacity16->LastLba3;\r
+ *Ptr++ = Capacity16->LastLba4;\r
+ *Ptr++ = Capacity16->LastLba5;\r
+ *Ptr++ = Capacity16->LastLba6;\r
+ *Ptr = Capacity16->LastLba7;\r
+ \r
+ ScsiDiskDevice->BlkIo.Media->BlockSize = (Capacity16->BlockSize3 << 24) |\r
+ (Capacity16->BlockSize2 << 16) | \r
+ (Capacity16->BlockSize1 << 8) |\r
+ Capacity16->BlockSize0;\r
\r
- NONE\r
+ ScsiDiskDevice->BlkIo.Media->LowestAlignedLba = (Capacity16->LowestAlignLogic2 << 8)|(Capacity16->LowestAlignLogic1);\r
+ ScsiDiskDevice->BlkIo.Media->LogicalBlocksPerPhysicalBlock = Capacity16->LogicPerPhysical;\r
+ ScsiDiskDevice->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2; \r
+ }\r
\r
---*/\r
-{\r
- ScsiDiskDevice->BlkIo.Media->LastBlock = (Capacity->LastLba3 << 24) |\r
- (Capacity->LastLba2 << 16) |\r
- (Capacity->LastLba1 << 8) |\r
- Capacity->LastLba0;\r
\r
ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;\r
- ScsiDiskDevice->BlkIo.Media->BlockSize = (Capacity->BlockSize3 << 24) |\r
- (Capacity->BlockSize2 << 16) | \r
- (Capacity->BlockSize1 << 8) |\r
- Capacity->BlockSize0;\r
+ \r
if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_DISK) {\r
ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200;\r
}\r
}\r
}\r
\r
+/**\r
+ Parse Inquiry data.\r
+\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+\r
+**/\r
VOID\r
ParseInquiryData (\r
- SCSI_DISK_DEV *ScsiDiskDevice\r
+ IN OUT SCSI_DISK_DEV *ScsiDiskDevice\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Parse Inquiry data\r
-\r
-Arguments:\r
-\r
- ScsiDiskDevice - The pointer of SCSI_DISK_DEV\r
-\r
-Returns:\r
-\r
- NONE\r
-\r
---*/\r
{\r
- ScsiDiskDevice->FixedDevice = (BOOLEAN) (ScsiDiskDevice->InquiryData.RMB ? 0 : 1);\r
+ ScsiDiskDevice->FixedDevice = (BOOLEAN) ((ScsiDiskDevice->InquiryData.Rmb == 1) ? 0 : 1);\r
ScsiDiskDevice->BlkIoMedia.RemovableMedia = (BOOLEAN) (!ScsiDiskDevice->FixedDevice);\r
}\r
\r
-EFI_STATUS\r
-EFIAPI\r
-ScsiDiskReadSectors (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- VOID *Buffer,\r
- EFI_LBA Lba,\r
- UINTN NumberOfBlocks\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Read sector from SCSI Disk\r
-\r
-Arguments:\r
-\r
- ScsiDiskDevice - The poiniter of SCSI_DISK_DEV\r
- Buffer - The buffer to fill in the read out data\r
- Lba - Logic block address\r
- NumberOfBlocks - The number of blocks to read\r
+/**\r
+ Read sector from SCSI Disk.\r
\r
-Returns:\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+ @param Buffer The buffer to fill in the read out data\r
+ @param Lba Logic block address\r
+ @param NumberOfBlocks The number of blocks to read\r
\r
- EFI_DEVICE_ERROR\r
- EFI_SUCCESS\r
+ @retval EFI_DEVICE_ERROR Indicates a device error.\r
+ @retval EFI_SUCCESS Operation is successful.\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+ScsiDiskReadSectors (\r
+ IN SCSI_DISK_DEV *ScsiDiskDevice,\r
+ OUT VOID *Buffer,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN NumberOfBlocks\r
+ )\r
{\r
UINTN BlocksRemaining;\r
- UINT32 Lba32;\r
UINT8 *PtrBuffer;\r
UINT32 BlockSize;\r
UINT32 ByteCount;\r
BOOLEAN NeedRetry;\r
EFI_SCSI_SENSE_DATA *SenseData;\r
UINTN NumberOfSenseKeys;\r
+ UINT8 ScsiVersion;\r
\r
SenseData = NULL;\r
NumberOfSenseKeys = 0;\r
\r
BlocksRemaining = NumberOfBlocks;\r
BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize;\r
+ ScsiVersion = (UINT8)(ScsiDiskDevice->InquiryData.Version & 0x03);\r
+ \r
//\r
- // limit the data bytes that can be transferred by one Read(10) Command\r
+ // limit the data bytes that can be transferred by one Read(10) or Read(16) Command\r
//\r
- MaxBlock = 65536;\r
+ if (ScsiVersion < SCSI_COMMAND_VERSION_3) {\r
+ MaxBlock = 65535;\r
+ } else {\r
+ MaxBlock = 4294967295;\r
+ }\r
\r
PtrBuffer = Buffer;\r
- Lba32 = (UINT32) Lba;\r
\r
while (BlocksRemaining > 0) {\r
\r
if (BlocksRemaining <= MaxBlock) {\r
-\r
- SectorCount = (UINT16) BlocksRemaining;\r
+ if (ScsiVersion < SCSI_COMMAND_VERSION_3) {\r
+ SectorCount = (UINT16) BlocksRemaining;\r
+ } else {\r
+ SectorCount = (UINT32) BlocksRemaining;\r
+ }\r
} else {\r
-\r
SectorCount = MaxBlock;\r
}\r
\r
ByteCount = SectorCount * BlockSize;\r
- Timeout = EFI_SCSI_STALL_SECONDS (2);\r
+ Timeout = EFI_TIMER_PERIOD_SECONDS (2);\r
\r
MaxRetry = 2;\r
for (Index = 0; Index < MaxRetry; Index++) {\r
-\r
- Status = ScsiDiskRead10 (\r
- ScsiDiskDevice,\r
- &NeedRetry,\r
- &SenseData,\r
- &NumberOfSenseKeys,\r
- Timeout,\r
- PtrBuffer,\r
- &ByteCount,\r
- Lba32,\r
- SectorCount\r
- );\r
+ if (ScsiVersion >= SCSI_COMMAND_VERSION_3) {\r
+ Status = ScsiDiskRead16 (\r
+ ScsiDiskDevice,\r
+ &NeedRetry,\r
+ &SenseData,\r
+ &NumberOfSenseKeys,\r
+ Timeout,\r
+ PtrBuffer,\r
+ &ByteCount,\r
+ Lba,\r
+ SectorCount\r
+ );\r
+ } else {\r
+ Status = ScsiDiskRead10 (\r
+ ScsiDiskDevice,\r
+ &NeedRetry,\r
+ &SenseData,\r
+ &NumberOfSenseKeys,\r
+ Timeout,\r
+ PtrBuffer,\r
+ &ByteCount,\r
+ (UINT32) Lba,\r
+ SectorCount\r
+ );\r
+ }\r
if (!EFI_ERROR (Status)) {\r
break;\r
}\r
//\r
SectorCount = ByteCount / BlockSize;\r
\r
- Lba32 += SectorCount;\r
+ Lba += SectorCount;\r
PtrBuffer = PtrBuffer + SectorCount * BlockSize;\r
BlocksRemaining -= SectorCount;\r
}\r
return EFI_SUCCESS;\r
}\r
\r
-EFI_STATUS\r
-ScsiDiskWriteSectors (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- VOID *Buffer,\r
- EFI_LBA Lba,\r
- UINTN NumberOfBlocks\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Write SCSI Disk sectors\r
-\r
-Arguments:\r
-\r
- ScsiDiskDevice - The pointer of SCSI_DISK_DEV\r
- Buffer - The data buffer to write sector\r
- Lba - Logic block address\r
- NumberOfBlocks - The number of blocks to write\r
+/**\r
+ Write sector to SCSI Disk.\r
\r
-Returns:\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+ @param Buffer The buffer of data to be written into SCSI Disk\r
+ @param Lba Logic block address\r
+ @param NumberOfBlocks The number of blocks to read\r
\r
- EFI_DEVICE_ERROR \r
- EFI_SUCCESS\r
+ @retval EFI_DEVICE_ERROR Indicates a device error.\r
+ @retval EFI_SUCCESS Operation is successful.\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+ScsiDiskWriteSectors (\r
+ IN SCSI_DISK_DEV *ScsiDiskDevice,\r
+ IN VOID *Buffer,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN NumberOfBlocks\r
+ )\r
{\r
UINTN BlocksRemaining;\r
- UINT32 Lba32;\r
UINT8 *PtrBuffer;\r
UINT32 BlockSize;\r
UINT32 ByteCount;\r
BOOLEAN NeedRetry;\r
EFI_SCSI_SENSE_DATA *SenseData;\r
UINTN NumberOfSenseKeys;\r
+ UINT8 ScsiVersion;\r
\r
SenseData = NULL;\r
NumberOfSenseKeys = 0;\r
\r
BlocksRemaining = NumberOfBlocks;\r
BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize;\r
+ ScsiVersion = (UINT8)(ScsiDiskDevice->InquiryData.Version & 0x03);\r
+\r
//\r
- // limit the data bytes that can be transferred by one Write(10) Command\r
+ // limit the data bytes that can be transferred by one Read(10) or Read(16) Command\r
//\r
- MaxBlock = 65536;\r
+ if (ScsiVersion < SCSI_COMMAND_VERSION_3) {\r
+ MaxBlock = 65535;\r
+ } else {\r
+ MaxBlock = 4294967295;\r
+ }\r
\r
PtrBuffer = Buffer;\r
- Lba32 = (UINT32) Lba;\r
\r
while (BlocksRemaining > 0) {\r
\r
if (BlocksRemaining <= MaxBlock) {\r
-\r
- SectorCount = (UINT16) BlocksRemaining;\r
+ if (ScsiVersion < SCSI_COMMAND_VERSION_3) {\r
+ SectorCount = (UINT16) BlocksRemaining;\r
+ } else {\r
+ SectorCount = (UINT32) BlocksRemaining;\r
+ }\r
} else {\r
-\r
SectorCount = MaxBlock;\r
}\r
\r
ByteCount = SectorCount * BlockSize;\r
- Timeout = EFI_SCSI_STALL_SECONDS (2);\r
+ Timeout = EFI_TIMER_PERIOD_SECONDS (2);\r
MaxRetry = 2;\r
for (Index = 0; Index < MaxRetry; Index++) {\r
- Status = ScsiDiskWrite10 (\r
- ScsiDiskDevice,\r
- &NeedRetry,\r
- &SenseData,\r
- &NumberOfSenseKeys,\r
- Timeout,\r
- PtrBuffer,\r
- &ByteCount,\r
- Lba32,\r
- SectorCount\r
- );\r
+ if (ScsiVersion >= SCSI_COMMAND_VERSION_3) {\r
+ Status = ScsiDiskWrite16 (\r
+ ScsiDiskDevice,\r
+ &NeedRetry,\r
+ &SenseData,\r
+ &NumberOfSenseKeys,\r
+ Timeout,\r
+ PtrBuffer,\r
+ &ByteCount,\r
+ Lba,\r
+ SectorCount\r
+ ); \r
+ } else {\r
+ Status = ScsiDiskWrite10 (\r
+ ScsiDiskDevice,\r
+ &NeedRetry,\r
+ &SenseData,\r
+ &NumberOfSenseKeys,\r
+ Timeout,\r
+ PtrBuffer,\r
+ &ByteCount,\r
+ (UINT32) Lba,\r
+ SectorCount\r
+ );\r
+ }\r
if (!EFI_ERROR (Status)) {\r
break;\r
}\r
//\r
SectorCount = ByteCount / BlockSize;\r
\r
- Lba32 += SectorCount;\r
+ Lba += SectorCount;\r
PtrBuffer = PtrBuffer + SectorCount * BlockSize;\r
BlocksRemaining -= SectorCount;\r
}\r
return EFI_SUCCESS;\r
}\r
\r
+\r
+/**\r
+ Submit Read(10) command.\r
+\r
+ @param ScsiDiskDevice The pointer of ScsiDiskDevice\r
+ @param NeedRetry The pointer of flag indicates if needs retry if error happens\r
+ @param SenseDataArray NOT used yet in this function\r
+ @param NumberOfSenseKeys The number of sense key\r
+ @param Timeout The time to complete the command\r
+ @param DataBuffer The buffer to fill with the read out data\r
+ @param DataLength The length of buffer\r
+ @param StartLba The start logic block address\r
+ @param SectorSize The size of sector\r
+\r
+ @return EFI_STATUS is returned by calling ScsiRead10Command().\r
+**/\r
EFI_STATUS\r
ScsiDiskRead10 (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- BOOLEAN *NeedRetry,\r
- EFI_SCSI_SENSE_DATA **SenseDataArray,\r
- UINTN *NumberOfSenseKeys,\r
- UINT64 Timeout,\r
- UINT8 *DataBuffer,\r
- UINT32 *DataLength,\r
- UINT32 StartLba,\r
- UINT32 SectorSize\r
+ IN SCSI_DISK_DEV *ScsiDiskDevice,\r
+ OUT BOOLEAN *NeedRetry,\r
+ OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL\r
+ OUT UINTN *NumberOfSenseKeys,\r
+ IN UINT64 Timeout,\r
+ OUT UINT8 *DataBuffer,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT32 StartLba,\r
+ IN UINT32 SectorSize\r
)\r
-/*++\r
+{\r
+ UINT8 SenseDataLength;\r
+ EFI_STATUS Status;\r
+ UINT8 HostAdapterStatus;\r
+ UINT8 TargetStatus;\r
\r
-Routine Description:\r
+ *NeedRetry = FALSE;\r
+ *NumberOfSenseKeys = 0;\r
+ SenseDataLength = 0;\r
+ Status = ScsiRead10Command (\r
+ ScsiDiskDevice->ScsiIo,\r
+ Timeout,\r
+ NULL,\r
+ &SenseDataLength,\r
+ &HostAdapterStatus,\r
+ &TargetStatus,\r
+ DataBuffer,\r
+ DataLength,\r
+ StartLba,\r
+ SectorSize\r
+ );\r
+ return Status;\r
+}\r
\r
- Sumbmit Read command \r
\r
-Arguments:\r
+/**\r
+ Submit Write(10) Command.\r
\r
- ScsiDiskDevice - The pointer of ScsiDiskDevice\r
- NeedRetry - The pointer of flag indicates if needs retry if error happens\r
- SenseDataArray - The pointer of an array of sense data\r
- NumberOfSenseKeys - The number of sense key\r
- Timeout - The time to complete the command\r
- DataBuffer - The buffer to fill with the read out data\r
- DataLength - The length of buffer\r
- StartLba - The start logic block address\r
- SectorSize - The size of sector\r
+ @param ScsiDiskDevice The pointer of ScsiDiskDevice\r
+ @param NeedRetry The pointer of flag indicates if needs retry if error happens\r
+ @param SenseDataArray NOT used yet in this function\r
+ @param NumberOfSenseKeys The number of sense key\r
+ @param Timeout The time to complete the command\r
+ @param DataBuffer The buffer to fill with the read out data\r
+ @param DataLength The length of buffer\r
+ @param StartLba The start logic block address\r
+ @param SectorSize The size of sector\r
\r
-Returns:\r
+ @return EFI_STATUS is returned by calling ScsiWrite10Command().\r
\r
- EFI_STATUS\r
- \r
---*/\r
+**/\r
+EFI_STATUS\r
+ScsiDiskWrite10 (\r
+ IN SCSI_DISK_DEV *ScsiDiskDevice,\r
+ OUT BOOLEAN *NeedRetry,\r
+ OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL\r
+ OUT UINTN *NumberOfSenseKeys,\r
+ IN UINT64 Timeout,\r
+ IN UINT8 *DataBuffer,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT32 StartLba,\r
+ IN UINT32 SectorSize\r
+ )\r
{\r
- UINT8 SenseDataLength;\r
EFI_STATUS Status;\r
+ UINT8 SenseDataLength;\r
UINT8 HostAdapterStatus;\r
UINT8 TargetStatus;\r
\r
*NeedRetry = FALSE;\r
*NumberOfSenseKeys = 0;\r
SenseDataLength = 0;\r
- Status = ScsiRead10Command (\r
+ Status = ScsiWrite10Command (\r
ScsiDiskDevice->ScsiIo,\r
Timeout,\r
NULL,\r
return Status;\r
}\r
\r
+\r
+/**\r
+ Submit Read(16) command.\r
+\r
+ @param ScsiDiskDevice The pointer of ScsiDiskDevice\r
+ @param NeedRetry The pointer of flag indicates if needs retry if error happens\r
+ @param SenseDataArray NOT used yet in this function\r
+ @param NumberOfSenseKeys The number of sense key\r
+ @param Timeout The time to complete the command\r
+ @param DataBuffer The buffer to fill with the read out data\r
+ @param DataLength The length of buffer\r
+ @param StartLba The start logic block address\r
+ @param SectorSize The size of sector\r
+\r
+ @return EFI_STATUS is returned by calling ScsiRead10Command().\r
+**/\r
EFI_STATUS\r
-ScsiDiskWrite10 (\r
- SCSI_DISK_DEV *ScsiDiskDevice,\r
- BOOLEAN *NeedRetry,\r
- EFI_SCSI_SENSE_DATA **SenseDataArray,\r
- UINTN *NumberOfSenseKeys,\r
- UINT64 Timeout,\r
- UINT8 *DataBuffer,\r
- UINT32 *DataLength,\r
- UINT32 StartLba,\r
- UINT32 SectorSize\r
+ScsiDiskRead16 (\r
+ IN SCSI_DISK_DEV *ScsiDiskDevice,\r
+ OUT BOOLEAN *NeedRetry,\r
+ OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL\r
+ OUT UINTN *NumberOfSenseKeys,\r
+ IN UINT64 Timeout,\r
+ OUT UINT8 *DataBuffer,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT64 StartLba,\r
+ IN UINT32 SectorSize\r
)\r
-/*++\r
-\r
-Routine Description:\r
+{\r
+ UINT8 SenseDataLength;\r
+ EFI_STATUS Status;\r
+ UINT8 HostAdapterStatus;\r
+ UINT8 TargetStatus;\r
\r
- Submit Write Command\r
+ *NeedRetry = FALSE;\r
+ *NumberOfSenseKeys = 0;\r
+ SenseDataLength = 0;\r
+ Status = ScsiRead16Command (\r
+ ScsiDiskDevice->ScsiIo,\r
+ Timeout,\r
+ NULL,\r
+ &SenseDataLength,\r
+ &HostAdapterStatus,\r
+ &TargetStatus,\r
+ DataBuffer,\r
+ DataLength,\r
+ StartLba,\r
+ SectorSize\r
+ );\r
+ return Status;\r
+}\r
\r
-Arguments:\r
\r
- ScsiDiskDevice - The pointer of ScsiDiskDevice\r
- NeedRetry - The pointer of flag indicates if needs retry if error happens\r
- SenseDataArray - The pointer of an array of sense data\r
- NumberOfSenseKeys - The number of sense key\r
- Timeout - The time to complete the command\r
- DataBuffer - The buffer to fill with the read out data\r
- DataLength - The length of buffer\r
- StartLba - The start logic block address\r
- SectorSize - The size of sector\r
+/**\r
+ Submit Write(16) Command.\r
\r
-Returns:\r
+ @param ScsiDiskDevice The pointer of ScsiDiskDevice\r
+ @param NeedRetry The pointer of flag indicates if needs retry if error happens\r
+ @param SenseDataArray NOT used yet in this function\r
+ @param NumberOfSenseKeys The number of sense key\r
+ @param Timeout The time to complete the command\r
+ @param DataBuffer The buffer to fill with the read out data\r
+ @param DataLength The length of buffer\r
+ @param StartLba The start logic block address\r
+ @param SectorSize The size of sector\r
\r
- EFI_STATUS\r
+ @return EFI_STATUS is returned by calling ScsiWrite10Command().\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+ScsiDiskWrite16 (\r
+ IN SCSI_DISK_DEV *ScsiDiskDevice,\r
+ OUT BOOLEAN *NeedRetry,\r
+ OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL\r
+ OUT UINTN *NumberOfSenseKeys,\r
+ IN UINT64 Timeout,\r
+ IN UINT8 *DataBuffer,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT64 StartLba,\r
+ IN UINT32 SectorSize\r
+ )\r
{\r
EFI_STATUS Status;\r
UINT8 SenseDataLength;\r
*NeedRetry = FALSE;\r
*NumberOfSenseKeys = 0;\r
SenseDataLength = 0;\r
- Status = ScsiWrite10Command (\r
+ Status = ScsiWrite16Command (\r
ScsiDiskDevice->ScsiIo,\r
Timeout,\r
NULL,\r
return Status;\r
}\r
\r
+\r
+/**\r
+ Check sense key to find if media presents.\r
+\r
+ @param SenseData The pointer of EFI_SCSI_SENSE_DATA\r
+ @param SenseCounts The number of sense key\r
+\r
+ @retval TRUE NOT any media\r
+ @retval FALSE Media presents\r
+**/\r
BOOLEAN\r
ScsiDiskIsNoMedia (\r
IN EFI_SCSI_SENSE_DATA *SenseData,\r
IN UINTN SenseCounts\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check sense key to find if media presents\r
-\r
-Arguments:\r
-\r
- SenseData - The pointer of EFI_SCSI_SENSE_DATA\r
- SenseCounts - The number of sense key\r
-\r
-Returns:\r
-\r
- BOOLEAN\r
-\r
---*/\r
{\r
EFI_SCSI_SENSE_DATA *SensePtr;\r
UINTN Index;\r
return IsNoMedia;\r
}\r
\r
+\r
+/**\r
+ Parse sense key.\r
+\r
+ @param SenseData The pointer of EFI_SCSI_SENSE_DATA\r
+ @param SenseCounts The number of sense key\r
+\r
+ @retval TRUE Error\r
+ @retval FALSE NOT error\r
+\r
+**/\r
BOOLEAN\r
ScsiDiskIsMediaError (\r
IN EFI_SCSI_SENSE_DATA *SenseData,\r
IN UINTN SenseCounts\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Parse sense key\r
-\r
-Arguments:\r
-\r
- SenseData - The pointer of EFI_SCSI_SENSE_DATA\r
- SenseCounts - The number of sense key\r
-\r
-Returns:\r
-\r
- BOOLEAN\r
-\r
---*/\r
{\r
EFI_SCSI_SENSE_DATA *SensePtr;\r
UINTN Index;\r
return IsError;\r
}\r
\r
+\r
+/**\r
+ Check sense key to find if hardware error happens.\r
+\r
+ @param SenseData The pointer of EFI_SCSI_SENSE_DATA\r
+ @param SenseCounts The number of sense key\r
+\r
+ @retval TRUE Hardware error exits.\r
+ @retval FALSE NO error.\r
+\r
+**/\r
BOOLEAN\r
ScsiDiskIsHardwareError (\r
IN EFI_SCSI_SENSE_DATA *SenseData,\r
IN UINTN SenseCounts\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check sense key to find if hardware error happens\r
-\r
-Arguments:\r
-\r
- SenseData - The pointer of EFI_SCSI_SENSE_DATA\r
- SenseCounts - The number of sense key\r
-\r
-Returns:\r
-\r
- BOOLEAN\r
-\r
---*/\r
{\r
EFI_SCSI_SENSE_DATA *SensePtr;\r
UINTN Index;\r
return IsError;\r
}\r
\r
+\r
+/**\r
+ Check sense key to find if media has changed.\r
+\r
+ @param SenseData The pointer of EFI_SCSI_SENSE_DATA\r
+ @param SenseCounts The number of sense key\r
+\r
+ @retval TRUE Media is changed.\r
+ @retval FALSE Media is NOT changed.\r
+**/\r
BOOLEAN\r
ScsiDiskIsMediaChange (\r
IN EFI_SCSI_SENSE_DATA *SenseData,\r
IN UINTN SenseCounts\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check sense key to find if media has changed\r
-\r
-Arguments:\r
-\r
- SenseData - The pointer of EFI_SCSI_SENSE_DATA\r
- SenseCounts - The number of sense key\r
-\r
-Returns:\r
-\r
- BOOLEAN\r
-\r
---*/\r
{\r
EFI_SCSI_SENSE_DATA *SensePtr;\r
UINTN Index;\r
return IsMediaChanged;\r
}\r
\r
+/**\r
+ Check sense key to find if reset happens.\r
+\r
+ @param SenseData The pointer of EFI_SCSI_SENSE_DATA\r
+ @param SenseCounts The number of sense key\r
+\r
+ @retval TRUE It is reset before.\r
+ @retval FALSE It is NOT reset before.\r
+\r
+**/\r
BOOLEAN\r
ScsiDiskIsResetBefore (\r
IN EFI_SCSI_SENSE_DATA *SenseData,\r
IN UINTN SenseCounts\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check sense key to find if reset happens\r
-\r
-Arguments:\r
-\r
- SenseData - The pointer of EFI_SCSI_SENSE_DATA\r
- SenseCounts - The number of sense key\r
-\r
-Returns:\r
-\r
- BOOLEAN\r
-\r
---*/\r
{\r
EFI_SCSI_SENSE_DATA *SensePtr;\r
UINTN Index;\r
return IsResetBefore;\r
}\r
\r
+/**\r
+ Check sense key to find if the drive is ready.\r
+\r
+ @param SenseData The pointer of EFI_SCSI_SENSE_DATA\r
+ @param SenseCounts The number of sense key\r
+ @param RetryLater The flag means if need a retry \r
+\r
+ @retval TRUE Drive is ready.\r
+ @retval FALSE Drive is NOT ready.\r
+\r
+**/\r
BOOLEAN\r
ScsiDiskIsDriveReady (\r
IN EFI_SCSI_SENSE_DATA *SenseData,\r
IN UINTN SenseCounts,\r
OUT BOOLEAN *RetryLater\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check sense key to find if the drive is ready\r
-\r
-Arguments:\r
-\r
- SenseData - The pointer of EFI_SCSI_SENSE_DATA\r
- SenseCounts - The number of sense key\r
- RetryLater - The flag means if need a retry \r
-\r
-Returns:\r
-\r
- BOOLEAN\r
-\r
---*/\r
{\r
EFI_SCSI_SENSE_DATA *SensePtr;\r
UINTN Index;\r
return IsReady;\r
}\r
\r
+/**\r
+ Check sense key to find if it has sense key.\r
+\r
+ @param SenseData - The pointer of EFI_SCSI_SENSE_DATA\r
+ @param SenseCounts - The number of sense key\r
+\r
+ @retval TRUE It has sense key.\r
+ @retval FALSE It has NOT any sense key.\r
+\r
+**/\r
BOOLEAN\r
ScsiDiskHaveSenseKey (\r
IN EFI_SCSI_SENSE_DATA *SenseData,\r
IN UINTN SenseCounts\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check sense key to find if it has sense key\r
-\r
-Arguments:\r
-\r
- SenseData - The pointer of EFI_SCSI_SENSE_DATA\r
- SenseCounts - The number of sense key\r
-\r
-Returns:\r
-\r
- BOOLEAN\r
-\r
---*/\r
{\r
EFI_SCSI_SENSE_DATA *SensePtr;\r
UINTN Index;\r
return HaveSenseKey;\r
}\r
\r
+/**\r
+ Release resource about disk device.\r
+\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+\r
+**/\r
VOID\r
ReleaseScsiDiskDeviceResources (\r
IN SCSI_DISK_DEV *ScsiDiskDevice\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Release resource about disk device\r
-\r
-Arguments:\r
-\r
- ScsiDiskDevice - The pointer of SCSI_DISK_DEV\r
-\r
-Returns:\r
-\r
- NONE\r
-\r
---*/\r
{\r
if (ScsiDiskDevice == NULL) {\r
return ;\r
}\r
\r
if (ScsiDiskDevice->SenseData != NULL) {\r
- gBS->FreePool (ScsiDiskDevice->SenseData);\r
+ FreePool (ScsiDiskDevice->SenseData);\r
ScsiDiskDevice->SenseData = NULL;\r
}\r
\r
ScsiDiskDevice->ControllerNameTable = NULL;\r
}\r
\r
- gBS->FreePool (ScsiDiskDevice);\r
+ FreePool (ScsiDiskDevice);\r
\r
ScsiDiskDevice = NULL;\r
}\r
+\r
+/**\r
+ Determine if Block Io should be produced.\r
+ \r
+\r
+ @param ChildHandle Child Handle to retrieve Parent information.\r
+ \r
+ @retval TRUE Should produce Block Io.\r
+ @retval FALSE Should not produce Block Io.\r
+\r
+**/ \r
+BOOLEAN\r
+DetermineInstallBlockIo (\r
+ IN EFI_HANDLE ChildHandle\r
+ ) \r
+{\r
+ EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;\r
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiPassThru;\r
+\r
+ //\r
+ // Firstly, check if ExtScsiPassThru Protocol parent handle exists. If existence,\r
+ // check its attribute, logic or physical.\r
+ //\r
+ ExtScsiPassThru = (EFI_EXT_SCSI_PASS_THRU_PROTOCOL *)GetParentProtocol (&gEfiExtScsiPassThruProtocolGuid, ChildHandle);\r
+ if (ExtScsiPassThru != NULL) {\r
+ if ((ExtScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL) != 0) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Secondly, check if ScsiPassThru Protocol parent handle exists. If existence,\r
+ // check its attribute, logic or physical.\r
+ //\r
+ ScsiPassThru = (EFI_SCSI_PASS_THRU_PROTOCOL *)GetParentProtocol (&gEfiScsiPassThruProtocolGuid, ChildHandle);\r
+ if (ScsiPassThru != NULL) {\r
+ if ((ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL) != 0) {\r
+ return TRUE;\r
+ }\r
+ }\r
+ \r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Search protocol database and check to see if the protocol\r
+ specified by ProtocolGuid is present on a ControllerHandle and opened by\r
+ ChildHandle with an attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ If the ControllerHandle is found, then the protocol specified by ProtocolGuid\r
+ will be opened on it. \r
+ \r
+\r
+ @param ProtocolGuid ProtocolGuid pointer.\r
+ @param ChildHandle Child Handle to retrieve Parent information.\r
+ \r
+**/ \r
+VOID *\r
+EFIAPI\r
+GetParentProtocol (\r
+ IN EFI_GUID *ProtocolGuid,\r
+ IN EFI_HANDLE ChildHandle\r
+ ) \r
+{\r
+ UINTN Index;\r
+ UINTN HandleCount;\r
+ VOID *Interface; \r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+\r
+ //\r
+ // Retrieve the list of all handles from the handle database\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ ProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Iterate to find who is parent handle that is opened with ProtocolGuid by ChildHandle \r
+ //\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = EfiTestChildHandle (HandleBuffer[Index], ChildHandle, ProtocolGuid);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->HandleProtocol (HandleBuffer[Index], ProtocolGuid, (VOID **)&Interface);\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->FreePool (HandleBuffer);\r
+ return Interface;\r
+ }\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (HandleBuffer);\r
+ return NULL;\r
+} \r
+\r
+/**\r
+ Provides inquiry information for the controller type.\r
+ \r
+ This function is used by the IDE bus driver to get inquiry data. Data format\r
+ of Identify data is defined by the Interface GUID.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
+ @param[in, out] InquiryData Pointer to a buffer for the inquiry data.\r
+ @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size.\r
+\r
+ @retval EFI_SUCCESS The command was accepted without any errors.\r
+ @retval EFI_NOT_FOUND Device does not support this data class \r
+ @retval EFI_DEVICE_ERROR Error reading InquiryData from device \r
+ @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough \r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiDiskInfoInquiry (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ IN OUT VOID *InquiryData,\r
+ IN OUT UINT32 *InquiryDataSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SCSI_DISK_DEV *ScsiDiskDevice;\r
+\r
+ ScsiDiskDevice = SCSI_DISK_DEV_FROM_DISKINFO (This);\r
+\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ if (*InquiryDataSize >= sizeof (ScsiDiskDevice->InquiryData)) {\r
+ Status = EFI_SUCCESS;\r
+ CopyMem (InquiryData, &ScsiDiskDevice->InquiryData, sizeof (ScsiDiskDevice->InquiryData));\r
+ }\r
+ *InquiryDataSize = sizeof (ScsiDiskDevice->InquiryData);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Provides identify information for the controller type.\r
+\r
+ This function is used by the IDE bus driver to get identify data. Data format\r
+ of Identify data is defined by the Interface GUID.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL \r
+ instance.\r
+ @param[in, out] IdentifyData Pointer to a buffer for the identify data.\r
+ @param[in, out] IdentifyDataSize Pointer to the value for the identify data\r
+ size.\r
+\r
+ @retval EFI_SUCCESS The command was accepted without any errors.\r
+ @retval EFI_NOT_FOUND Device does not support this data class \r
+ @retval EFI_DEVICE_ERROR Error reading IdentifyData from device \r
+ @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough \r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiDiskInfoIdentify (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ IN OUT VOID *IdentifyData,\r
+ IN OUT UINT32 *IdentifyDataSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SCSI_DISK_DEV *ScsiDiskDevice;\r
+\r
+ if (CompareGuid (&This->Interface, &gEfiDiskInfoScsiInterfaceGuid)) {\r
+ //\r
+ // Physical SCSI bus does not support this data class. \r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ ScsiDiskDevice = SCSI_DISK_DEV_FROM_DISKINFO (This);\r
+\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ if (*IdentifyDataSize >= sizeof (ScsiDiskDevice->IdentifyData)) {\r
+ Status = EFI_SUCCESS;\r
+ CopyMem (IdentifyData, &ScsiDiskDevice->IdentifyData, sizeof (ScsiDiskDevice->IdentifyData));\r
+ }\r
+ *IdentifyDataSize = sizeof (ScsiDiskDevice->IdentifyData);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Provides sense data information for the controller type.\r
+ \r
+ This function is used by the IDE bus driver to get sense data. \r
+ Data format of Sense data is defined by the Interface GUID.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
+ @param[in, out] SenseData Pointer to the SenseData.\r
+ @param[in, out] SenseDataSize Size of SenseData in bytes.\r
+ @param[out] SenseDataNumber Pointer to the value for the sense data size.\r
+\r
+ @retval EFI_SUCCESS The command was accepted without any errors.\r
+ @retval EFI_NOT_FOUND Device does not support this data class.\r
+ @retval EFI_DEVICE_ERROR Error reading SenseData from device.\r
+ @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiDiskInfoSenseData (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ IN OUT VOID *SenseData,\r
+ IN OUT UINT32 *SenseDataSize,\r
+ OUT UINT8 *SenseDataNumber\r
+ )\r
+{\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ This function is used by the IDE bus driver to get controller information.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. \r
+ @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.\r
+ @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.\r
+\r
+ @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.\r
+ @retval EFI_UNSUPPORTED This is not an IDE device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiDiskInfoWhichIde (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ OUT UINT32 *IdeChannel,\r
+ OUT UINT32 *IdeDevice\r
+ )\r
+{\r
+ SCSI_DISK_DEV *ScsiDiskDevice;\r
+\r
+ if (CompareGuid (&This->Interface, &gEfiDiskInfoScsiInterfaceGuid)) {\r
+ //\r
+ // This is not an IDE physical device.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ ScsiDiskDevice = SCSI_DISK_DEV_FROM_DISKINFO (This);\r
+ *IdeChannel = ScsiDiskDevice->Channel;\r
+ *IdeDevice = ScsiDiskDevice->Device;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Issues ATA IDENTIFY DEVICE command to identify ATAPI device.\r
+\r
+ This function tries to fill 512-byte ATAPI_IDENTIFY_DATA for ATAPI device to\r
+ implement Identify() interface for DiskInfo protocol. The ATA command is sent\r
+ via SCSI Request Packet.\r
+\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV\r
+ \r
+ @retval EFI_SUCCESS The ATAPI device identify data were retrieved successfully.\r
+ @retval others Some error occurred during the identification that ATAPI device.\r
+\r
+**/ \r
+EFI_STATUS\r
+AtapiIdentifyDevice (\r
+ IN OUT SCSI_DISK_DEV *ScsiDiskDevice\r
+ )\r
+{\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ UINT8 Cdb[6];\r
+\r
+ //\r
+ // Initialize SCSI REQUEST_PACKET and 6-byte Cdb\r
+ //\r
+ ZeroMem (&CommandPacket, sizeof (CommandPacket));\r
+ ZeroMem (Cdb, sizeof (Cdb));\r
+\r
+ Cdb[0] = ATA_CMD_IDENTIFY_DEVICE;\r
+ CommandPacket.Timeout = EFI_TIMER_PERIOD_SECONDS (1);\r
+ CommandPacket.Cdb = Cdb;\r
+ CommandPacket.CdbLength = sizeof (Cdb);\r
+ CommandPacket.InDataBuffer = &ScsiDiskDevice->IdentifyData;\r
+ CommandPacket.InTransferLength = sizeof (ScsiDiskDevice->IdentifyData);\r
+\r
+ return ScsiDiskDevice->ScsiIo->ExecuteScsiCommand (ScsiDiskDevice->ScsiIo, &CommandPacket, NULL);\r
+}\r
+\r
+\r
+/**\r
+ Initialize the installation of DiskInfo protocol.\r
+\r
+ This function prepares for the installation of DiskInfo protocol on the child handle.\r
+ By default, it installs DiskInfo protocol with SCSI interface GUID. If it further\r
+ detects that the physical device is an ATAPI/AHCI device, it then updates interface GUID\r
+ to be IDE/AHCI interface GUID.\r
+\r
+ @param ScsiDiskDevice The pointer of SCSI_DISK_DEV.\r
+ @param ChildHandle Child handle to install DiskInfo protocol.\r
+ \r
+**/ \r
+VOID\r
+InitializeInstallDiskInfo (\r
+ IN SCSI_DISK_DEV *ScsiDiskDevice,\r
+ IN EFI_HANDLE ChildHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *ChildDevicePathNode;\r
+ ATAPI_DEVICE_PATH *AtapiDevicePath;\r
+ SATA_DEVICE_PATH *SataDevicePath;\r
+ UINTN IdentifyRetry;\r
+\r
+ Status = gBS->HandleProtocol (ChildHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePathNode);\r
+ //\r
+ // Device Path protocol must be installed on the device handle. \r
+ //\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // Copy the DiskInfo protocol template.\r
+ //\r
+ CopyMem (&ScsiDiskDevice->DiskInfo, &gScsiDiskInfoProtocolTemplate, sizeof (gScsiDiskInfoProtocolTemplate));\r
+\r
+ while (!IsDevicePathEnd (DevicePathNode)) {\r
+ ChildDevicePathNode = NextDevicePathNode (DevicePathNode);\r
+ if ((DevicePathType (DevicePathNode) == HARDWARE_DEVICE_PATH) &&\r
+ (DevicePathSubType (DevicePathNode) == HW_PCI_DP) &&\r
+ (DevicePathType (ChildDevicePathNode) == MESSAGING_DEVICE_PATH) &&\r
+ ((DevicePathSubType (ChildDevicePathNode) == MSG_ATAPI_DP) ||\r
+ (DevicePathSubType (ChildDevicePathNode) == MSG_SATA_DP))) {\r
+\r
+ IdentifyRetry = 3;\r
+ do {\r
+ //\r
+ // Issue ATA Identify Device Command via SCSI command, which is required to publish DiskInfo protocol\r
+ // with IDE/AHCI interface GUID.\r
+ //\r
+ Status = AtapiIdentifyDevice (ScsiDiskDevice);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (DevicePathSubType(ChildDevicePathNode) == MSG_ATAPI_DP) {\r
+ //\r
+ // We find the valid ATAPI device path\r
+ //\r
+ AtapiDevicePath = (ATAPI_DEVICE_PATH *) ChildDevicePathNode;\r
+ ScsiDiskDevice->Channel = AtapiDevicePath->PrimarySecondary;\r
+ ScsiDiskDevice->Device = AtapiDevicePath->SlaveMaster;\r
+ //\r
+ // Update the DiskInfo.Interface to IDE interface GUID for the physical ATAPI device. \r
+ //\r
+ CopyGuid (&ScsiDiskDevice->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid);\r
+ } else {\r
+ //\r
+ // We find the valid SATA device path\r
+ //\r
+ SataDevicePath = (SATA_DEVICE_PATH *) ChildDevicePathNode;\r
+ ScsiDiskDevice->Channel = SataDevicePath->HBAPortNumber;\r
+ ScsiDiskDevice->Device = SataDevicePath->PortMultiplierPortNumber;\r
+ //\r
+ // Update the DiskInfo.Interface to AHCI interface GUID for the physical AHCI device. \r
+ //\r
+ CopyGuid (&ScsiDiskDevice->DiskInfo.Interface, &gEfiDiskInfoAhciInterfaceGuid);\r
+ }\r
+ return;\r
+ }\r
+ } while (--IdentifyRetry > 0);\r
+ }\r
+ DevicePathNode = ChildDevicePathNode;\r
+ }\r
+\r
+ return;\r
+}\r