mirror of https://github.com/acidanthera/audk.git
Allocate aligned buffer to satisfy the IoAlign requirement of high level protocol.
Signed-off-by: lzeng14 Reviewed-by: erictian git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12788 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
79d07c66d9
commit
957fe09353
|
@ -129,7 +129,7 @@ FreeAlignedBuffer (
|
|||
)
|
||||
{
|
||||
if (Buffer != NULL) {
|
||||
FreePages (Buffer, EFI_SIZE_TO_PAGES (BufferSize));
|
||||
FreeAlignedPages (Buffer, EFI_SIZE_TO_PAGES (BufferSize));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
SCSI Bus driver that layers on every SCSI Pass Thru and
|
||||
Extended SCSI Pass Thru protocol in the system.
|
||||
|
||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -71,6 +71,49 @@ NotifyFunction (
|
|||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Allocates an aligned buffer for SCSI device.
|
||||
|
||||
This function allocates an aligned buffer for the SCSI device to perform
|
||||
SCSI pass through operations. The alignment requirement is from SCSI pass
|
||||
through interface.
|
||||
|
||||
@param ScsiIoDevice The SCSI child device involved for the operation.
|
||||
@param BufferSize The request buffer size.
|
||||
|
||||
@return A pointer to the aligned buffer or NULL if the allocation fails.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
AllocateAlignedBuffer (
|
||||
IN SCSI_IO_DEV *ScsiIoDevice,
|
||||
IN UINTN BufferSize
|
||||
)
|
||||
{
|
||||
return AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), ScsiIoDevice->ScsiIo.IoAlign);
|
||||
}
|
||||
|
||||
/**
|
||||
Frees an aligned buffer for SCSI device.
|
||||
|
||||
This function frees an aligned buffer for the SCSI device to perform
|
||||
SCSI pass through operations.
|
||||
|
||||
@param Buffer The aligned buffer to be freed.
|
||||
@param BufferSize The request buffer size.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FreeAlignedBuffer (
|
||||
IN VOID *Buffer,
|
||||
IN UINTN BufferSize
|
||||
)
|
||||
{
|
||||
if (Buffer != NULL) {
|
||||
FreeAlignedPages (Buffer, EFI_SIZE_TO_PAGES (BufferSize));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The user Entry Point for module ScsiBus. The user code starts with this function.
|
||||
|
||||
|
@ -1178,30 +1221,37 @@ DiscoverScsiDevice (
|
|||
UINT8 SenseDataLength;
|
||||
UINT8 HostAdapterStatus;
|
||||
UINT8 TargetStatus;
|
||||
EFI_SCSI_SENSE_DATA SenseData;
|
||||
EFI_SCSI_INQUIRY_DATA InquiryData;
|
||||
EFI_SCSI_INQUIRY_DATA *InquiryData;
|
||||
UINT8 MaxRetry;
|
||||
UINT8 Index;
|
||||
BOOLEAN ScsiDeviceFound;
|
||||
|
||||
HostAdapterStatus = 0;
|
||||
TargetStatus = 0;
|
||||
|
||||
InquiryData = AllocateAlignedBuffer (ScsiIoDevice, sizeof (EFI_SCSI_INQUIRY_DATA));
|
||||
if (InquiryData == NULL) {
|
||||
ScsiDeviceFound = FALSE;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Using Inquiry command to scan for the device
|
||||
//
|
||||
InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
|
||||
SenseDataLength = (UINT8) sizeof (EFI_SCSI_SENSE_DATA);
|
||||
ZeroMem (&InquiryData, InquiryDataLength);
|
||||
SenseDataLength = 0;
|
||||
ZeroMem (InquiryData, InquiryDataLength);
|
||||
|
||||
MaxRetry = 2;
|
||||
for (Index = 0; Index < MaxRetry; Index++) {
|
||||
Status = ScsiInquiryCommand (
|
||||
&ScsiIoDevice->ScsiIo,
|
||||
EFI_TIMER_PERIOD_SECONDS (1),
|
||||
(VOID *) &SenseData,
|
||||
NULL,
|
||||
&SenseDataLength,
|
||||
&HostAdapterStatus,
|
||||
&TargetStatus,
|
||||
(VOID *) &InquiryData,
|
||||
(VOID *) InquiryData,
|
||||
&InquiryDataLength,
|
||||
FALSE
|
||||
);
|
||||
|
@ -1210,47 +1260,57 @@ DiscoverScsiDevice (
|
|||
} else if ((Status == EFI_BAD_BUFFER_SIZE) ||
|
||||
(Status == EFI_INVALID_PARAMETER) ||
|
||||
(Status == EFI_UNSUPPORTED)) {
|
||||
return FALSE;
|
||||
ScsiDeviceFound = FALSE;
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
if (Index == MaxRetry) {
|
||||
return FALSE;
|
||||
ScsiDeviceFound = FALSE;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieved inquiry data successfully
|
||||
//
|
||||
if ((InquiryData.Peripheral_Qualifier != 0) &&
|
||||
(InquiryData.Peripheral_Qualifier != 3)) {
|
||||
return FALSE;
|
||||
if ((InquiryData->Peripheral_Qualifier != 0) &&
|
||||
(InquiryData->Peripheral_Qualifier != 3)) {
|
||||
ScsiDeviceFound = FALSE;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (InquiryData.Peripheral_Qualifier == 3) {
|
||||
if (InquiryData.Peripheral_Type != 0x1f) {
|
||||
return FALSE;
|
||||
if (InquiryData->Peripheral_Qualifier == 3) {
|
||||
if (InquiryData->Peripheral_Type != 0x1f) {
|
||||
ScsiDeviceFound = FALSE;
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
if (0x1e >= InquiryData.Peripheral_Type && InquiryData.Peripheral_Type >= 0xa) {
|
||||
return FALSE;
|
||||
if (0x1e >= InquiryData->Peripheral_Type && InquiryData->Peripheral_Type >= 0xa) {
|
||||
ScsiDeviceFound = FALSE;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// valid device type and peripheral qualifier combination.
|
||||
//
|
||||
ScsiIoDevice->ScsiDeviceType = InquiryData.Peripheral_Type;
|
||||
ScsiIoDevice->RemovableDevice = InquiryData.Rmb;
|
||||
if (InquiryData.Version == 0) {
|
||||
ScsiIoDevice->ScsiDeviceType = InquiryData->Peripheral_Type;
|
||||
ScsiIoDevice->RemovableDevice = InquiryData->Rmb;
|
||||
if (InquiryData->Version == 0) {
|
||||
ScsiIoDevice->ScsiVersion = 0;
|
||||
} else {
|
||||
//
|
||||
// ANSI-approved version
|
||||
//
|
||||
ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x07);
|
||||
ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData->Version & 0x07);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
ScsiDeviceFound = TRUE;
|
||||
|
||||
Done:
|
||||
FreeAlignedBuffer (InquiryData, sizeof (EFI_SCSI_INQUIRY_DATA));
|
||||
|
||||
return ScsiDeviceFound;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,48 @@ EFI_DISK_INFO_PROTOCOL gScsiDiskInfoProtocolTemplate = {
|
|||
ScsiDiskInfoWhichIde
|
||||
};
|
||||
|
||||
/**
|
||||
Allocates an aligned buffer for SCSI disk.
|
||||
|
||||
This function allocates an aligned buffer for the SCSI disk to perform
|
||||
SCSI IO operations. The alignment requirement is from SCSI IO interface.
|
||||
|
||||
@param ScsiDiskDevice The SCSI disk involved for the operation.
|
||||
@param BufferSize The request buffer size.
|
||||
|
||||
@return A pointer to the aligned buffer or NULL if the allocation fails.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
AllocateAlignedBuffer (
|
||||
IN SCSI_DISK_DEV *ScsiDiskDevice,
|
||||
IN UINTN BufferSize
|
||||
)
|
||||
{
|
||||
return AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), ScsiDiskDevice->ScsiIo->IoAlign);
|
||||
}
|
||||
|
||||
/**
|
||||
Frees an aligned buffer for SCSI disk.
|
||||
|
||||
This function frees an aligned buffer for the SCSI disk to perform
|
||||
SCSI IO operations.
|
||||
|
||||
@param Buffer The aligned buffer to be freed.
|
||||
@param BufferSize The request buffer size.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FreeAlignedBuffer (
|
||||
IN VOID *Buffer,
|
||||
IN UINTN BufferSize
|
||||
)
|
||||
{
|
||||
if (Buffer != NULL) {
|
||||
FreeAlignedPages (Buffer, EFI_SIZE_TO_PAGES (BufferSize));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The user Entry Point for module ScsiDisk.
|
||||
|
||||
|
@ -902,8 +944,8 @@ ScsiDiskInquiryDevice (
|
|||
EFI_STATUS Status;
|
||||
UINT8 MaxRetry;
|
||||
UINT8 Index;
|
||||
EFI_SCSI_SUPPORTED_VPD_PAGES_VPD_PAGE SupportedVpdPages;
|
||||
EFI_SCSI_BLOCK_LIMITS_VPD_PAGE BlockLimits;
|
||||
EFI_SCSI_SUPPORTED_VPD_PAGES_VPD_PAGE *SupportedVpdPages;
|
||||
EFI_SCSI_BLOCK_LIMITS_VPD_PAGE *BlockLimits;
|
||||
UINTN PageLength;
|
||||
|
||||
InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
|
||||
|
@ -930,8 +972,13 @@ ScsiDiskInquiryDevice (
|
|||
//
|
||||
// Check whether the device supports Block Limits VPD page (0xB0)
|
||||
//
|
||||
ZeroMem (&SupportedVpdPages, sizeof (SupportedVpdPages));
|
||||
InquiryDataLength = sizeof (SupportedVpdPages);
|
||||
SupportedVpdPages = AllocateAlignedBuffer (ScsiDiskDevice, sizeof (EFI_SCSI_SUPPORTED_VPD_PAGES_VPD_PAGE));
|
||||
if (SupportedVpdPages == NULL) {
|
||||
*NeedRetry = FALSE;
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
ZeroMem (SupportedVpdPages, sizeof (EFI_SCSI_SUPPORTED_VPD_PAGES_VPD_PAGE));
|
||||
InquiryDataLength = sizeof (EFI_SCSI_SUPPORTED_VPD_PAGES_VPD_PAGE);
|
||||
SenseDataLength = 0;
|
||||
Status = ScsiInquiryCommandEx (
|
||||
ScsiDiskDevice->ScsiIo,
|
||||
|
@ -940,16 +987,16 @@ ScsiDiskInquiryDevice (
|
|||
&SenseDataLength,
|
||||
&HostAdapterStatus,
|
||||
&TargetStatus,
|
||||
(VOID *) &SupportedVpdPages,
|
||||
(VOID *) SupportedVpdPages,
|
||||
&InquiryDataLength,
|
||||
TRUE,
|
||||
EFI_SCSI_PAGE_CODE_SUPPORTED_VPD
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
PageLength = (SupportedVpdPages.PageLength2 << 8)
|
||||
| SupportedVpdPages.PageLength1;
|
||||
PageLength = (SupportedVpdPages->PageLength2 << 8)
|
||||
| SupportedVpdPages->PageLength1;
|
||||
for (Index = 0; Index < PageLength; Index++) {
|
||||
if (SupportedVpdPages.SupportedVpdPageList[Index] == EFI_SCSI_PAGE_CODE_BLOCK_LIMITS_VPD) {
|
||||
if (SupportedVpdPages->SupportedVpdPageList[Index] == EFI_SCSI_PAGE_CODE_BLOCK_LIMITS_VPD) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -958,8 +1005,14 @@ ScsiDiskInquiryDevice (
|
|||
// Query the Block Limits VPD page
|
||||
//
|
||||
if (Index < PageLength) {
|
||||
ZeroMem (&BlockLimits, sizeof (BlockLimits));
|
||||
InquiryDataLength = sizeof (BlockLimits);
|
||||
BlockLimits = AllocateAlignedBuffer (ScsiDiskDevice, sizeof (EFI_SCSI_BLOCK_LIMITS_VPD_PAGE));
|
||||
if (BlockLimits == NULL) {
|
||||
FreeAlignedBuffer (SupportedVpdPages, sizeof (EFI_SCSI_SUPPORTED_VPD_PAGES_VPD_PAGE));
|
||||
*NeedRetry = FALSE;
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
ZeroMem (BlockLimits, sizeof (EFI_SCSI_BLOCK_LIMITS_VPD_PAGE));
|
||||
InquiryDataLength = sizeof (EFI_SCSI_BLOCK_LIMITS_VPD_PAGE);
|
||||
SenseDataLength = 0;
|
||||
Status = ScsiInquiryCommandEx (
|
||||
ScsiDiskDevice->ScsiIo,
|
||||
|
@ -968,18 +1021,22 @@ ScsiDiskInquiryDevice (
|
|||
&SenseDataLength,
|
||||
&HostAdapterStatus,
|
||||
&TargetStatus,
|
||||
(VOID *) &BlockLimits,
|
||||
(VOID *) BlockLimits,
|
||||
&InquiryDataLength,
|
||||
TRUE,
|
||||
EFI_SCSI_PAGE_CODE_BLOCK_LIMITS_VPD
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
ScsiDiskDevice->BlkIo.Media->OptimalTransferLengthGranularity =
|
||||
(BlockLimits.OptimalTransferLengthGranularity2 << 8) |
|
||||
BlockLimits.OptimalTransferLengthGranularity1;
|
||||
}
|
||||
(BlockLimits->OptimalTransferLengthGranularity2 << 8) |
|
||||
BlockLimits->OptimalTransferLengthGranularity1;
|
||||
}
|
||||
|
||||
FreeAlignedBuffer (BlockLimits, sizeof (EFI_SCSI_BLOCK_LIMITS_VPD_PAGE));
|
||||
}
|
||||
}
|
||||
|
||||
FreeAlignedBuffer (SupportedVpdPages, sizeof (EFI_SCSI_SUPPORTED_VPD_PAGES_VPD_PAGE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1285,15 +1342,26 @@ ScsiDiskReadCapacity (
|
|||
UINT8 SenseDataLength;
|
||||
UINT32 DataLength10;
|
||||
UINT32 DataLength16;
|
||||
EFI_SCSI_DISK_CAPACITY_DATA CapacityData10;
|
||||
EFI_SCSI_DISK_CAPACITY_DATA16 CapacityData16;
|
||||
EFI_SCSI_DISK_CAPACITY_DATA *CapacityData10;
|
||||
EFI_SCSI_DISK_CAPACITY_DATA16 *CapacityData16;
|
||||
|
||||
CapacityData10 = AllocateAlignedBuffer (ScsiDiskDevice, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));
|
||||
if (CapacityData10 == NULL) {
|
||||
*NeedRetry = FALSE;
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
CapacityData16 = AllocateAlignedBuffer (ScsiDiskDevice, sizeof (EFI_SCSI_DISK_CAPACITY_DATA16));
|
||||
if (CapacityData16 == NULL) {
|
||||
FreeAlignedBuffer (CapacityData10, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));
|
||||
*NeedRetry = FALSE;
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
SenseDataLength = 0;
|
||||
DataLength10 = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);
|
||||
DataLength16 = sizeof (EFI_SCSI_DISK_CAPACITY_DATA16);
|
||||
ZeroMem (&CapacityData10, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));
|
||||
ZeroMem (&CapacityData16, sizeof (EFI_SCSI_DISK_CAPACITY_DATA16));
|
||||
ZeroMem (CapacityData10, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));
|
||||
ZeroMem (CapacityData16, sizeof (EFI_SCSI_DISK_CAPACITY_DATA16));
|
||||
|
||||
*NumberOfSenseKeys = 0;
|
||||
*NeedRetry = FALSE;
|
||||
|
@ -1309,14 +1377,14 @@ ScsiDiskReadCapacity (
|
|||
&SenseDataLength,
|
||||
&HostAdapterStatus,
|
||||
&TargetStatus,
|
||||
(VOID *) &CapacityData10,
|
||||
(VOID *) CapacityData10,
|
||||
&DataLength10,
|
||||
FALSE
|
||||
);
|
||||
|
||||
ScsiDiskDevice->Cdb16Byte = FALSE;
|
||||
if ((!EFI_ERROR (CommandStatus)) && (CapacityData10.LastLba3 == 0xff) && (CapacityData10.LastLba2 == 0xff) &&
|
||||
(CapacityData10.LastLba1 == 0xff) && (CapacityData10.LastLba0 == 0xff)) {
|
||||
if ((!EFI_ERROR (CommandStatus)) && (CapacityData10->LastLba3 == 0xff) && (CapacityData10->LastLba2 == 0xff) &&
|
||||
(CapacityData10->LastLba1 == 0xff) && (CapacityData10->LastLba0 == 0xff)) {
|
||||
//
|
||||
// use Read Capacity (16), Read (16) and Write (16) next when hard disk size > 2TB
|
||||
//
|
||||
|
@ -1332,7 +1400,7 @@ ScsiDiskReadCapacity (
|
|||
&SenseDataLength,
|
||||
&HostAdapterStatus,
|
||||
&TargetStatus,
|
||||
(VOID *) &CapacityData16,
|
||||
(VOID *) CapacityData16,
|
||||
&DataLength16,
|
||||
FALSE
|
||||
);
|
||||
|
@ -1342,17 +1410,23 @@ ScsiDiskReadCapacity (
|
|||
// no need to check HostAdapterStatus and TargetStatus
|
||||
//
|
||||
if (CommandStatus == EFI_SUCCESS) {
|
||||
GetMediaInfo (ScsiDiskDevice, &CapacityData10,&CapacityData16);
|
||||
GetMediaInfo (ScsiDiskDevice, CapacityData10, CapacityData16);
|
||||
FreeAlignedBuffer (CapacityData10, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));
|
||||
FreeAlignedBuffer (CapacityData16, sizeof (EFI_SCSI_DISK_CAPACITY_DATA16));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
} else if (CommandStatus == EFI_NOT_READY) {
|
||||
FreeAlignedBuffer (CapacityData10, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));
|
||||
FreeAlignedBuffer (CapacityData16, sizeof (EFI_SCSI_DISK_CAPACITY_DATA16));
|
||||
|
||||
if (CommandStatus == EFI_NOT_READY) {
|
||||
*NeedRetry = TRUE;
|
||||
return EFI_DEVICE_ERROR;
|
||||
|
||||
} else if ((CommandStatus == EFI_INVALID_PARAMETER) || (CommandStatus == EFI_UNSUPPORTED)) {
|
||||
*NeedRetry = FALSE;
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// go ahead to check HostAdapterStatus and TargetStatus
|
||||
// (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL)
|
||||
|
|
Loading…
Reference in New Issue