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 + -
显示快捷键?