X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FScsi%2FScsiBusDxe%2FScsiBus.c;h=1068770cd87f02903ca28e31b4ae94da09487fcc;hp=b1c4d207f9de8bf415b3b7a157906391dcba334e;hb=c09e481bbb34cb781b3d98f4ec781305e61dfda5;hpb=c8ad2d7a296c851c2a91519f80dab479df0fdf46 diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c index b1c4d207f9..1068770cd8 100644 --- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c +++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c @@ -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.
+Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
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. @@ -298,6 +341,15 @@ SCSIBusDriverBindingStart ( return DevicePathStatus; } + // + // Report Status Code to indicate SCSI bus starts + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_SCSI | EFI_IOB_PC_INIT), + ParentDevicePath + ); + // // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly @@ -408,6 +460,15 @@ SCSIBusDriverBindingStart ( ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify); } + // + // Report Status Code to indicate detecting devices on bus + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_SCSI | EFI_IOB_PC_DETECT), + ParentDevicePath + ); + Lun = 0; if (RemainingDevicePath == NULL) { // @@ -785,6 +846,15 @@ ScsiResetBus ( ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); + // + // Report Status Code to indicate reset happens + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET), + ScsiIoDevice->ScsiBusDeviceData->DevicePath + ); + if (ScsiIoDevice->ExtScsiSupport){ return ScsiIoDevice->ExtScsiPassThru->ResetChannel (ScsiIoDevice->ExtScsiPassThru); } else { @@ -814,6 +884,16 @@ ScsiResetDevice ( UINT8 Target[TARGET_MAX_BYTES]; ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); + + // + // Report Status Code to indicate reset happens + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET), + ScsiIoDevice->ScsiBusDeviceData->DevicePath + ); + CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES); @@ -906,13 +986,35 @@ ScsiExecuteSCSICommand ( if (ScsiIoDevice->ExtScsiSupport) { ExtRequestPacket = (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet; - Status = ScsiIoDevice->ExtScsiPassThru->PassThru ( - ScsiIoDevice->ExtScsiPassThru, - Target, - ScsiIoDevice->Lun, - ExtRequestPacket, - Event - ); + + if (((ScsiIoDevice->ExtScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) != 0) && (Event != NULL)) { + Status = ScsiIoDevice->ExtScsiPassThru->PassThru ( + ScsiIoDevice->ExtScsiPassThru, + Target, + ScsiIoDevice->Lun, + ExtRequestPacket, + Event + ); + } else { + // + // If there's no event or the SCSI Device doesn't support NON-BLOCKING, + // let the 'Event' parameter for PassThru() be NULL. + // + Status = ScsiIoDevice->ExtScsiPassThru->PassThru ( + ScsiIoDevice->ExtScsiPassThru, + Target, + ScsiIoDevice->Lun, + ExtRequestPacket, + NULL + ); + if ((!EFI_ERROR(Status)) && (Event != NULL)) { + // + // Signal Event to tell caller to pick up the SCSI IO packet if the + // PassThru() succeeds. + // + gBS->SignalEvent (Event); + } + } } else { mWorkingBuffer = AllocatePool (sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); @@ -938,7 +1040,7 @@ ScsiExecuteSCSICommand ( // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, NotifyFunction, &EventData, &PacketEvent @@ -972,7 +1074,7 @@ ScsiExecuteSCSICommand ( ScsiIoDevice->Pun.ScsiId.Scsi, ScsiIoDevice->Lun, mWorkingBuffer, - Event + NULL ); if (EFI_ERROR(Status)) { FreePool(mWorkingBuffer); @@ -985,6 +1087,13 @@ ScsiExecuteSCSICommand ( // free mWorkingBuffer. // FreePool(mWorkingBuffer); + + // + // Signal Event to tell caller to pick up the SCSI IO Packet. + // + if (Event != NULL) { + gBS->SignalEvent (Event); + } } } return Status; @@ -1078,6 +1187,7 @@ ScsiScanCreateDevice ( } ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE; + ScsiIoDevice->ScsiBusDeviceData = ScsiBusDev; CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES); ScsiIoDevice->Lun = Lun; @@ -1098,6 +1208,15 @@ ScsiScanCreateDevice ( ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice; ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand; + // + // Report Status Code here since the new SCSI device will be discovered + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_SCSI | EFI_IOB_PC_ENABLE), + ScsiBusDev->DevicePath + ); + if (!DiscoverScsiDevice (ScsiIoDevice)) { Status = EFI_OUT_OF_RESOURCES; goto ErrorExit; @@ -1178,79 +1297,89 @@ 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, + SCSI_BUS_TIMEOUT, + NULL, &SenseDataLength, &HostAdapterStatus, &TargetStatus, - (VOID *) &InquiryData, + (VOID *) InquiryData, &InquiryDataLength, FALSE ); if (!EFI_ERROR (Status)) { break; - } else if ((Status == EFI_BAD_BUFFER_SIZE) || - (Status == EFI_INVALID_PARAMETER) || - (Status == EFI_UNSUPPORTED)) { - return FALSE; + } + if ((Status == EFI_BAD_BUFFER_SIZE) || + (Status == EFI_INVALID_PARAMETER) || + (Status == EFI_UNSUPPORTED)) { + 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) { + ScsiDeviceFound = FALSE; + goto Done; } - if (InquiryData.Peripheral_Qualifier == 3) { - if (InquiryData.Peripheral_Type != 0x1f) { - return FALSE; - } - } - - 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; }