NULL\r
};\r
\r
+\r
/**\r
The user Entry Point for module ScsiDisk.\r
\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
// Retrieve device information\r
//\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
-\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
+ // Determine if Block IO should be produced on this controller handle\r
+ //\r
+ if (DetermineInstallBlockIo(Controller)) {\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Controller,\r
+ &gEfiBlockIoProtocolGuid,\r
+ &ScsiDiskDevice->BlkIo,\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
- 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
- return EFI_SUCCESS;\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
\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
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_TIMER_PERIOD_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
VOID\r
GetMediaInfo (\r
IN OUT SCSI_DISK_DEV *ScsiDiskDevice,\r
- IN EFI_SCSI_DISK_CAPACITY_DATA *Capacity\r
+ EFI_SCSI_DISK_CAPACITY_DATA *Capacity10,\r
+ EFI_SCSI_DISK_CAPACITY_DATA16 *Capacity16\r
)\r
{\r
- ScsiDiskDevice->BlkIo.Media->LastBlock = (Capacity->LastLba3 << 24) |\r
- (Capacity->LastLba2 << 16) |\r
- (Capacity->LastLba1 << 8) |\r
- Capacity->LastLba0;\r
+ UINT8 ScsiVersion;\r
+ UINT8 *Ptr;\r
+\r
+ ScsiVersion = (UINT8)(ScsiDiskDevice->InquiryData.Version & 0x03);\r
+ ScsiDiskDevice->BlkIo.Media->LowestAlignedLba = 0;\r
+ ScsiDiskDevice->BlkIo.Media->LogicalBlocksPerPhysicalBlock = 1;\r
+ \r
+\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
+ 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
+ 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
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
IN OUT SCSI_DISK_DEV *ScsiDiskDevice\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
}\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 retrive 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