driver model 代码解读

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;
}
 

猜你喜欢

转载自blog.csdn.net/robinsongsog/article/details/106774785