idecontroller.c

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

C
628
字号
/*++

Copyright (c) 2006 Intel Corporation. All rights reserved
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:

  IdeController.c

Abstract:
    
  This driver module produces IDE_CONTROLLER_INIT protocol and will be used by 
  IDE Bus driver to support platform dependent timing information. This driver
  is responsible for early initialization of IDE controller.

Revision History
--*/

#include "IdeController.h"
#include "idedata.h"

//
// IDE Controller Init Guid
//
EFI_GUID
  gIdeControllerDriverGuid = { 0x91e365e9, 0xe0c0, 0x4647, 0xb0, 0xeb, 0xf6, 0x78, 0xf6, 0x21, 0xf8, 0x8d };

//
//  EFI_DRIVER_BINDING_PROTOCOL instance
//
EFI_DRIVER_BINDING_PROTOCOL gIdeControllerDriverBinding = {
  IdeControllerSupported,
  IdeControllerStart,
  IdeControllerStop,
  0x10,
  NULL,
  NULL
};

//
// Internal function definitions
//
EFI_STATUS
EnableNativeIdeDecode (
  IN  EFI_PCI_IO_PROTOCOL        *PciIo
  );

EFI_STATUS
EnableLegacyIdeDecode (
  EFI_EVENT  Event,
  VOID       *Context
  );

EFI_STATUS
IdeDetectCableType (
  IN  UINT8                      Channel,
  IN  UINT8                      Device,
  IN  EFI_PCI_IO_PROTOCOL        *PciIo,
  IN  EFI_IDENTIFY_DATA          *IdentifyData
  );

EFI_STATUS
AdjustUdmaModeByCableType (
  IN     UINT8                   Channel,
  IN     UINT8                   Device,
  IN     EFI_PCI_IO_PROTOCOL     *PciIo,
  IN OUT EFI_ATA_COLLECTIVE_MODE *Modes
  );

EFI_STATUS
CalculateBestPioMode (
  IN  EFI_IDENTIFY_DATA          * IdentifyData,
  IN  UINT16                     *DisPioMode OPTIONAL,
  OUT UINT16                     *SelectedMode
  );

EFI_STATUS
CalculateBestUdmaMode (
  IN  EFI_IDENTIFY_DATA          * IdentifyData,
  IN  UINT16                     *DisUDmaMode OPTIONAL,
  OUT UINT16                     *SelectedMode
  );

EFI_STATUS
IdeInitSetUdmaTiming (
  IN  UINT8                       Channel,
  IN  UINT8                       Device,
  IN  EFI_PCI_IO_PROTOCOL         *PciIo,
  IN  EFI_ATA_COLLECTIVE_MODE     *Modes
  );

EFI_STATUS
IdeInitSetPioTiming (
  IN  UINT8                       Channel,
  IN  UINT8                       Device,
  IN  EFI_PCI_IO_PROTOCOL         *PciIo,
  IN  EFI_IDENTIFY_DATA           *IdentifyData,
  IN  EFI_ATA_COLLECTIVE_MODE     *Modes
  );

EFI_DRIVER_ENTRY_POINT (InitializeIdeControllerDriver)
//
// *************************************
//  IdeController Driver Entry Point
// *************************************
//
EFI_STATUS
EFIAPI
InitializeIdeControllerDriver (
  IN EFI_HANDLE       ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
/*++
  Routine Description:
  
    Chipset Ide Driver EntryPoint function. It follows the standard EFI driver 
    model. It's called by StartImage() of DXE Core
    
  Argments:
  
    ImageHnadle  -- While the driver image loaded be the ImageLoader(), 
                    an image handle is assigned to this driver binary, 
                    all activities of the driver is tied to this ImageHandle
    *SystemTable -- A pointer to the system table, for all BS(Boo Services) and
                    RT(Runtime Services)

  Retruns:
  
    Always call EfiLibInstallDriverBindingProtocol( ) and retrun the result

--*/
{

  return INSTALL_ALL_DRIVER_PROTOCOLS (
          ImageHandle,
          SystemTable,
          &gIdeControllerDriverBinding,
          ImageHandle,
          &gIdeControllerName,
          NULL,
          NULL
          );
}

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

  Routine Description:
  
  Register Driver Binding protocol for this driver.
  
  Arguments:
  
    This                 -- a pointer points to the Binding Protocol instance
    Controller           -- The handle of controller to be tested. 
    *RemainingDevicePath -- A pointer to the device path. Ignored by device
                            driver but used by bus driver

  Returns:

    EFI_SUCCESS          -- Driver loaded.
    other                -- Driver not loaded.
--*/
{
  EFI_STATUS                Status;
  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
  EFI_PCI_IO_PROTOCOL       *PciIo;
  PCI_TYPE00                PciData;

  //
  // Ide Controller is a device driver, and should ingore the
  // "RemainingDevicePath" according to EFI spec
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID *) &ParentDevicePath,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    //
    // EFI_ALREADY_STARTED is also an error
    //
    return Status;
  }
  //
  // Close the protocol because we don't use it here
  //
  gBS->CloseProtocol (
        Controller,
        &gEfiDevicePathProtocolGuid,
        This->DriverBindingHandle,
        Controller
        );

  //
  // Now test the EfiPciIoProtocol
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiPciIoProtocolGuid,
                  (VOID **) &PciIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Now further check the PCI header: Base class (offset 0x0B) and
  // Sub Class (offset 0x0A). This controller should be an Ide controller
  //
  Status = PciIo->Pci.Read (
                        PciIo,
                        EfiPciIoWidthUint8,
                        0,
                        sizeof (PciData),
                        &PciData
                        );

  if (EFI_ERROR (Status)) {
    gBS->CloseProtocol (
          Controller,
          &gEfiPciIoProtocolGuid,
          This->DriverBindingHandle,
          Controller
          );
    return EFI_UNSUPPORTED;
  }
  //
  // Examine Ide PCI Configuration table fields
  //
  if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) ||
      (PciData.Hdr.ClassCode[1] != PCI_SUB_CLASS_IDE)
      ) {

    Status = EFI_UNSUPPORTED;
  }

  gBS->CloseProtocol (
        Controller,
        &gEfiPciIoProtocolGuid,
        This->DriverBindingHandle,
        Controller
        );

  return Status;
}

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

  Routine Description:
  
    This routine is called right after the .Supported() called and return 
    EFI_SUCCESS. Notes: The supported protocols are checked but the Protocols
    are closed.

  Arguments:
      
    This                 -- a pointer points to the Binding Protocol instance
    Controller           -- The handle of controller to be tested. Parameter
                            passed by the caller
    *RemainingDevicePath -- A pointer to the device path. Should be ignored by
                            device driver
--*/
{
  EFI_STATUS                      Status;
  EFI_PCI_IO_PROTOCOL             *PciIo;
  EFI_IDE_CONTROLLER_PRIVATE_DATA *IdePrivateData;

  //
  // Now test and open the EfiPciIoProtocol
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiPciIoProtocolGuid,
                  (VOID **) &PciIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );

  //
  // Status == 0 - A normal execution flow, SUCCESS and the program proceeds.
  // Status == ALREADY_STARTED - A non-zero Status code returned. It indicates
  //           that the protocol has been opened and should be treated as a
  //           normal condition and the program proceeds. The Protocol will not
  //           opened 'again' by this call.
  // Status != ALREADY_STARTED - Error status, terminate program execution
  //
  if (EFI_ERROR (Status)) {

⌨️ 快捷键说明

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