scsibus.c

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

C
1,046
字号
/*++

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:

    scsibus.c
    
Abstract: 

    SCSI Bus Driver

Revision History
--*/

#include "scsibus.h"
#include "ScsiLib.h"


EFI_STATUS
EFIAPI
SCSIBusDriverBindingSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  );

EFI_STATUS
EFIAPI
SCSIBusDriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  );

EFI_STATUS
EFIAPI
SCSIBusDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
  IN  EFI_HANDLE                      Controller,
  IN  UINTN                           NumberOfChildren,
  IN  EFI_HANDLE                      *ChildHandleBuffer
  );

EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {
  SCSIBusDriverBindingSupported,
  SCSIBusDriverBindingStart,
  SCSIBusDriverBindingStop,
  0x10,
  NULL,
  NULL
};


//
// The ScsiBusProtocol is just used to locate ScsiBusDev
// structure in the SCSIBusDriverBindingStop(). Then we can
// Close all opened protocols and release this structure.
//
STATIC EFI_GUID  mScsiBusProtocolGuid = EFI_SCSI_BUS_PROTOCOL_GUID;


EFI_DRIVER_ENTRY_POINT (ScsiBusControllerDriverEntryPoint)

EFI_STATUS
EFIAPI
ScsiBusControllerDriverEntryPoint (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
/*++

Routine Description:

  Entry point for EFI drivers.

Arguments:

  ImageHandle - EFI_HANDLE
  SystemTable - EFI_SYSTEM_TABLE

Returns:

  EFI_SUCCESS
  Others 
--*/
{
  EFI_STATUS  Status;

  //
  // Initialize the EFI Library
  //
  Status = EfiLibInstallAllDriverProtocols (
             ImageHandle,
             SystemTable,
             &gSCSIBusDriverBinding,
             ImageHandle,
             &gScsiBusComponentName,
             NULL,
             NULL
             );
  return Status;
}

EFI_STATUS
EFIAPI
SCSIBusDriverBindingSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
/*++

Routine Description:

  Test to see if this driver supports ControllerHandle. Any ControllerHandle
  that has ExtScsiPassThruProtocol/ScsiPassThruProtocol installed will be supported.

Arguments:

  This                - Protocol instance pointer.
  Controller          - Handle of device to test
  RemainingDevicePath - Not used

Returns:

  EFI_SUCCESS         - This driver supports this device.
  EFI_UNSUPPORTED     - This driver does not support this device.

--*/

{
  EFI_STATUS  Status;

  //
  // If RemainingDevicePath is not NULL, it should verify that the first device
  // path node in RemainingDevicePath is an ATAPI Device path node.
  //
  if (RemainingDevicePath != NULL) {
    if ((RemainingDevicePath->Type != MESSAGING_DEVICE_PATH) ||
        (RemainingDevicePath->SubType != MSG_ATAPI_DP) ||
        (DevicePathNodeLength (RemainingDevicePath) != sizeof(ATAPI_DEVICE_PATH))) {
      return EFI_UNSUPPORTED;
    }
  }
  //
  // Check for the existence of Extended SCSI Pass Thru Protocol and SCSI Pass Thru Protocol
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiExtScsiPassThruProtocolGuid,
                  NULL,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                  );
  if (EFI_ERROR (Status)) {
    Status = gBS->OpenProtocol (
                    Controller,
                    &gEfiScsiPassThruProtocolGuid,
                    NULL,
                    This->DriverBindingHandle,
                    Controller,
                    EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                    );
    if (EFI_ERROR (Status)) {
      Status = EFI_UNSUPPORTED;
    }
  }
  return Status;
}

EFI_STATUS
EFIAPI
SCSIBusDriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
/*++

Routine Description:
  Starting the SCSI Bus Driver

Arguments:
  This                - Protocol instance pointer.
  Controller          - Handle of device to test
  RemainingDevicePath - Not used

Returns:
  EFI_SUCCESS         - This driver supports this device.
  EFI_UNSUPPORTED     - This driver does not support this device.
  EFI_DEVICE_ERROR    - This driver cannot be started due to device Error

--*/
{
  EFI_STATUS                  Status;
  UINT32                      StartPun;
  UINT64                      StartLun;
  UINT32                      Pun;
  UINT64                      Lun;
  BOOLEAN                     ScanOtherPuns;
  SCSI_BUS_DEVICE             *ScsiBusDev;
  UINT8                       **TargetId;
  UINT8                       Target[4];

  TargetId = NULL;
  //
  // Allocate SCSI_BUS_DEVICE structure
  //
  ScsiBusDev = NULL;
  ScsiBusDev = EfiLibAllocateZeroPool (sizeof (SCSI_BUS_DEVICE));
  if (ScsiBusDev == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  
  StartPun  = 0;
  StartLun  = 0;
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &(ScsiBusDev->DevicePath),
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    gBS->FreePool (ScsiBusDev);
    return Status;
  }

  //
  // First consume Extended SCSI Pass Thru protocol, if fail, then consume
  // SCSI Pass Thru protocol
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiExtScsiPassThruProtocolGuid,
                  (VOID **) &(ScsiBusDev->ExtScsiInterface),
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    Status = gBS->OpenProtocol (
                    Controller,
                    &gEfiScsiPassThruProtocolGuid,
                    (VOID **) &(ScsiBusDev->ScsiInterface),
                    This->DriverBindingHandle,
                    Controller,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );
    if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
      gBS->CloseProtocol (
             Controller,
             &gEfiDevicePathProtocolGuid,
             This->DriverBindingHandle,
             Controller
             );
      gBS->FreePool (ScsiBusDev);
      return Status;
    } 
    DEBUG ((EFI_D_INFO, "Open Scsi Pass Thrugh Protocol\n"));
    ScsiBusDev->ExtScsiSupport  = FALSE;
  } else {
    DEBUG ((EFI_D_INFO, "Open Extended Scsi Pass Thrugh Protocol\n"));
    ScsiBusDev->ExtScsiSupport  = TRUE;
  }

  ScsiBusDev->Signature = SCSI_BUS_DEVICE_SIGNATURE;
  //
  // Attach EFI_SCSI_BUS_PROTOCOL to controller handle
  //
  Status = gBS->InstallProtocolInterface (
                  &Controller,
                  &mScsiBusProtocolGuid,
                  EFI_NATIVE_INTERFACE,
                  &ScsiBusDev->BusIdentify
                  );

  if (EFI_ERROR (Status)) {
    gBS->CloseProtocol (
           Controller,
           &gEfiDevicePathProtocolGuid,
           This->DriverBindingHandle,
           Controller
           );
    if (ScsiBusDev->ExtScsiSupport) {
      gBS->CloseProtocol (
             Controller,
             &gEfiExtScsiPassThruProtocolGuid,
             This->DriverBindingHandle,
             Controller
             );
    } else {
      gBS->CloseProtocol (
             Controller,
             &gEfiScsiPassThruProtocolGuid,
             This->DriverBindingHandle,
             Controller
             );
    }
    gBS->FreePool (ScsiBusDev);
    return Status;
  }

  if (RemainingDevicePath == NULL) {
    StartPun  = 0xFFFFFFFF;
    StartLun  = 0;
  } else {
    if (ScsiBusDev->ExtScsiSupport) {
      *(UINT32*)Target = StartPun;
      *TargetId = Target;
      ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, TargetId, &StartLun);  
      StartPun = *(UINT32*)Target;
    } else {
      ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &StartPun, &StartLun);
    }
  }

  for (Pun = StartPun, ScanOtherPuns = TRUE; ScanOtherPuns;) {

    if (StartPun == 0xFFFFFFFF) {
      //
      // Remaining Device Path is NULL, scan all the possible Puns in the
      // SCSI Channel.
      //
      if (ScsiBusDev->ExtScsiSupport) {
        *(UINT32*)Target = Pun;
        *TargetId = Target;
        Status = ScsiBusDev->ExtScsiInterface->GetNextTargetLun (ScsiBusDev->ExtScsiInterface, TargetId, &Lun);
        Pun = *(UINT32*)Target;
      } else {
        Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &Pun, &Lun);
      }
      if (EFI_ERROR (Status)) {
        //
        // no legal Pun and Lun found any more
        //
        break;
      }
    } else {

⌨️ 快捷键说明

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