EFI_STATUS
EFIAPI
AtaAtapiPassThruSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_PCI_IO_PROTOCOL *PciIo;
PCI_TYPE00 PciData;
EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInit;
先看gEfiDevicePathProtocolGuid 有没有被open by driver .
open protocol by driver 有下面四个特点:
1 用来获得protocol interface .
2 如protocol 被reinstalled 或者uninstalled 的时候,需要调用driver 的stop 函数。
3 一旦某个protocol interface 被某个driver 以这种属性打开,其他的driver 就不允许再以
这种属于打开。
4, 调用者需要close 这个protocol interface.
//
// SATA Controller is a device driver, and should ignore the
// "RemainingDevicePath" according to UEFI spec
//
Status = gBS->OpenProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
(VOID *) &ParentDevicePath,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
如果faild 的话,代表这个controller 已经被别人occupied.
已经被别人open by driver了。 那我就不support 它了。
//
// EFI_ALREADY_STARTED is also an error
//
return Status;
}
open by driver, 我们就需要close 它,不然就会被一直占着。上面open 的目的只
是要测试,它有没有占住。
//
// Close the protocol because we don't use it here
//
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
Status = gBS->OpenProtocol (
Controller,
&gEfiIdeControllerInitProtocolGuid,
(VOID **) &IdeControllerInit,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
//
// EFI_ALREADY_STARTED is also an error
//
return Status;
}
//
// Close the I/O Abstraction(s) used to perform the supported test
//
gBS->CloseProtocol (
Controller,
&gEfiIdeControllerInitProtocolGuid,
This->DriverBindingHandle,
Controller
);
//
// Now test the EfiPciIoProtocol
//
Status = gBS->OpenProtocol (
Controller,
&gEfiPciIoProtocolGuid,
(VOID **) &PciIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL // 如果是get protocol ,是不用close 的。
);
if (EFI_ERROR (Status)) {
如果faild , 就直接返回,连pciio 都没有,也不可能是我们想要的。
return Status;
}
GET_PROTOCOLUsed by a driver to get a protocol interface from a handle.
Care must be taken when using this open mode because the driver that
opens a protocol interface in this manner will not be informed if
the protocol interface is uninstalled or reinstalled.
The caller is also not required to close the protocol interface with
//
// Now further check the PCI header: Base class (offset 0x0B) and
// Sub Class (offset 0x0A). This controller should be an ATA controller
//
通过上面拿到的PciIo 去read classcode
Status = PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint8,
PCI_CLASSCODE_OFFSET,
sizeof (PciData.Hdr.ClassCode),
PciData.Hdr.ClassCode
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
最后通过classcode , 来判断是不是sata ,
if (IS_PCI_IDE (&PciData) || IS_PCI_SATADPA (&PciData)) {
return EFI_SUCCESS;
}
return EFI_UNSUPPORTED;
}