scsilib.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 671 行 · 第 1/2 页

C
671
字号
/*++

Copyright (c) 2004 - 2006, 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:

    ScsiLib.c
    
Abstract: 
    

Revision History
--*/

#include "ScsiLib.h"

EFI_STATUS
SubmitTestUnitReadyCommand (
  IN  EFI_SCSI_IO_PROTOCOL  *ScsiIo,
  IN  UINT64                Timeout,
  OUT VOID                  *SenseData,
  OUT UINT8                 *SenseDataLength,
  OUT UINT8                 *HostAdapterStatus,
  OUT UINT8                 *TargetStatus
  )
/*++

Routine Description:

  Function tests the ready status of SCSI unit.

Arguments:

  ScsiIo               - A pointer to SCSI IO protocol.
  Timeout              - The length of timeout period.
  SenseData            - A pointer to output sense data.
  SenseDataLength      - The length of output sense data.
  HostAdapterStatus    - The status of Host Adapter.
  TargetStatus         - The status of the target.

Returns:

  EFI_SUCCESS                - The status of the unit is tested successfully.
  EFI_WARN_BUFFER_TOO_SMALL  - The SCSI Request Packet was executed, 
                             but the entire DataBuffer could not be transferred.
                             The actual number of bytes transferred is returned
                             in TransferLength.
  EFI_NOT_READY              - The SCSI Request Packet could not be sent because 
                             there are too many SCSI Command Packets already 
                             queued.
  EFI_DEVICE_ERROR           - A device error occurred while attempting to send 
                             the SCSI Request Packet.
  EFI_INVALID_PARAMETER      - The contents of CommandPacket are invalid.  
  EFI_UNSUPPORTED            - The command described by the SCSI Request Packet
                             is not supported by the SCSI initiator(i.e., SCSI 
                             Host Controller).
  EFI_TIMEOUT                - A timeout occurred while waiting for the SCSI 
                             Request Packet to execute.

--*/
{
  EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
  UINT64                          Lun;
  UINT8                           *Target;
  UINT8                           TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
  EFI_STATUS                      Status;
  UINT8                           Cdb[6];


  EfiZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
  EfiZeroMem (Cdb, 6);

  CommandPacket.Timeout         = Timeout;
  CommandPacket.InDataBuffer    = NULL;
  CommandPacket.InTransferLength= 0;
  CommandPacket.OutDataBuffer    = NULL;
  CommandPacket.OutTransferLength= 0;
  CommandPacket.SenseData       = SenseData;
  CommandPacket.Cdb             = Cdb;
  //
  // Fill Cdb for Test Unit Ready Command
  //
  Target = &TargetArray[0];
  ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);

  Cdb[0]                        = EFI_SCSI_OP_TEST_UNIT_READY;
  Cdb[1]                        = (UINT8) (Lun & 0xe0);
  CommandPacket.CdbLength       = (UINT8) 6;
  CommandPacket.SenseDataLength = *SenseDataLength;

  Status                        = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL);

  *HostAdapterStatus            = CommandPacket.HostAdapterStatus;
  *TargetStatus                 = CommandPacket.TargetStatus;
  *SenseDataLength              = CommandPacket.SenseDataLength;

  return Status;
}

EFI_STATUS
SubmitInquiryCommand (
  IN  EFI_SCSI_IO_PROTOCOL  *ScsiIo,
  IN  UINT64                Timeout,
  IN  VOID                  *SenseData,
  IN OUT UINT8              *SenseDataLength,
  OUT UINT8                 *HostAdapterStatus,
  OUT UINT8                 *TargetStatus,
  IN OUT VOID               *InquiryDataBuffer,
  IN OUT UINT32             *InquiryDataLength,
  IN  BOOLEAN               EnableVitalProductData
  )
/*++

Routine Description:

  Function to submit SCSI inquiry command.

Arguments:

  ScsiIo               - A pointer to SCSI IO protocol.
  Timeout              - The length of timeout period.
  SenseData            - A pointer to output sense data.
  SenseDataLength      - The length of output sense data.
  HostAdapterStatus    - The status of Host Adapter.
  TargetStatus         - The status of the target.
  InquiryDataBuffer    - A pointer to inquiry data buffer.
  InquiryDataLength    - The length of inquiry data buffer.
  EnableVitalProductData - Boolean to enable Vital Product Data.

Returns:

  EFI_SUCCESS                - The status of the unit is tested successfully.
  EFI_WARN_BUFFER_TOO_SMALL  - The SCSI Request Packet was executed, 
                               but the entire DataBuffer could not be transferred.
                               The actual number of bytes transferred is returned
                               in TransferLength.
  EFI_NOT_READY              - The SCSI Request Packet could not be sent because 
                               there are too many SCSI Command Packets already 
                               queued.
  EFI_DEVICE_ERROR           - A device error occurred while attempting to send 
                               the SCSI Request Packet.
  EFI_INVALID_PARAMETER      - The contents of CommandPacket are invalid.  
  EFI_UNSUPPORTED            - The command described by the SCSI Request Packet
                               is not supported by the SCSI initiator(i.e., SCSI 
                               Host Controller).
  EFI_TIMEOUT                - A timeout occurred while waiting for the SCSI 
                               Request Packet to execute.

--*/
{
  EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
  UINT64                          Lun;
  UINT8                           *Target;
  UINT8                           TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
  EFI_STATUS                      Status;
  UINT8                           Cdb[6];

  EfiZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
  EfiZeroMem (Cdb, 6);

  CommandPacket.Timeout         = Timeout;
  CommandPacket.InDataBuffer    = InquiryDataBuffer;
  CommandPacket.InTransferLength= *InquiryDataLength;
  CommandPacket.SenseData       = SenseData;
  CommandPacket.SenseDataLength = *SenseDataLength;
  CommandPacket.Cdb             = Cdb;

  Target = &TargetArray[0];
  ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);

  Cdb[0]  = EFI_SCSI_OP_INQUIRY;
  Cdb[1]  = (UINT8) (Lun & 0xe0);
  if (EnableVitalProductData) {
    Cdb[1] |= 0x01;
  }

  if (*InquiryDataLength > 0xff) {
    *InquiryDataLength = 0xff;
  }

  Cdb[4]                      = (UINT8) (*InquiryDataLength);
  CommandPacket.CdbLength     = (UINT8) 6;
  CommandPacket.DataDirection = EFI_SCSI_DATA_IN;

  Status                      = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL);

  *HostAdapterStatus          = CommandPacket.HostAdapterStatus;
  *TargetStatus               = CommandPacket.TargetStatus;
  *SenseDataLength            = CommandPacket.SenseDataLength;
  *InquiryDataLength          = CommandPacket.InTransferLength;

  return Status;
}

EFI_STATUS
SubmitModeSense10Command (
  IN  EFI_SCSI_IO_PROTOCOL    *ScsiIo,
  IN  UINT64                  Timeout,
  IN  VOID                    *SenseData,
  IN OUT UINT8                *SenseDataLength,
  OUT UINT8                   *HostAdapterStatus,
  OUT UINT8                   *TargetStatus,
  IN  VOID                    *DataBuffer,
  IN OUT UINT32               *DataLength,
  IN  UINT8                   DBDField, OPTIONAL
  IN  UINT8                   PageControl,
  IN  UINT8                   PageCode
  )
/*++

Routine Description:

  Function to submit SCSI mode sense 10 command.

Arguments:

  ScsiIo               - A pointer to SCSI IO protocol.
  Timeout              - The length of timeout period.
  SenseData            - A pointer to output sense data.
  SenseDataLength      - The length of output sense data.
  HostAdapterStatus    - The status of Host Adapter.
  TargetStatus         - The status of the target.
  DataBuffer           - A pointer to input data buffer.
  DataLength           - The length of input data buffer.
  DBDField             - The DBD Field (Optional).
  PageControl          - Page Control.
  PageCode             - Page code.

Returns:

  EFI_SUCCESS                - The status of the unit is tested successfully.
  EFI_WARN_BUFFER_TOO_SMALL  - The SCSI Request Packet was executed, 
                               but the entire DataBuffer could not be transferred.
                               The actual number of bytes transferred is returned
                               in TransferLength.
  EFI_NOT_READY              - The SCSI Request Packet could not be sent because 
                               there are too many SCSI Command Packets already 
                               queued.
  EFI_DEVICE_ERROR           - A device error occurred while attempting to send 
                               the SCSI Request Packet.
  EFI_INVALID_PARAMETER      - The contents of CommandPacket are invalid.  
  EFI_UNSUPPORTED            - The command described by the SCSI Request Packet
                               is not supported by the SCSI initiator(i.e., SCSI 
                               Host Controller).
  EFI_TIMEOUT                - A timeout occurred while waiting for the SCSI 
                               Request Packet to execute.

--*/
{
  EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
  UINT64                          Lun;
  UINT8                           *Target;
  UINT8                           TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
  EFI_STATUS                      Status;
  UINT8                           Cdb[10];

  EfiZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
  EfiZeroMem (Cdb, 10);

  CommandPacket.Timeout         = Timeout;
  CommandPacket.InDataBuffer    = DataBuffer;
  CommandPacket.SenseData       = SenseData;
  CommandPacket.InTransferLength= *DataLength;
  CommandPacket.Cdb             = Cdb;
  //
  // Fill Cdb for Mode Sense (10) Command
  //
  Target = &TargetArray[0];
  ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);

  Cdb[0]                        = EFI_SCSI_OP_MODE_SEN10;
  Cdb[1]                        = (UINT8) (Lun & 0xe0 + (DBDField << 3) & 0x08);
  Cdb[2]                        = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f));
  Cdb[7]                        = (UINT8) (*DataLength >> 8);
  Cdb[8]                        = (UINT8) (*DataLength);

  CommandPacket.CdbLength       = 10;
  CommandPacket.DataDirection   = EFI_SCSI_DATA_IN;
  CommandPacket.SenseDataLength = *SenseDataLength;

  Status                        = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL);

  *HostAdapterStatus            = CommandPacket.HostAdapterStatus;
  *TargetStatus                 = CommandPacket.TargetStatus;
  *SenseDataLength              = CommandPacket.SenseDataLength;
  *DataLength                   = CommandPacket.InTransferLength;

  return Status;
}

EFI_STATUS
SubmitRequestSenseCommand (
  IN  EFI_SCSI_IO_PROTOCOL  *ScsiIo,
  IN  UINT64                Timeout,
  IN  VOID                  *SenseData,
  IN OUT UINT8              *SenseDataLength,
  OUT UINT8                 *HostAdapterStatus,
  OUT UINT8                 *TargetStatus
  )
/*++

Routine Description:

  Function to submit SCSI request sense command.

Arguments:

  ScsiIo               - A pointer to SCSI IO protocol.
  Timeout              - The length of timeout period.
  SenseData            - A pointer to output sense data.
  SenseDataLength      - The length of output sense data.
  HostAdapterStatus    - The status of Host Adapter.
  TargetStatus         - The status of the target.

Returns:

  EFI_SUCCESS                - The status of the unit is tested successfully.
  EFI_WARN_BUFFER_TOO_SMALL  - The SCSI Request Packet was executed, 
                               but the entire DataBuffer could not be transferred.
                               The actual number of bytes transferred is returned
                               in TransferLength.
  EFI_NOT_READY              - The SCSI Request Packet could not be sent because 
                               there are too many SCSI Command Packets already 
                               queued.
  EFI_DEVICE_ERROR           - A device error occurred while attempting to send 
                               the SCSI Request Packet.
  EFI_INVALID_PARAMETER      - The contents of CommandPacket are invalid.  
  EFI_UNSUPPORTED            - The command described by the SCSI Request Packet
                               is not supported by the SCSI initiator(i.e., SCSI 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?