mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 03:03:46 +01:00 
			
		
		
		
	Changed old event definitions reference to these new event definitions. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2729 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			2355 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2355 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2006 - 2007, 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        
 | |
| http://opensource.org/licenses/bsd-license.php                                            
 | |
|                                                                                           
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | |
| 
 | |
| Module Name:
 | |
| 
 | |
|   ScsiDisk.c
 | |
| 
 | |
| Abstract:
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include "ScsiDisk.h"
 | |
| 
 | |
| EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding = {
 | |
|   ScsiDiskDriverBindingSupported,
 | |
|   ScsiDiskDriverBindingStart,
 | |
|   ScsiDiskDriverBindingStop,
 | |
|   0xa,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ScsiDiskDriverBindingSupported (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | |
|   IN EFI_HANDLE                   Controller,
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
|   
 | |
|   Routine Description:
 | |
|   
 | |
|   Arguments:
 | |
|   
 | |
|   Returns:
 | |
|   
 | |
| --*/
 | |
| // TODO:    This - add argument and description to function comment
 | |
| // TODO:    Controller - add argument and description to function comment
 | |
| // TODO:    RemainingDevicePath - add argument and description to function comment
 | |
| {
 | |
|   EFI_STATUS            Status;
 | |
|   EFI_SCSI_IO_PROTOCOL  *ScsiIo;
 | |
|   UINT8                 DeviceType;
 | |
| 
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiScsiIoProtocolGuid,
 | |
|                   (VOID **) &ScsiIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = ScsiIo->GetDeviceType (ScsiIo, &DeviceType);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     if ((DeviceType == EFI_SCSI_TYPE_DISK) || (DeviceType == EFI_SCSI_TYPE_CDROM)) {
 | |
|       Status = EFI_SUCCESS;
 | |
|     } else {
 | |
|       Status = EFI_UNSUPPORTED;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   gBS->CloseProtocol (
 | |
|         Controller,
 | |
|         &gEfiScsiIoProtocolGuid,
 | |
|         This->DriverBindingHandle,
 | |
|         Controller
 | |
|         );
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ScsiDiskDriverBindingStart (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | |
|   IN EFI_HANDLE                   Controller,
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
|   
 | |
|   Routine Description:
 | |
|   
 | |
|   Arguments:
 | |
|   
 | |
|   Returns:
 | |
|   
 | |
| --*/
 | |
| // TODO:    This - add argument and description to function comment
 | |
| // TODO:    Controller - add argument and description to function comment
 | |
| // TODO:    RemainingDevicePath - add argument and description to function comment
 | |
| // TODO:    EFI_DEVICE_ERROR - add return value to function comment
 | |
| // TODO:    EFI_SUCCESS - add return value to function comment
 | |
| {
 | |
|   EFI_STATUS            Status;
 | |
|   EFI_SCSI_IO_PROTOCOL  *ScsiIo;
 | |
|   SCSI_DISK_DEV         *ScsiDiskDevice;
 | |
|   BOOLEAN               Temp;
 | |
|   UINT8                 Index;
 | |
|   UINT8                 MaxRetry;
 | |
|   BOOLEAN               NeedRetry;
 | |
| 
 | |
|   Status = gBS->AllocatePool (
 | |
|                   EfiBootServicesData,
 | |
|                   sizeof (SCSI_DISK_DEV),
 | |
|                   (VOID **) &ScsiDiskDevice
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   ZeroMem (ScsiDiskDevice, sizeof (SCSI_DISK_DEV));
 | |
| 
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiScsiIoProtocolGuid,
 | |
|                   (VOID **) &ScsiIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->FreePool (ScsiDiskDevice);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   ScsiDiskDevice->Signature         = SCSI_DISK_DEV_SIGNATURE;
 | |
|   ScsiDiskDevice->ScsiIo            = ScsiIo;
 | |
|   ScsiDiskDevice->BlkIo.Media       = &ScsiDiskDevice->BlkIoMedia;
 | |
|   ScsiDiskDevice->BlkIo.Reset       = ScsiDiskReset;
 | |
|   ScsiDiskDevice->BlkIo.ReadBlocks  = ScsiDiskReadBlocks;
 | |
|   ScsiDiskDevice->BlkIo.WriteBlocks = ScsiDiskWriteBlocks;
 | |
|   ScsiDiskDevice->BlkIo.FlushBlocks = ScsiDiskFlushBlocks;
 | |
|   ScsiDiskDevice->Handle            = Controller;
 | |
| 
 | |
|   ScsiIo->GetDeviceType (ScsiIo, &(ScsiDiskDevice->DeviceType));
 | |
|   switch (ScsiDiskDevice->DeviceType) {
 | |
|   case EFI_SCSI_TYPE_DISK:
 | |
|     ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200;
 | |
|     break;
 | |
| 
 | |
|   case EFI_SCSI_TYPE_CDROM:
 | |
|     ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800;
 | |
|     break;
 | |
|   }
 | |
|   //
 | |
|   // The Sense Data Array's initial size is 6
 | |
|   //
 | |
|   ScsiDiskDevice->SenseDataNumber = 6;
 | |
|   Status = gBS->AllocatePool (
 | |
|                   EfiBootServicesData,
 | |
|                   sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber,
 | |
|                   (VOID **) &(ScsiDiskDevice->SenseData)
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->CloseProtocol (
 | |
|           Controller,
 | |
|           &gEfiScsiIoProtocolGuid,
 | |
|           This->DriverBindingHandle,
 | |
|           Controller
 | |
|           );
 | |
|     gBS->FreePool (ScsiDiskDevice);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   ZeroMem (
 | |
|     ScsiDiskDevice->SenseData,
 | |
|     sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Retrive device information
 | |
|   //
 | |
|   MaxRetry = 2;
 | |
|   for (Index = 0; Index < MaxRetry; Index++) {
 | |
|     Status = ScsiDiskInquiryDevice (ScsiDiskDevice, &NeedRetry);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if (!NeedRetry) {
 | |
|       gBS->FreePool (ScsiDiskDevice->SenseData);
 | |
|       gBS->CloseProtocol (
 | |
|             Controller,
 | |
|             &gEfiScsiIoProtocolGuid,
 | |
|             This->DriverBindingHandle,
 | |
|             Controller
 | |
|             );
 | |
|       gBS->FreePool (ScsiDiskDevice);
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // The second parameter "TRUE" means must
 | |
|   // retrieve media capacity
 | |
|   //
 | |
|   Status = ScsiDiskDetectMedia (ScsiDiskDevice, TRUE, &Temp);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                     &Controller,
 | |
|                     &gEfiBlockIoProtocolGuid,
 | |
|                     &ScsiDiskDevice->BlkIo,
 | |
|                     NULL
 | |
|                     );
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->FreePool (ScsiDiskDevice->SenseData);
 | |
|     gBS->CloseProtocol (
 | |
|           Controller,
 | |
|           &gEfiScsiIoProtocolGuid,
 | |
|           This->DriverBindingHandle,
 | |
|           Controller
 | |
|           );
 | |
|     gBS->FreePool (ScsiDiskDevice);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   ScsiDiskDevice->ControllerNameTable = NULL;
 | |
|   AddUnicodeString (
 | |
|     "eng",
 | |
|     gScsiDiskComponentName.SupportedLanguages,
 | |
|     &ScsiDiskDevice->ControllerNameTable,
 | |
|     (CHAR16 *) L"SCSI Disk Device"
 | |
|     );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| 
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ScsiDiskDriverBindingStop (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      Controller,
 | |
|   IN  UINTN                           NumberOfChildren,
 | |
|   IN  EFI_HANDLE                      *ChildHandleBuffer
 | |
|   )
 | |
| /*++
 | |
|   
 | |
|   Routine Description:
 | |
|   
 | |
|   Arguments:
 | |
|   
 | |
|   Returns:
 | |
|   
 | |
| --*/
 | |
| // TODO:    This - add argument and description to function comment
 | |
| // TODO:    Controller - add argument and description to function comment
 | |
| // TODO:    NumberOfChildren - add argument and description to function comment
 | |
| // TODO:    ChildHandleBuffer - add argument and description to function comment
 | |
| // TODO:    EFI_SUCCESS - add return value to function comment
 | |
| {
 | |
|   EFI_BLOCK_IO_PROTOCOL *BlkIo;
 | |
|   SCSI_DISK_DEV         *ScsiDiskDevice;
 | |
|   EFI_STATUS            Status;
 | |
| 
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiBlockIoProtocolGuid,
 | |
|                   (VOID **) &BlkIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (BlkIo);
 | |
|   Status = gBS->UninstallProtocolInterface (
 | |
|                   Controller,
 | |
|                   &gEfiBlockIoProtocolGuid,
 | |
|                   &ScsiDiskDevice->BlkIo
 | |
|                   );
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     gBS->CloseProtocol (
 | |
|           Controller,
 | |
|           &gEfiScsiIoProtocolGuid,
 | |
|           This->DriverBindingHandle,
 | |
|           Controller
 | |
|           );
 | |
| 
 | |
|     ReleaseScsiDiskDeviceResources (ScsiDiskDevice);
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
|   //
 | |
|   // errors met
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| //
 | |
| // Block I/O Protocol Interface
 | |
| //
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ScsiDiskReset (
 | |
|   IN  EFI_BLOCK_IO_PROTOCOL   *This,
 | |
|   IN  BOOLEAN                 ExtendedVerification
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This                  - TODO: add argument description
 | |
|   ExtendedVerification  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   SCSI_DISK_DEV *ScsiDiskDevice;
 | |
|   EFI_STATUS    Status;
 | |
|   EFI_TPL       OldTpl;
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
| 
 | |
|   ScsiDiskDevice  = SCSI_DISK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   Status          = ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
 | |
| 
 | |
|   if (!ExtendedVerification) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
 | |
| 
 | |
| Done:
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ScsiDiskReadBlocks (
 | |
|   IN  EFI_BLOCK_IO_PROTOCOL   *This,
 | |
|   IN  UINT32                  MediaId,
 | |
|   IN  EFI_LBA                 LBA,
 | |
|   IN  UINTN                   BufferSize,
 | |
|   OUT VOID                    *Buffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This        - TODO: add argument description
 | |
|   MediaId     - TODO: add argument description
 | |
|   LBA         - TODO: add argument description
 | |
|   BufferSize  - TODO: add argument description
 | |
|   Buffer      - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_INVALID_PARAMETER - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_NO_MEDIA - TODO: Add description for return value
 | |
|   EFI_MEDIA_CHANGED - TODO: Add description for return value
 | |
|   EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
 | |
|   EFI_INVALID_PARAMETER - TODO: Add description for return value
 | |
|   EFI_INVALID_PARAMETER - TODO: Add description for return value
 | |
|   EFI_INVALID_PARAMETER - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   SCSI_DISK_DEV       *ScsiDiskDevice;
 | |
|   EFI_BLOCK_IO_MEDIA  *Media;
 | |
|   EFI_STATUS          Status;
 | |
|   UINTN               BlockSize;
 | |
|   UINTN               NumberOfBlocks;
 | |
|   BOOLEAN             MediaChange;
 | |
|   EFI_TPL             OldTpl;
 | |
| 
 | |
|   MediaChange = FALSE;
 | |
|   if (!Buffer) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (BufferSize == 0) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
| 
 | |
|   ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (!IsDeviceFixed (ScsiDiskDevice)) {
 | |
| 
 | |
|     Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (MediaChange) {
 | |
|       gBS->ReinstallProtocolInterface (
 | |
|             ScsiDiskDevice->Handle,
 | |
|             &gEfiBlockIoProtocolGuid,
 | |
|             &ScsiDiskDevice->BlkIo,
 | |
|             &ScsiDiskDevice->BlkIo
 | |
|             );
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Get the intrinsic block size
 | |
|   //
 | |
|   Media           = ScsiDiskDevice->BlkIo.Media;
 | |
|   BlockSize       = Media->BlockSize;
 | |
| 
 | |
|   NumberOfBlocks  = BufferSize / BlockSize;
 | |
| 
 | |
|   if (!(Media->MediaPresent)) {
 | |
|     Status = EFI_NO_MEDIA;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (MediaId != Media->MediaId) {
 | |
|     Status = EFI_MEDIA_CHANGED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (BufferSize % BlockSize != 0) {
 | |
|     Status = EFI_BAD_BUFFER_SIZE;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (LBA > Media->LastBlock) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Done;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // if all the parameters are valid, then perform read sectors command
 | |
|   // to transfer data from device to host.
 | |
|   //
 | |
|   Status = ScsiDiskReadSectors (ScsiDiskDevice, Buffer, LBA, NumberOfBlocks);
 | |
| 
 | |
| Done:
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ScsiDiskWriteBlocks (
 | |
|   IN  EFI_BLOCK_IO_PROTOCOL   *This,
 | |
|   IN  UINT32                  MediaId,
 | |
|   IN  EFI_LBA                 LBA,
 | |
|   IN  UINTN                   BufferSize,
 | |
|   IN  VOID                    *Buffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This        - TODO: add argument description
 | |
|   MediaId     - TODO: add argument description
 | |
|   LBA         - TODO: add argument description
 | |
|   BufferSize  - TODO: add argument description
 | |
|   Buffer      - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_INVALID_PARAMETER - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_NO_MEDIA - TODO: Add description for return value
 | |
|   EFI_MEDIA_CHANGED - TODO: Add description for return value
 | |
|   EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
 | |
|   EFI_INVALID_PARAMETER - TODO: Add description for return value
 | |
|   EFI_INVALID_PARAMETER - TODO: Add description for return value
 | |
|   EFI_INVALID_PARAMETER - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   SCSI_DISK_DEV       *ScsiDiskDevice;
 | |
|   EFI_BLOCK_IO_MEDIA  *Media;
 | |
|   EFI_STATUS          Status;
 | |
|   UINTN               BlockSize;
 | |
|   UINTN               NumberOfBlocks;
 | |
|   BOOLEAN             MediaChange;
 | |
|   EFI_TPL             OldTpl;
 | |
| 
 | |
|   MediaChange = FALSE;
 | |
|   if (!Buffer) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (BufferSize == 0) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
| 
 | |
|   ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (!IsDeviceFixed (ScsiDiskDevice)) {
 | |
| 
 | |
|     Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (MediaChange) {
 | |
|       gBS->ReinstallProtocolInterface (
 | |
|             ScsiDiskDevice->Handle,
 | |
|             &gEfiBlockIoProtocolGuid,
 | |
|             &ScsiDiskDevice->BlkIo,
 | |
|             &ScsiDiskDevice->BlkIo
 | |
|             );
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Get the intrinsic block size
 | |
|   //
 | |
|   Media           = ScsiDiskDevice->BlkIo.Media;
 | |
|   BlockSize       = Media->BlockSize;
 | |
| 
 | |
|   NumberOfBlocks  = BufferSize / BlockSize;
 | |
| 
 | |
|   if (!(Media->MediaPresent)) {
 | |
|     Status = EFI_NO_MEDIA;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (MediaId != Media->MediaId) {
 | |
|     Status = EFI_MEDIA_CHANGED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (BufferSize % BlockSize != 0) {
 | |
|     Status = EFI_BAD_BUFFER_SIZE;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (LBA > Media->LastBlock) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // if all the parameters are valid, then perform read sectors command
 | |
|   // to transfer data from device to host.
 | |
|   //
 | |
|   Status = ScsiDiskWriteSectors (ScsiDiskDevice, Buffer, LBA, NumberOfBlocks);
 | |
| 
 | |
| Done:
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ScsiDiskFlushBlocks (
 | |
|   IN  EFI_BLOCK_IO_PROTOCOL   *This
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   //
 | |
|   // return directly
 | |
|   //
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ScsiDiskDetectMedia (
 | |
|   SCSI_DISK_DEV   *ScsiDiskDevice,
 | |
|   BOOLEAN         MustReadCapacity,
 | |
|   BOOLEAN         *MediaChange
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice    - TODO: add argument description
 | |
|   MustReadCapacity  - TODO: add argument description
 | |
|   MediaChange       - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS          Status;
 | |
|   EFI_STATUS          ReadCapacityStatus;
 | |
|   EFI_SCSI_SENSE_DATA *SenseData;
 | |
|   UINTN               NumberOfSenseKeys;
 | |
|   BOOLEAN             NeedRetry;
 | |
|   BOOLEAN             NeedReadCapacity;
 | |
|   UINT8               Index;
 | |
|   UINT8               MaxRetry;
 | |
|   EFI_BLOCK_IO_MEDIA  OldMedia;
 | |
|   UINTN               Action;
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   ReadCapacityStatus  = EFI_SUCCESS;
 | |
|   SenseData           = NULL;
 | |
|   NumberOfSenseKeys   = 0;
 | |
|   NeedReadCapacity    = FALSE;
 | |
|   CopyMem (&OldMedia, ScsiDiskDevice->BlkIo.Media, sizeof (OldMedia));
 | |
|   // OldMedia            = *(ScsiDiskDevice->BlkIo.Media);
 | |
| 
 | |
|   *MediaChange        = FALSE;
 | |
| 
 | |
|   MaxRetry            = 3;
 | |
|   for (Index = 0; Index < MaxRetry; Index++) {
 | |
|     Status = ScsiDiskTestUnitReady (
 | |
|               ScsiDiskDevice,
 | |
|               &NeedRetry,
 | |
|               &SenseData,
 | |
|               &NumberOfSenseKeys
 | |
|               );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if (!NeedRetry) {
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((Index == MaxRetry) && EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   Status = DetectMediaParsingSenseKeys (
 | |
|             ScsiDiskDevice,
 | |
|             SenseData,
 | |
|             NumberOfSenseKeys,
 | |
|             &Action
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // ACTION_NO_ACTION: need not read capacity
 | |
|   // other action code: need read capacity
 | |
|   //
 | |
|   if (Action == ACTION_NO_ACTION) {
 | |
|     NeedReadCapacity = FALSE;
 | |
|   } else {
 | |
|     NeedReadCapacity = TRUE;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // either NeedReadCapacity is TRUE, or MustReadCapacity is TRUE,
 | |
|   // retrieve capacity via Read Capacity command
 | |
|   //
 | |
|   if (NeedReadCapacity || MustReadCapacity) {
 | |
|     
 | |
|     //
 | |
|     // retrieve media information
 | |
|     //
 | |
|     MaxRetry = 3;
 | |
|     for (Index = 0; Index < MaxRetry; Index++) {
 | |
| 
 | |
|       ReadCapacityStatus = ScsiDiskReadCapacity (
 | |
|                             ScsiDiskDevice,
 | |
|                             &NeedRetry,
 | |
|                             &SenseData,
 | |
|                             &NumberOfSenseKeys
 | |
|                             );
 | |
|       if (EFI_ERROR (ReadCapacityStatus) && !NeedRetry) {
 | |
|         return EFI_DEVICE_ERROR;
 | |
|       }
 | |
|       //
 | |
|       // analyze sense key to action
 | |
|       //
 | |
|       Status = DetectMediaParsingSenseKeys (
 | |
|                 ScsiDiskDevice,
 | |
|                 SenseData,
 | |
|                 NumberOfSenseKeys,
 | |
|                 &Action
 | |
|                 );
 | |
|       //
 | |
|       // if Status is error, it may indicate crisis error,
 | |
|       // so return without retry.
 | |
|       //
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         return Status;
 | |
|       }
 | |
| 
 | |
|       switch (Action) {
 | |
|       case ACTION_NO_ACTION:
 | |
|         //
 | |
|         // no retry
 | |
|         //
 | |
|         Index = MaxRetry;
 | |
|         break;
 | |
| 
 | |
|       case ACTION_RETRY_COMMAND_LATER:
 | |
|         //
 | |
|         // retry the ReadCapacity later and continuously, until the condition
 | |
|         // no longer emerges.
 | |
|         // stall time is 100000us, or say 0.1 second.
 | |
|         //
 | |
|         gBS->Stall (100000);
 | |
|         Index = 0;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         //
 | |
|         // other cases, just retry the command
 | |
|         //
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if ((Index == MaxRetry) && EFI_ERROR (ReadCapacityStatus)) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskDevice->BlkIo.Media->MediaId != OldMedia.MediaId) {
 | |
|     //
 | |
|     // Media change information got from the device
 | |
|     //
 | |
|     *MediaChange = TRUE;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskDevice->BlkIo.Media->ReadOnly != OldMedia.ReadOnly) {
 | |
|     *MediaChange = TRUE;
 | |
|     ScsiDiskDevice->BlkIo.Media->MediaId += 1;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskDevice->BlkIo.Media->BlockSize != OldMedia.BlockSize) {
 | |
|     *MediaChange = TRUE;
 | |
|     ScsiDiskDevice->BlkIo.Media->MediaId += 1;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskDevice->BlkIo.Media->LastBlock != OldMedia.LastBlock) {
 | |
|     *MediaChange = TRUE;
 | |
|     ScsiDiskDevice->BlkIo.Media->MediaId += 1;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskDevice->BlkIo.Media->MediaPresent != OldMedia.MediaPresent) {
 | |
|     if (ScsiDiskDevice->BlkIo.Media->MediaPresent) {
 | |
|       //
 | |
|       // when change from no media to media present, reset the MediaId to 1.
 | |
|       //
 | |
|       ScsiDiskDevice->BlkIo.Media->MediaId = 1;
 | |
|     } else {
 | |
|       //
 | |
|       // when no media, reset the MediaId to zero.
 | |
|       //
 | |
|       ScsiDiskDevice->BlkIo.Media->MediaId = 0;
 | |
|     }
 | |
| 
 | |
|     *MediaChange = TRUE;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ScsiDiskInquiryDevice (
 | |
|   SCSI_DISK_DEV   *ScsiDiskDevice,
 | |
|   BOOLEAN         *NeedRetry
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice  - TODO: add argument description
 | |
|   NeedRetry       - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT32              InquiryDataLength;
 | |
|   UINT8               SenseDataLength;
 | |
|   UINT8               HostAdapterStatus;
 | |
|   UINT8               TargetStatus;
 | |
|   EFI_SCSI_SENSE_DATA *SenseDataArray;
 | |
|   UINTN               NumberOfSenseKeys;
 | |
|   EFI_STATUS          Status;
 | |
|   UINT8               MaxRetry;
 | |
|   UINT8               Index;
 | |
| 
 | |
|   InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
 | |
|   SenseDataLength   = 0;
 | |
| 
 | |
|   Status = SubmitInquiryCommand (
 | |
|             ScsiDiskDevice->ScsiIo,
 | |
|             EfiScsiStallSeconds (1),
 | |
|             NULL,
 | |
|             &SenseDataLength,
 | |
|             &HostAdapterStatus,
 | |
|             &TargetStatus,
 | |
|             (VOID *) &(ScsiDiskDevice->InquiryData),
 | |
|             &InquiryDataLength,
 | |
|             FALSE
 | |
|             );
 | |
|   if ((Status == EFI_SUCCESS) || (Status == EFI_WARN_BUFFER_TOO_SMALL)) {
 | |
|     //
 | |
|     // no need to check HostAdapterStatus and TargetStatus
 | |
|     //
 | |
|     ParseInquiryData (ScsiDiskDevice);
 | |
|     return EFI_SUCCESS;
 | |
|   } else if (Status == EFI_NOT_READY) {
 | |
|     //
 | |
|     // no need to check HostAdapterStatus and TargetStatus
 | |
|     //
 | |
|     *NeedRetry = TRUE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   } else if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) {
 | |
|     //
 | |
|     // no need to check HostAdapterStatus and TargetStatus
 | |
|     //
 | |
|     *NeedRetry = FALSE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // go ahead to check HostAdapterStatus and TargetStatus
 | |
|   // (EFI_TIMEOUT, EFI_DEVICE_ERROR)
 | |
|   //
 | |
|   Status = CheckHostAdapterStatus (HostAdapterStatus);
 | |
|   if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) {
 | |
|     *NeedRetry = TRUE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   } else if (Status == EFI_DEVICE_ERROR) {
 | |
|     //
 | |
|     // reset the scsi channel
 | |
|     //
 | |
|     ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
 | |
|     *NeedRetry = FALSE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   Status = CheckTargetStatus (TargetStatus);
 | |
|   if (Status == EFI_NOT_READY) {
 | |
|     //
 | |
|     // reset the scsi device
 | |
|     //
 | |
|     ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
 | |
|     *NeedRetry = TRUE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   } else if (Status == EFI_DEVICE_ERROR) {
 | |
|     *NeedRetry = FALSE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // if goes here, meant SubmitInquiryCommand() failed.
 | |
|   // if ScsiDiskRequestSenseKeys() succeeds at last,
 | |
|   // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE)
 | |
|   //
 | |
|   MaxRetry = 3;
 | |
|   for (Index = 0; Index < MaxRetry; Index++) {
 | |
| 
 | |
|     Status = ScsiDiskRequestSenseKeys (
 | |
|               ScsiDiskDevice,
 | |
|               NeedRetry,
 | |
|               &SenseDataArray,
 | |
|               &NumberOfSenseKeys,
 | |
|               TRUE
 | |
|               );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       *NeedRetry = TRUE;
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (!*NeedRetry) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
 | |
|   // set *NeedRetry = FALSE to avoid the outside caller try again.
 | |
|   //
 | |
|   *NeedRetry = FALSE;
 | |
|   return EFI_DEVICE_ERROR;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ScsiDiskTestUnitReady (
 | |
|   SCSI_DISK_DEV         *ScsiDiskDevice,
 | |
|   BOOLEAN               *NeedRetry,
 | |
|   EFI_SCSI_SENSE_DATA   **SenseDataArray,
 | |
|   UINTN                 *NumberOfSenseKeys
 | |
|   )
 | |
| // TODO: function comment should start with '/*++'
 | |
| /*
 | |
|   When Test Unit Ready command succeeds,
 | |
|   retrieve Sense Keys via Request Sense;
 | |
|   When Test Unit Ready command encounters any error caused by host adapter or
 | |
|   target, return error without retrieving Sense Keys.
 | |
| */
 | |
| // TODO: function comment should end with '--*/'
 | |
| // TODO: function comment is missing 'Routine Description:'
 | |
| // TODO: function comment is missing 'Arguments:'
 | |
| // TODO: function comment is missing 'Returns:'
 | |
| // TODO:    ScsiDiskDevice - add argument and description to function comment
 | |
| // TODO:    NeedRetry - add argument and description to function comment
 | |
| // TODO:    SenseDataArray - add argument and description to function comment
 | |
| // TODO:    NumberOfSenseKeys - add argument and description to function comment
 | |
| // TODO:    EFI_DEVICE_ERROR - add return value to function comment
 | |
| // TODO:    EFI_DEVICE_ERROR - add return value to function comment
 | |
| // TODO:    EFI_DEVICE_ERROR - add return value to function comment
 | |
| // TODO:    EFI_DEVICE_ERROR - add return value to function comment
 | |
| // TODO:    EFI_DEVICE_ERROR - add return value to function comment
 | |
| // TODO:    EFI_DEVICE_ERROR - add return value to function comment
 | |
| // TODO:    EFI_SUCCESS - add return value to function comment
 | |
| // TODO:    EFI_DEVICE_ERROR - add return value to function comment
 | |
| // TODO:    EFI_DEVICE_ERROR - add return value to function comment
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT8       SenseDataLength;
 | |
|   UINT8       HostAdapterStatus;
 | |
|   UINT8       TargetStatus;
 | |
|   UINT8       Index;
 | |
|   UINT8       MaxRetry;
 | |
| 
 | |
|   SenseDataLength     = 0;
 | |
|   *NumberOfSenseKeys  = 0;
 | |
| 
 | |
|   //
 | |
|   // Parameter 3 and 4: do not require sense data, retrieve it when needed.
 | |
|   //
 | |
|   Status = SubmitTestUnitReadyCommand (
 | |
|             ScsiDiskDevice->ScsiIo,
 | |
|             EfiScsiStallSeconds (1),
 | |
|             NULL,
 | |
|             &SenseDataLength,
 | |
|             &HostAdapterStatus,
 | |
|             &TargetStatus
 | |
|             );
 | |
|   if (Status == EFI_NOT_READY) {
 | |
|     //
 | |
|     // no need to check HostAdapterStatus and TargetStatus
 | |
|     //
 | |
|     *NeedRetry = TRUE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   } else if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) {
 | |
|     //
 | |
|     // no need to check HostAdapterStatus and TargetStatus
 | |
|     //
 | |
|     *NeedRetry = FALSE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // go ahead to check HostAdapterStatus and TargetStatus
 | |
|   //
 | |
|   Status = CheckHostAdapterStatus (HostAdapterStatus);
 | |
|   if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) {
 | |
|     *NeedRetry = TRUE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   } else if (Status == EFI_DEVICE_ERROR) {
 | |
|     //
 | |
|     // reset the scsi channel
 | |
|     //
 | |
|     ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
 | |
|     *NeedRetry = FALSE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   Status = CheckTargetStatus (TargetStatus);
 | |
|   if (Status == EFI_NOT_READY) {
 | |
|     //
 | |
|     // reset the scsi device
 | |
|     //
 | |
|     ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
 | |
|     *NeedRetry = TRUE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   } else if (Status == EFI_DEVICE_ERROR) {
 | |
|     *NeedRetry = FALSE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   MaxRetry = 3;
 | |
|   for (Index = 0; Index < MaxRetry; Index++) {
 | |
| 
 | |
|     Status = ScsiDiskRequestSenseKeys (
 | |
|               ScsiDiskDevice,
 | |
|               NeedRetry,
 | |
|               SenseDataArray,
 | |
|               NumberOfSenseKeys,
 | |
|               FALSE
 | |
|               );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     if (!*NeedRetry) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
 | |
|   // set *NeedRetry = FALSE to avoid the outside caller try again.
 | |
|   //
 | |
|   *NeedRetry = FALSE;
 | |
|   return EFI_DEVICE_ERROR;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| DetectMediaParsingSenseKeys (
 | |
|   SCSI_DISK_DEV           *ScsiDiskDevice,
 | |
|   EFI_SCSI_SENSE_DATA     *SenseData,
 | |
|   UINTN                   NumberOfSenseKeys,
 | |
|   UINTN                   *Action
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice    - TODO: add argument description
 | |
|   SenseData         - TODO: add argument description
 | |
|   NumberOfSenseKeys - TODO: add argument description
 | |
|   Action            - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   BOOLEAN RetryLater;
 | |
| 
 | |
|   //
 | |
|   // Default is to read capacity, unless..
 | |
|   //
 | |
|   *Action = ACTION_READ_CAPACITY;
 | |
| 
 | |
|   if (NumberOfSenseKeys == 0) {
 | |
|     *Action = ACTION_NO_ACTION;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (!ScsiDiskHaveSenseKey (SenseData, NumberOfSenseKeys)) {
 | |
|     //
 | |
|     // No Sense Key returned from last submitted command
 | |
|     //
 | |
|     *Action = ACTION_NO_ACTION;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskIsNoMedia (SenseData, NumberOfSenseKeys)) {
 | |
|     ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
 | |
|     ScsiDiskDevice->BlkIo.Media->LastBlock    = 0;
 | |
|     *Action = ACTION_NO_ACTION;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) {
 | |
|     ScsiDiskDevice->BlkIo.Media->MediaId++;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) {
 | |
|     ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
 | |
|     ScsiDiskDevice->BlkIo.Media->LastBlock    = 0;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskIsHardwareError (SenseData, NumberOfSenseKeys)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   if (!ScsiDiskIsDriveReady (SenseData, NumberOfSenseKeys, &RetryLater)) {
 | |
|     if (RetryLater) {
 | |
|       *Action = ACTION_RETRY_COMMAND_LATER;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ScsiDiskReadCapacity (
 | |
|   SCSI_DISK_DEV           *ScsiDiskDevice,
 | |
|   BOOLEAN                 *NeedRetry,
 | |
|   EFI_SCSI_SENSE_DATA     **SenseDataArray,
 | |
|   UINTN                   *NumberOfSenseKeys
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice    - TODO: add argument description
 | |
|   NeedRetry         - TODO: add argument description
 | |
|   SenseDataArray    - TODO: add argument description
 | |
|   NumberOfSenseKeys - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_SCSI_DISK_CAPACITY_DATA CapacityData;
 | |
|   UINT32                      DataLength;
 | |
|   UINT8                       HostAdapterStatus;
 | |
|   UINT8                       TargetStatus;
 | |
|   EFI_STATUS                  CommandStatus;
 | |
|   EFI_STATUS                  Status;
 | |
|   UINT8                       Index;
 | |
|   UINT8                       MaxRetry;
 | |
|   UINT8                       SenseDataLength;
 | |
| 
 | |
|   SenseDataLength = 0;
 | |
|   ZeroMem (&CapacityData, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));
 | |
|   DataLength          = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);
 | |
| 
 | |
|   *NumberOfSenseKeys  = 0;
 | |
|   *NeedRetry          = FALSE;
 | |
|   //
 | |
|   // submit Read Capacity Command. in this call,not request sense data
 | |
|   //
 | |
|   CommandStatus = SubmitReadCapacityCommand (
 | |
|                     ScsiDiskDevice->ScsiIo,
 | |
|                     EfiScsiStallSeconds (1),
 | |
|                     NULL,
 | |
|                     &SenseDataLength,
 | |
|                     &HostAdapterStatus,
 | |
|                     &TargetStatus,
 | |
|                     (VOID *) &CapacityData,
 | |
|                     &DataLength,
 | |
|                     FALSE
 | |
|                     );
 | |
|   if (CommandStatus == EFI_SUCCESS) {
 | |
|     //
 | |
|     // no need to check HostAdapterStatus and TargetStatus
 | |
|     //
 | |
|     GetMediaInfo (ScsiDiskDevice, &CapacityData);
 | |
|     return EFI_SUCCESS;
 | |
|   } else if (CommandStatus == EFI_NOT_READY) {
 | |
|     //
 | |
|     // no need to check HostAdapterStatus and TargetStatus
 | |
|     //
 | |
|     *NeedRetry = TRUE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   } else if ((CommandStatus == EFI_INVALID_PARAMETER) || (CommandStatus == EFI_UNSUPPORTED)) {
 | |
|     //
 | |
|     // no need to check HostAdapterStatus and TargetStatus
 | |
|     //
 | |
|     *NeedRetry = FALSE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // go ahead to check HostAdapterStatus and TargetStatus
 | |
|   // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL)
 | |
|   //
 | |
|   
 | |
|   Status = CheckHostAdapterStatus (HostAdapterStatus);
 | |
|   if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) {
 | |
|     *NeedRetry = TRUE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   } else if (Status == EFI_DEVICE_ERROR) {
 | |
|     //
 | |
|     // reset the scsi channel
 | |
|     //
 | |
|     ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
 | |
|     *NeedRetry = FALSE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   Status = CheckTargetStatus (TargetStatus);
 | |
|   if (Status == EFI_NOT_READY) {
 | |
|     //
 | |
|     // reset the scsi device
 | |
|     //
 | |
|     ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
 | |
|     *NeedRetry = TRUE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   } else if (Status == EFI_DEVICE_ERROR) {
 | |
|     *NeedRetry = FALSE;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // if goes here, meant SubmitReadCapacityCommand() failed.
 | |
|   // if ScsiDiskRequestSenseKeys() succeeds at last,
 | |
|   // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE)
 | |
|   //
 | |
|   MaxRetry = 3;
 | |
|   for (Index = 0; Index < MaxRetry; Index++) {
 | |
| 
 | |
|     Status = ScsiDiskRequestSenseKeys (
 | |
|               ScsiDiskDevice,
 | |
|               NeedRetry,
 | |
|               SenseDataArray,
 | |
|               NumberOfSenseKeys,
 | |
|               TRUE
 | |
|               );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       *NeedRetry = TRUE;
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (!*NeedRetry) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
 | |
|   // set *NeedRetry = FALSE to avoid the outside caller try again.
 | |
|   //
 | |
|   *NeedRetry = FALSE;
 | |
|   return EFI_DEVICE_ERROR;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| CheckHostAdapterStatus (
 | |
|   UINT8   HostAdapterStatus
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   HostAdapterStatus - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_TIMEOUT - TODO: Add description for return value
 | |
|   EFI_NOT_READY - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   switch (HostAdapterStatus) {
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK:
 | |
|     return EFI_SUCCESS;
 | |
| 
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT:
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT:
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND:
 | |
|     return EFI_TIMEOUT;
 | |
| 
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT:
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR:
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED:
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN:
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET:
 | |
|     return EFI_NOT_READY;
 | |
| 
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE:
 | |
|   case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR:
 | |
|     return EFI_DEVICE_ERROR;
 | |
| 
 | |
|   default:
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| CheckTargetStatus (
 | |
|   UINT8   TargetStatus
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   TargetStatus  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_NOT_READY - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   switch (TargetStatus) {
 | |
|   case EFI_SCSI_IO_STATUS_TARGET_GOOD:
 | |
|   case EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION:
 | |
|   case EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET:
 | |
|     return EFI_SUCCESS;
 | |
| 
 | |
|   case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE:
 | |
|   case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET:
 | |
|   case EFI_SCSI_IO_STATUS_TARGET_BUSY:
 | |
|   case EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED:
 | |
|   case EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL:
 | |
|     return EFI_NOT_READY;
 | |
| 
 | |
|   case EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ScsiDiskRequestSenseKeys (
 | |
|   SCSI_DISK_DEV           *ScsiDiskDevice,
 | |
|   BOOLEAN                 *NeedRetry,
 | |
|   EFI_SCSI_SENSE_DATA     **SenseDataArray,
 | |
|   UINTN                   *NumberOfSenseKeys,
 | |
|   BOOLEAN                 AskResetIfError
 | |
|   )
 | |
| // TODO: function comment should start with '/*++'
 | |
| /*
 | |
|   Retrieve all sense keys from the device.
 | |
|   When encountering error during the process,
 | |
|   if retrieve sense keys before error encounterred,
 | |
|   return the sense keys with return status set to EFI_SUCCESS,
 | |
|   and NeedRetry set to FALSE; otherwize, return the proper return
 | |
|   status.
 | |
| */
 | |
| // TODO: function comment should end with '--*/'
 | |
| // TODO: function comment is missing 'Routine Description:'
 | |
| // TODO: function comment is missing 'Arguments:'
 | |
| // TODO: function comment is missing 'Returns:'
 | |
| // TODO:    ScsiDiskDevice - add argument and description to function comment
 | |
| // TODO:    NeedRetry - add argument and description to function comment
 | |
| // TODO:    SenseDataArray - add argument and description to function comment
 | |
| // TODO:    NumberOfSenseKeys - add argument and description to function comment
 | |
| // TODO:    AskResetIfError - add argument and description to function comment
 | |
| // TODO:    EFI_SUCCESS - add return value to function comment
 | |
| // TODO:    EFI_DEVICE_ERROR - add return value to function comment
 | |
| // TODO:    EFI_SUCCESS - add return value to function comment
 | |
| {
 | |
|   EFI_SCSI_SENSE_DATA *PtrSenseData;
 | |
|   UINT8               SenseDataLength;
 | |
|   BOOLEAN             SenseReq;
 | |
|   EFI_STATUS          Status;
 | |
|   EFI_STATUS          FallStatus;
 | |
|   UINT8               HostAdapterStatus;
 | |
|   UINT8               TargetStatus;
 | |
| 
 | |
|   FallStatus      = EFI_SUCCESS;
 | |
|   SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);
 | |
| 
 | |
|   ZeroMem (
 | |
|     ScsiDiskDevice->SenseData,
 | |
|     sizeof (EFI_SCSI_SENSE_DATA) * (ScsiDiskDevice->SenseDataNumber)
 | |
|     );
 | |
| 
 | |
|   *NumberOfSenseKeys  = 0;
 | |
|   *SenseDataArray     = ScsiDiskDevice->SenseData;
 | |
|   PtrSenseData        = ScsiDiskDevice->SenseData;
 | |
| 
 | |
|   for (SenseReq = TRUE; SenseReq;) {
 | |
| 
 | |
|     Status = SubmitRequestSenseCommand (
 | |
|               ScsiDiskDevice->ScsiIo,
 | |
|               EfiScsiStallSeconds (2),
 | |
|               PtrSenseData,
 | |
|               &SenseDataLength,
 | |
|               &HostAdapterStatus,
 | |
|               &TargetStatus
 | |
|               );
 | |
|     if ((Status == EFI_SUCCESS) || (Status == EFI_WARN_BUFFER_TOO_SMALL)) {
 | |
|       FallStatus = EFI_SUCCESS;
 | |
|     } else if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) { 
 | |
|       *NeedRetry  = TRUE;
 | |
|       FallStatus  = EFI_DEVICE_ERROR;
 | |
|     } else if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) {
 | |
|       *NeedRetry  = FALSE;
 | |
|       FallStatus  = EFI_DEVICE_ERROR;
 | |
|     } else if (Status == EFI_DEVICE_ERROR) {
 | |
|       if (AskResetIfError) {
 | |
|         ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
 | |
|       }
 | |
| 
 | |
|       FallStatus = EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (FallStatus)) {
 | |
|       if (*NumberOfSenseKeys != 0) {
 | |
|         *NeedRetry = FALSE;
 | |
|         return EFI_SUCCESS;
 | |
|       } else {
 | |
|         return EFI_DEVICE_ERROR;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     (*NumberOfSenseKeys) += 1;
 | |
| 
 | |
|     //
 | |
|     // no more sense key or number of sense keys exceeds predefined,
 | |
|     // skip the loop.
 | |
|     //
 | |
|     if ((PtrSenseData->Sense_Key == EFI_SCSI_SK_NO_SENSE) || 
 | |
|         (*NumberOfSenseKeys == ScsiDiskDevice->SenseDataNumber)) {
 | |
|       SenseReq = FALSE;
 | |
|     }
 | |
| 
 | |
|     PtrSenseData += 1;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| GetMediaInfo (
 | |
|   SCSI_DISK_DEV                 *ScsiDiskDevice,
 | |
|   EFI_SCSI_DISK_CAPACITY_DATA   *Capacity
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice  - TODO: add argument description
 | |
|   Capacity        - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   ScsiDiskDevice->BlkIo.Media->LastBlock =  (Capacity->LastLba3 << 24) |
 | |
|                                             (Capacity->LastLba2 << 16) |
 | |
|                                             (Capacity->LastLba1 << 8)  |
 | |
|                                              Capacity->LastLba0;
 | |
| 
 | |
|   ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
 | |
|   ScsiDiskDevice->BlkIo.Media->BlockSize = (Capacity->BlockSize3 << 24) |
 | |
|                                            (Capacity->BlockSize2 << 16) | 
 | |
|                                            (Capacity->BlockSize1 << 8)  |
 | |
|                                             Capacity->BlockSize0;
 | |
|   if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_DISK) {
 | |
|     ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_CDROM) {
 | |
|     ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800;
 | |
|   }
 | |
| }
 | |
| 
 | |
| VOID
 | |
| ParseInquiryData (
 | |
|   SCSI_DISK_DEV   *ScsiDiskDevice
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   ScsiDiskDevice->FixedDevice               = (BOOLEAN) (ScsiDiskDevice->InquiryData.RMB ? 0 : 1);
 | |
|   ScsiDiskDevice->BlkIoMedia.RemovableMedia = (BOOLEAN) (!ScsiDiskDevice->FixedDevice);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ScsiDiskReadSectors (
 | |
|   SCSI_DISK_DEV     *ScsiDiskDevice,
 | |
|   VOID              *Buffer,
 | |
|   EFI_LBA           Lba,
 | |
|   UINTN             NumberOfBlocks
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice  - TODO: add argument description
 | |
|   Buffer          - TODO: add argument description
 | |
|   Lba             - TODO: add argument description
 | |
|   NumberOfBlocks  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINTN               BlocksRemaining;
 | |
|   UINT32              Lba32;
 | |
|   UINT8               *PtrBuffer;
 | |
|   UINT32              BlockSize;
 | |
|   UINT32              ByteCount;
 | |
|   UINT32              MaxBlock;
 | |
|   UINT32              SectorCount;
 | |
|   UINT64              Timeout;
 | |
|   EFI_STATUS          Status;
 | |
|   UINT8               Index;
 | |
|   UINT8               MaxRetry;
 | |
|   BOOLEAN             NeedRetry;
 | |
|   EFI_SCSI_SENSE_DATA *SenseData;
 | |
|   UINTN               NumberOfSenseKeys;
 | |
| 
 | |
|   SenseData         = NULL;
 | |
|   NumberOfSenseKeys = 0;
 | |
| 
 | |
|   Status            = EFI_SUCCESS;
 | |
| 
 | |
|   BlocksRemaining   = NumberOfBlocks;
 | |
|   BlockSize         = ScsiDiskDevice->BlkIo.Media->BlockSize;
 | |
|   //
 | |
|   // limit the data bytes that can be transferred by one Read(10) Command
 | |
|   //
 | |
|   MaxBlock  = 65536;
 | |
| 
 | |
|   PtrBuffer = Buffer;
 | |
|   Lba32     = (UINT32) Lba;
 | |
| 
 | |
|   while (BlocksRemaining > 0) {
 | |
| 
 | |
|     if (BlocksRemaining <= MaxBlock) {
 | |
| 
 | |
|       SectorCount = (UINT16) BlocksRemaining;
 | |
|     } else {
 | |
| 
 | |
|       SectorCount = MaxBlock;
 | |
|     }
 | |
| 
 | |
|     ByteCount = SectorCount * BlockSize;
 | |
|     Timeout   = EfiScsiStallSeconds (2);
 | |
| 
 | |
|     MaxRetry  = 2;
 | |
|     for (Index = 0; Index < MaxRetry; Index++) {
 | |
| 
 | |
|       Status = ScsiDiskRead10 (
 | |
|                 ScsiDiskDevice,
 | |
|                 &NeedRetry,
 | |
|                 &SenseData,
 | |
|                 &NumberOfSenseKeys,
 | |
|                 Timeout,
 | |
|                 PtrBuffer,
 | |
|                 &ByteCount,
 | |
|                 Lba32,
 | |
|                 SectorCount
 | |
|                 );
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if (!NeedRetry) {
 | |
|         return EFI_DEVICE_ERROR;
 | |
|       }
 | |
| 
 | |
|     }
 | |
| 
 | |
|     if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // actual transferred sectors
 | |
|     //
 | |
|     SectorCount = ByteCount / BlockSize;
 | |
| 
 | |
|     Lba32 += SectorCount;
 | |
|     PtrBuffer = PtrBuffer + SectorCount * BlockSize;
 | |
|     BlocksRemaining -= SectorCount;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ScsiDiskWriteSectors (
 | |
|   SCSI_DISK_DEV     *ScsiDiskDevice,
 | |
|   VOID              *Buffer,
 | |
|   EFI_LBA           Lba,
 | |
|   UINTN             NumberOfBlocks
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice  - TODO: add argument description
 | |
|   Buffer          - TODO: add argument description
 | |
|   Lba             - TODO: add argument description
 | |
|   NumberOfBlocks  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_DEVICE_ERROR - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINTN               BlocksRemaining;
 | |
|   UINT32              Lba32;
 | |
|   UINT8               *PtrBuffer;
 | |
|   UINT32              BlockSize;
 | |
|   UINT32              ByteCount;
 | |
|   UINT32              MaxBlock;
 | |
|   UINT32              SectorCount;
 | |
|   UINT64              Timeout;
 | |
|   EFI_STATUS          Status;
 | |
|   UINT8               Index;
 | |
|   UINT8               MaxRetry;
 | |
|   BOOLEAN             NeedRetry;
 | |
|   EFI_SCSI_SENSE_DATA *SenseData;
 | |
|   UINTN               NumberOfSenseKeys;
 | |
| 
 | |
|   SenseData         = NULL;
 | |
|   NumberOfSenseKeys = 0;
 | |
| 
 | |
|   Status            = EFI_SUCCESS;
 | |
| 
 | |
|   BlocksRemaining   = NumberOfBlocks;
 | |
|   BlockSize         = ScsiDiskDevice->BlkIo.Media->BlockSize;
 | |
|   //
 | |
|   // limit the data bytes that can be transferred by one Write(10) Command
 | |
|   //
 | |
|   MaxBlock  = 65536;
 | |
| 
 | |
|   PtrBuffer = Buffer;
 | |
|   Lba32     = (UINT32) Lba;
 | |
| 
 | |
|   while (BlocksRemaining > 0) {
 | |
| 
 | |
|     if (BlocksRemaining <= MaxBlock) {
 | |
| 
 | |
|       SectorCount = (UINT16) BlocksRemaining;
 | |
|     } else {
 | |
| 
 | |
|       SectorCount = MaxBlock;
 | |
|     }
 | |
| 
 | |
|     ByteCount = SectorCount * BlockSize;
 | |
|     Timeout   = EfiScsiStallSeconds (2);
 | |
|     MaxRetry  = 2;
 | |
|     for (Index = 0; Index < MaxRetry; Index++) {
 | |
|       Status = ScsiDiskWrite10 (
 | |
|                 ScsiDiskDevice,
 | |
|                 &NeedRetry,
 | |
|                 &SenseData,
 | |
|                 &NumberOfSenseKeys,
 | |
|                 Timeout,
 | |
|                 PtrBuffer,
 | |
|                 &ByteCount,
 | |
|                 Lba32,
 | |
|                 SectorCount
 | |
|                 );
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if (!NeedRetry) {
 | |
|         return EFI_DEVICE_ERROR;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     //
 | |
|     // actual transferred sectors
 | |
|     //
 | |
|     SectorCount = ByteCount / BlockSize;
 | |
| 
 | |
|     Lba32 += SectorCount;
 | |
|     PtrBuffer = PtrBuffer + SectorCount * BlockSize;
 | |
|     BlocksRemaining -= SectorCount;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ScsiDiskRead10 (
 | |
|   SCSI_DISK_DEV         *ScsiDiskDevice,
 | |
|   BOOLEAN               *NeedRetry,
 | |
|   EFI_SCSI_SENSE_DATA   **SenseDataArray,
 | |
|   UINTN                 *NumberOfSenseKeys,
 | |
|   UINT64                Timeout,
 | |
|   UINT8                 *DataBuffer,
 | |
|   UINT32                *DataLength,
 | |
|   UINT32                StartLba,
 | |
|   UINT32                SectorSize
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice    - TODO: add argument description
 | |
|   NeedRetry         - TODO: add argument description
 | |
|   SenseDataArray    - TODO: add argument description
 | |
|   NumberOfSenseKeys - TODO: add argument description
 | |
|   Timeout           - TODO: add argument description
 | |
|   DataBuffer        - TODO: add argument description
 | |
|   DataLength        - TODO: add argument description
 | |
|   StartLba          - TODO: add argument description
 | |
|   SectorSize        - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT8       SenseDataLength;
 | |
|   EFI_STATUS  Status;
 | |
|   UINT8       HostAdapterStatus;
 | |
|   UINT8       TargetStatus;
 | |
| 
 | |
|   *NeedRetry          = FALSE;
 | |
|   *NumberOfSenseKeys  = 0;
 | |
|   SenseDataLength     = 0;
 | |
|   Status = SubmitRead10Command (
 | |
|             ScsiDiskDevice->ScsiIo,
 | |
|             Timeout,
 | |
|             NULL,
 | |
|             &SenseDataLength,
 | |
|             &HostAdapterStatus,
 | |
|             &TargetStatus,
 | |
|             DataBuffer,
 | |
|             DataLength,
 | |
|             StartLba,
 | |
|             SectorSize
 | |
|             );
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ScsiDiskWrite10 (
 | |
|   SCSI_DISK_DEV         *ScsiDiskDevice,
 | |
|   BOOLEAN               *NeedRetry,
 | |
|   EFI_SCSI_SENSE_DATA   **SenseDataArray,
 | |
|   UINTN                 *NumberOfSenseKeys,
 | |
|   UINT64                Timeout,
 | |
|   UINT8                 *DataBuffer,
 | |
|   UINT32                *DataLength,
 | |
|   UINT32                StartLba,
 | |
|   UINT32                SectorSize
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice    - TODO: add argument description
 | |
|   NeedRetry         - TODO: add argument description
 | |
|   SenseDataArray    - TODO: add argument description
 | |
|   NumberOfSenseKeys - TODO: add argument description
 | |
|   Timeout           - TODO: add argument description
 | |
|   DataBuffer        - TODO: add argument description
 | |
|   DataLength        - TODO: add argument description
 | |
|   StartLba          - TODO: add argument description
 | |
|   SectorSize        - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT8       SenseDataLength;
 | |
|   UINT8       HostAdapterStatus;
 | |
|   UINT8       TargetStatus;
 | |
| 
 | |
|   *NeedRetry          = FALSE;
 | |
|   *NumberOfSenseKeys  = 0;
 | |
|   SenseDataLength     = 0;
 | |
|   Status = SubmitWrite10Command (
 | |
|             ScsiDiskDevice->ScsiIo,
 | |
|             Timeout,
 | |
|             NULL,
 | |
|             &SenseDataLength,
 | |
|             &HostAdapterStatus,
 | |
|             &TargetStatus,
 | |
|             DataBuffer,
 | |
|             DataLength,
 | |
|             StartLba,
 | |
|             SectorSize
 | |
|             );
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| ScsiDiskIsNoMedia (
 | |
|   IN  EFI_SCSI_SENSE_DATA   *SenseData,
 | |
|   IN  UINTN                 SenseCounts
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   SenseData   - TODO: add argument description
 | |
|   SenseCounts - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_SCSI_SENSE_DATA *SensePtr;
 | |
|   UINTN               Index;
 | |
|   BOOLEAN             IsNoMedia;
 | |
| 
 | |
|   IsNoMedia = FALSE;
 | |
|   SensePtr  = SenseData;
 | |
| 
 | |
|   for (Index = 0; Index < SenseCounts; Index++) {
 | |
| 
 | |
|     //
 | |
|     // Sense Key is EFI_SCSI_SK_NOT_READY (0x2),
 | |
|     // Additional Sense Code is ASC_NO_MEDIA (0x3A)
 | |
|     //
 | |
|     if ((SensePtr->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
 | |
|         (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA)) {
 | |
|       IsNoMedia = TRUE;
 | |
|     }
 | |
| 
 | |
|     SensePtr++;
 | |
|   }
 | |
| 
 | |
|   return IsNoMedia;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| ScsiDiskIsMediaError (
 | |
|   IN  EFI_SCSI_SENSE_DATA   *SenseData,
 | |
|   IN  UINTN                 SenseCounts
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   SenseData   - TODO: add argument description
 | |
|   SenseCounts - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_SCSI_SENSE_DATA *SensePtr;
 | |
|   UINTN               Index;
 | |
|   BOOLEAN             IsError;
 | |
| 
 | |
|   IsError   = FALSE;
 | |
|   SensePtr  = SenseData;
 | |
| 
 | |
|   for (Index = 0; Index < SenseCounts; Index++) {
 | |
| 
 | |
|     switch (SensePtr->Sense_Key) {
 | |
| 
 | |
|     case EFI_SCSI_SK_MEDIUM_ERROR:
 | |
|       //
 | |
|       // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3)
 | |
|       //
 | |
|       switch (SensePtr->Addnl_Sense_Code) {
 | |
| 
 | |
|       //
 | |
|       // fall through
 | |
|       //
 | |
|       case EFI_SCSI_ASC_MEDIA_ERR1:
 | |
| 
 | |
|       //
 | |
|       // fall through
 | |
|       //
 | |
|       case EFI_SCSI_ASC_MEDIA_ERR2:
 | |
| 
 | |
|       //
 | |
|       // fall through
 | |
|       //
 | |
|       case EFI_SCSI_ASC_MEDIA_ERR3:
 | |
|       case EFI_SCSI_ASC_MEDIA_ERR4:
 | |
|         IsError = TRUE;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case EFI_SCSI_SK_NOT_READY:
 | |
|       //
 | |
|       // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
 | |
|       //
 | |
|       switch (SensePtr->Addnl_Sense_Code) {
 | |
|       //
 | |
|       // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
 | |
|       //
 | |
|       case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN:
 | |
|         IsError = TRUE;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         break;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     SensePtr++;
 | |
|   }
 | |
| 
 | |
|   return IsError;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| ScsiDiskIsHardwareError (
 | |
|   IN  EFI_SCSI_SENSE_DATA   *SenseData,
 | |
|   IN  UINTN                 SenseCounts
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   SenseData   - TODO: add argument description
 | |
|   SenseCounts - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_SCSI_SENSE_DATA *SensePtr;
 | |
|   UINTN               Index;
 | |
|   BOOLEAN             IsError;
 | |
| 
 | |
|   IsError   = FALSE;
 | |
|   SensePtr  = SenseData;
 | |
| 
 | |
|   for (Index = 0; Index < SenseCounts; Index++) {
 | |
|     
 | |
|     //
 | |
|     // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4)
 | |
|     //
 | |
|     if (SensePtr->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) {
 | |
|       IsError = TRUE;
 | |
|     }
 | |
| 
 | |
|     SensePtr++;
 | |
|   }
 | |
| 
 | |
|   return IsError;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| ScsiDiskIsMediaChange (
 | |
|   IN  EFI_SCSI_SENSE_DATA   *SenseData,
 | |
|   IN  UINTN                 SenseCounts
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   SenseData   - TODO: add argument description
 | |
|   SenseCounts - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_SCSI_SENSE_DATA *SensePtr;
 | |
|   UINTN               Index;
 | |
|   BOOLEAN             IsMediaChanged;
 | |
| 
 | |
|   IsMediaChanged  = FALSE;
 | |
|   SensePtr        = SenseData;
 | |
| 
 | |
|   for (Index = 0; Index < SenseCounts; Index++) {
 | |
|     //
 | |
|     // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6),
 | |
|     // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28)
 | |
|     //
 | |
|     if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
 | |
|         (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE)) {
 | |
|       IsMediaChanged = TRUE;
 | |
|     }
 | |
| 
 | |
|     SensePtr++;
 | |
|   }
 | |
| 
 | |
|   return IsMediaChanged;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| ScsiDiskIsResetBefore (
 | |
|   IN  EFI_SCSI_SENSE_DATA   *SenseData,
 | |
|   IN  UINTN                 SenseCounts
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   SenseData   - TODO: add argument description
 | |
|   SenseCounts - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_SCSI_SENSE_DATA *SensePtr;
 | |
|   UINTN               Index;
 | |
|   BOOLEAN             IsResetBefore;
 | |
| 
 | |
|   IsResetBefore = FALSE;
 | |
|   SensePtr      = SenseData;
 | |
| 
 | |
|   for (Index = 0; Index < SenseCounts; Index++) {
 | |
|     
 | |
|     //
 | |
|     // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6)
 | |
|     // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29)
 | |
|     //
 | |
|     if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
 | |
|         (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_RESET)) {
 | |
|       IsResetBefore = TRUE;
 | |
|     }
 | |
| 
 | |
|     SensePtr++;
 | |
|   }
 | |
| 
 | |
|   return IsResetBefore;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| ScsiDiskIsDriveReady (
 | |
|   IN  EFI_SCSI_SENSE_DATA   *SenseData,
 | |
|   IN  UINTN                 SenseCounts,
 | |
|   OUT BOOLEAN               *RetryLater
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   SenseData   - TODO: add argument description
 | |
|   SenseCounts - TODO: add argument description
 | |
|   RetryLater  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_SCSI_SENSE_DATA *SensePtr;
 | |
|   UINTN               Index;
 | |
|   BOOLEAN             IsReady;
 | |
| 
 | |
|   IsReady     = TRUE;
 | |
|   *RetryLater = FALSE;
 | |
|   SensePtr    = SenseData;
 | |
| 
 | |
|   for (Index = 0; Index < SenseCounts; Index++) {
 | |
| 
 | |
|     switch (SensePtr->Sense_Key) {
 | |
| 
 | |
|     case EFI_SCSI_SK_NOT_READY:
 | |
|       //
 | |
|       // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
 | |
|       //
 | |
|       switch (SensePtr->Addnl_Sense_Code) {
 | |
|       case EFI_SCSI_ASC_NOT_READY:
 | |
|         //
 | |
|         // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4)
 | |
|         //
 | |
|         switch (SensePtr->Addnl_Sense_Code_Qualifier) {
 | |
|         case EFI_SCSI_ASCQ_IN_PROGRESS:
 | |
|           //
 | |
|           // Additional Sense Code Qualifier is
 | |
|           // EFI_SCSI_ASCQ_IN_PROGRESS (0x1)
 | |
|           //
 | |
|           IsReady     = FALSE;
 | |
|           *RetryLater = TRUE;
 | |
|           break;
 | |
| 
 | |
|         default:
 | |
|           IsReady     = FALSE;
 | |
|           *RetryLater = FALSE;
 | |
|           break;
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         break;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     SensePtr++;
 | |
|   }
 | |
| 
 | |
|   return IsReady;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| ScsiDiskHaveSenseKey (
 | |
|   IN  EFI_SCSI_SENSE_DATA   *SenseData,
 | |
|   IN  UINTN                 SenseCounts
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   SenseData   - TODO: add argument description
 | |
|   SenseCounts - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_SCSI_SENSE_DATA *SensePtr;
 | |
|   UINTN               Index;
 | |
|   BOOLEAN             HaveSenseKey;
 | |
| 
 | |
|   if (SenseCounts == 0) {
 | |
|     HaveSenseKey = FALSE;
 | |
|   } else {
 | |
|     HaveSenseKey = TRUE;
 | |
|   }
 | |
| 
 | |
|   SensePtr = SenseData;
 | |
| 
 | |
|   for (Index = 0; Index < SenseCounts; Index++) {
 | |
|     
 | |
|     //
 | |
|     // Sense Key is SK_NO_SENSE (0x0)
 | |
|     //
 | |
|     if ((SensePtr->Sense_Key == EFI_SCSI_SK_NO_SENSE) &&
 | |
|         (Index == 0)) {
 | |
|       HaveSenseKey = FALSE;
 | |
|     }
 | |
| 
 | |
|     SensePtr++;
 | |
|   }
 | |
| 
 | |
|   return HaveSenseKey;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| ReleaseScsiDiskDeviceResources (
 | |
|   IN  SCSI_DISK_DEV   *ScsiDiskDevice
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ScsiDiskDevice  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   if (ScsiDiskDevice == NULL) {
 | |
|     return ;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskDevice->SenseData != NULL) {
 | |
|     gBS->FreePool (ScsiDiskDevice->SenseData);
 | |
|     ScsiDiskDevice->SenseData = NULL;
 | |
|   }
 | |
| 
 | |
|   if (ScsiDiskDevice->ControllerNameTable != NULL) {
 | |
|     FreeUnicodeStringTable (ScsiDiskDevice->ControllerNameTable);
 | |
|     ScsiDiskDevice->ControllerNameTable = NULL;
 | |
|   }
 | |
| 
 | |
|   gBS->FreePool (ScsiDiskDevice);
 | |
| 
 | |
|   ScsiDiskDevice = NULL;
 | |
| }
 |