idebus.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,475 行 · 第 1/3 页
C
1,475 行
/*++
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:
idebus.c
Abstract:
Revision History
This module is modified from DXE\IDE module for Ide Contriller Init support
--*/
#include "idebus.h"
#define PCI_CLASS_MASS_STORAGE 0x01
#define PCI_SUB_CLASS_IDE 0x01
//
// IDE Bus Driver GUID
//
EFI_GUID gIDEBusDriverGuid = {
0xe778c047, 0x2121, 0x4ad1, 0x82, 0x36, 0x9, 0x7, 0x40, 0x61, 0x9f, 0x5
};
//
// IDE Bus Driver Binding Protocol Instance
//
EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = {
IDEBusDriverBindingSupported,
IDEBusDriverBindingStart,
IDEBusDriverBindingStop,
0x10,
NULL,
NULL
};
EFI_DRIVER_ENTRY_POINT (IDEBusControllerDriverEntryPoint)
//
// ***********************************************************************************
// IDEBusControllerDriverEntryPoint
// ***********************************************************************************
//
EFI_STATUS
EFIAPI
IDEBusControllerDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: ImageHandle - add argument and description to function comment
// TODO: SystemTable - add argument and description to function comment
{
return INSTALL_ALL_DRIVER_PROTOCOLS (
ImageHandle,
SystemTable,
&gIDEBusDriverBinding,
ImageHandle,
&gIDEBusComponentName,
NULL,
NULL
);
}
//
// ***********************************************************************************
// IDEBusDriverBindingSupported
// ***********************************************************************************
//
EFI_STATUS
EFIAPI
IDEBusDriverBindingSupported (
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 to the EFI_DRIVER_BINDING_PROTOCOL instance.
ControllerHandle -- The handle of the controller to test.
RemainingDevicePath -- A pointer to the remaining portion of a device path.
Returns:
EFI_SUCCESS - Driver loaded.
other - Driver not loaded.
--*/
// TODO: Controller - add argument and description to function comment
// TODO: EFI_UNSUPPORTED - add return value to function comment
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_DEV_PATH *Node;
EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
if (RemainingDevicePath != NULL) {
Node = (EFI_DEV_PATH *) RemainingDevicePath;
if (Node->DevPath.Type != MESSAGING_DEVICE_PATH ||
Node->DevPath.SubType != MSG_ATAPI_DP ||
DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) {
return EFI_UNSUPPORTED;
}
}
//
// Open the IO Abstraction(s) needed to perform the supported test
//
Status = gBS->OpenProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
(VOID **) &ParentDevicePath,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (Status == EFI_ALREADY_STARTED) {
return EFI_SUCCESS;
}
if (EFI_ERROR (Status)) {
return Status;
}
//
// Clsoe protocol, don't use device path protocol in the .Support() function
//
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
//
// Verify the Ide Controller Init Protocol, which installed by the
// IdeController module.
// Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't
// open BY_DRIVER here) That's why we don't check pciio protocol
// Note 2: ide_init driver check ide controller's pci config space, so we dont
// check here any more to save code size
//
Status = gBS->OpenProtocol (
Controller,
&gEfiIdeControllerInitProtocolGuid,
(VOID **) &IdeInit,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (Status == EFI_ALREADY_STARTED) {
return EFI_SUCCESS;
}
//
// If protocols were opened normally, closed it
//
gBS->CloseProtocol (
Controller,
&gEfiIdeControllerInitProtocolGuid,
This->DriverBindingHandle,
Controller
);
return Status;
}
//
// ***********************************************************************************
// IDEBusDriverBindingStart
// ***********************************************************************************
//
EFI_STATUS
EFIAPI
IDEBusDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Start this driver on Controller by detecting all disks and installing
BlockIo protocol on them.
Arguments:
This - Protocol instance pointer.
Controller - Handle of device to bind driver to.
RemainingDevicePath - Not used, always produce all possible children.
Returns:
EFI_SUCCESS - This driver is added to ControllerHandle.
EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
other - This driver does not support this device.
--*/
{
EFI_STATUS Status;
EFI_STATUS SavedStatus;
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_DEV_PATH *Node;
UINT8 IdeChannel;
UINT8 BeginningIdeChannel;
UINT8 EndIdeChannel;
UINT8 IdeDevice;
UINT8 BeginningIdeDevice;
UINT8 EndIdeDevice;
IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice];
IDE_BLK_IO_DEV *IdeBlkIoDevicePtr;
IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
ATA_TRANSFER_MODE TransferMode;
ATA_DRIVE_PARMS DriveParameters;
EFI_DEV_PATH NewNode;
UINT8 ConfigurationOptions;
UINT16 CommandBlockBaseAddr;
UINT16 ControlBlockBaseAddr;
UINTN DataSize;
UINT32 Attributes;
IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
//
// Local variables declaration for IdeControllerInit support
//
EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
BOOLEAN EnumAll;
BOOLEAN ChannelEnabled;
UINT8 ChannelCount;
UINT8 MaxDevices;
EFI_IDENTIFY_DATA IdentifyData;
EFI_ATA_COLLECTIVE_MODE *SupportedModes;
IdeBusDriverPrivateData = NULL;
SupportedModes = NULL;
//
// Perform IdeBus initialization
//
Status = gBS->OpenProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
(VOID **) &ParentDevicePath,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
return Status;
}
//
// Now open the IDE_CONTROLLER_INIT protocol. Step7.1
//
Status = gBS->OpenProtocol (
Controller,
&gEfiIdeControllerInitProtocolGuid,
(VOID **) &IdeInit,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
//
// The following OpenProtocol function with _GET_PROTOCOL attribute and
// will not return EFI_ALREADY_STARTED, so save it for now
//
SavedStatus = Status;
if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status));
//
// open protocol is not SUCCESS or not ALREADY_STARTED, error exit
//
goto ErrorExit;
}
//
// Save Enumall and ChannelCount. Step7.2
//
EnumAll = IdeInit->EnumAll;
ChannelCount = IdeInit->ChannelCount;
//
// Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
// attribute will not return EFI_ALREADY_STARTED
//
Status = gBS->OpenProtocol (
Controller,
&gEfiPciIoProtocolGuid,
(VOID **) &PciIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status));
goto ErrorExit;
}
//
// We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
//
if (SavedStatus != EFI_ALREADY_STARTED) {
IdeBusDriverPrivateData = EfiLibAllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
if (IdeBusDriverPrivateData == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ErrorExit;
}
EfiZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
Status = gBS->InstallMultipleProtocolInterfaces (
&Controller,
&gIDEBusDriverGuid,
IdeBusDriverPrivateData,
NULL
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
} else {
Status = gBS->OpenProtocol (
Controller,
&gIDEBusDriverGuid,
(VOID **) &IdeBusDriverPrivateData,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
IdeBusDriverPrivateData = NULL;
goto ErrorExit;
}
}
Status = PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationEnable,
EFI_PCI_DEVICE_ENABLE,
NULL
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Read the environment variable that contains the IDEBus Driver's
// Config options that were set by the Driver Configuration Protocol
//
DataSize = sizeof (ConfigurationOptions);
Status = gRT->GetVariable (
L"Configuration",
&gIDEBusDriverGuid,
&Attributes,
&DataSize,
&ConfigurationOptions
);
if (EFI_ERROR (Status)) {
ConfigurationOptions = 0x0f;
}
if (EnumAll) {
//
// If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway
//
BeginningIdeChannel = IdePrimary;
EndIdeChannel = IdeSecondary;
BeginningIdeDevice = IdeMaster;
EndIdeDevice = IdeSlave;
} else if (RemainingDevicePath == NULL) {
//
// RemainingDevicePath is NULL, scan IDE bus for each device;
//
BeginningIdeChannel = IdePrimary;
EndIdeChannel = IdeSecondary;
BeginningIdeDevice = IdeMaster;
//
// default, may be redefined by IdeInit
//
EndIdeDevice = IdeSlave;
} else {
//
// RemainingDevicePath is not NULL, only scan the specified device.
//
Node = (EFI_DEV_PATH *) RemainingDevicePath;
BeginningIdeChannel = Node->Atapi.PrimarySecondary;
EndIdeChannel = BeginningIdeChannel;
BeginningIdeDevice = Node->Atapi.SlaveMaster;
EndIdeDevice = BeginningIdeDevice;
}
//
// Obtain IDE IO port registers' base addresses
//
Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Report status code: begin IdeBus initialization
//
ReportStatusCodeWithDevicePath (
EFI_PROGRESS_CODE,
(EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
0,
&gIDEBusDriverGuid,
ParentDevicePath
);
//
// Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
//
for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);
//
// now obtain channel information fron IdeControllerInit protocol. Step9
//
Status = IdeInit->GetChannelInfo (
IdeInit,
IdeChannel,
&ChannelEnabled,
&MaxDevices
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));
continue;
}
if (!ChannelEnabled) {
continue;
}
EndIdeDevice = (UINT8) EFI_MIN ((MaxDevices - 1), EndIdeDevice);
//
// Now inform the IDE Controller Init Module. Sept10
//
IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);
//
// No reset channel function implemented. Sept11
//
IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);
//
// Step13
//
IdeInit->NotifyPhase (
IdeInit,
EfiIdeBusBeforeDevicePresenceDetection,
IdeChannel
);
//
// Prepare to detect IDE device of this channel
//
InitializeIDEChannelData ();
//
// -- 1st inner loop --- Master/Slave ------------ Step14
//
for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
//
// Check whether the configuration options allow this device
//
if (!(ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice)))) {
continue;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?