CorebootModulePkg: Remove DuetPkg references

Remove the references to DuetPkg.  Copy the files from revision
ffea0a2ce21e8e9878587de2419959a7bfea4021 of DuetPkg into
CorebootModulePkg.  The components include:
* PciBusNoEnumerationDxe
* PciRootBridgeNoEnumerationDxe
* SataControllerDxe

TEST=Build and run on Galileo Gen2

Change-Id: Id07185f7e226749e5f7c6b6cb427bcef7eac8496
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Reviewed-by: Maurice Ma <maurice.ma@intel.com>
Reviewed-by: Prince Agyeman <prince.agyeman@intel.com>
This commit is contained in:
Leahy, Leroy P 2016-05-02 12:59:17 -07:00 committed by Prince Agyeman
parent 13986b690c
commit 81a23a0fee
39 changed files with 15258 additions and 9 deletions

View File

@ -0,0 +1,161 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation. All rights reserved.<BR>
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:
ComponentName.c
Abstract:
--*/
#include "PciBus.h"
//
// EFI Component Name Functions
//
EFI_STATUS
EFIAPI
PciBusComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
PciBusComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName = {
PciBusComponentNameGetDriverName,
PciBusComponentNameGetControllerName,
"eng"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciBusComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciBusComponentNameGetControllerName,
"en"
};
EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = {
{ "eng;en", L"PCI Bus Driver" },
{ NULL, NULL }
};
EFI_STATUS
EFIAPI
PciBusComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that that the caller
is requesting, and it must match one of the languages specified
in SupportedLanguages. The number of languages supported by a
driver is up to the driver writer.
DriverName - A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
Returns:
EFI_SUCCESS - The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mPciBusDriverNameTable,
DriverName,
(BOOLEAN)(This == &gPciBusComponentName)
);
}
EFI_STATUS
EFIAPI
PciBusComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that that the caller is requesting, and it must match one
of the languages specified in SupportedLanguages. The
number of languages supported by a driver is up to the
driver writer.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language specified
by Language from the point of view of the driver specified
by This.
Returns:
EFI_SUCCESS - The Unicode string for the user readable name in the
language specified by Language for the driver
specified by This was returned in DriverName.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently managing
the controller specified by ControllerHandle and
ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}

View File

@ -0,0 +1,346 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciBus.c
Abstract:
PCI Bus Driver
Revision History
--*/
#include "PciBus.h"
//
// PCI Bus Support Function Prototypes
//
EFI_STATUS
EFIAPI
PciBusEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
EFI_STATUS
EFIAPI
PciBusDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
PciBusDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
PciBusDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
//
// PCI Bus Driver Global Variables
//
EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding = {
PciBusDriverBindingSupported,
PciBusDriverBindingStart,
PciBusDriverBindingStop,
0xa,
NULL,
NULL
};
BOOLEAN gFullEnumeration;
UINT64 gAllOne = 0xFFFFFFFFFFFFFFFFULL;
UINT64 gAllZero = 0;
//
// PCI Bus Driver Support Functions
//
EFI_STATUS
EFIAPI
PciBusEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Initialize the global variables
publish the driver binding protocol
Arguments:
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
Returns:
EFI_SUCCESS
EFI_DEVICE_ERROR
--*/
{
EFI_STATUS Status;
//
// Initialize the EFI Driver Library
//
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gPciBusDriverBinding,
ImageHandle,
&gPciBusComponentName,
&gPciBusComponentName2
);
ASSERT_EFI_ERROR (Status);
InitializePciDevicePool ();
gFullEnumeration = TRUE;
return Status;
}
EFI_STATUS
EFIAPI
PciBusDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Check to see if pci bus driver supports the given controller
Arguments:
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
Returns:
EFI_SUCCESS
--*/
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
EFI_DEV_PATH_PTR Node;
if (RemainingDevicePath != NULL) {
Node.DevPath = RemainingDevicePath;
if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
Node.DevPath->SubType != HW_PCI_DP ||
DevicePathNodeLength(Node.DevPath) != sizeof(PCI_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;
}
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
Status = gBS->OpenProtocol (
Controller,
&gEfiPciRootBridgeIoProtocolGuid,
(VOID **) &PciRootBridgeIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (Status == EFI_ALREADY_STARTED) {
return EFI_SUCCESS;
}
if (EFI_ERROR (Status)) {
return Status;
}
gBS->CloseProtocol (
Controller,
&gEfiPciRootBridgeIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
PciBusDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Start to management the controller passed in
Arguments:
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
Returns:
--*/
{
EFI_STATUS Status;
//
// Enumerate the entire host bridge
// After enumeration, a database that records all the device information will be created
//
//
Status = PciEnumerator (Controller);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Enable PCI device specified by remaining device path. BDS or other driver can call the
// start more than once.
//
StartPciDevices (Controller, RemainingDevicePath);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
PciBusDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
/*++
Routine Description:
Stop one or more children created at start of pci bus driver
if all the the children get closed, close the protocol
Arguments:
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
Returns:
--*/
{
EFI_STATUS Status;
UINTN Index;
BOOLEAN AllChildrenStopped;
if (NumberOfChildren == 0) {
//
// Close the bus driver
//
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
gBS->CloseProtocol (
Controller,
&gEfiPciRootBridgeIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
DestroyRootBridgeByHandle (
Controller
);
return EFI_SUCCESS;
}
//
// Stop all the children
//
AllChildrenStopped = TRUE;
for (Index = 0; Index < NumberOfChildren; Index++) {
//
// De register all the pci device
//
Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);
if (EFI_ERROR (Status)) {
AllChildrenStopped = FALSE;
}
}
if (!AllChildrenStopped) {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,225 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation. All rights reserved.<BR>
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:
PciBus.h
Abstract:
PCI Bus Driver
Revision History
--*/
#ifndef _EFI_PCI_BUS_H
#define _EFI_PCI_BUS_H
#include <PiDxe.h>
#include <Protocol/PciIo.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Protocol/DevicePath.h>
#include <Protocol/Decompress.h>
#include <Protocol/UgaIo.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/BusSpecificDriverOverride.h>
#include <Guid/PciOptionRomTable.h>
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/Acpi.h>
#include <IndustryStandard/PeImage.h>
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/ReportStatusCodeLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DevicePathLib.h>
#include <Library/PcdLib.h>
#include <Library/PeCoffLib.h>
//
// Driver Produced Protocol Prototypes
//
#define VGABASE1 0x3B0
#define VGALIMIT1 0x3BB
#define VGABASE2 0x3C0
#define VGALIMIT2 0x3DF
#define ISABASE 0x100
#define ISALIMIT 0x3FF
typedef enum {
PciBarTypeUnknown = 0,
PciBarTypeIo16,
PciBarTypeIo32,
PciBarTypeMem32,
PciBarTypePMem32,
PciBarTypeMem64,
PciBarTypePMem64,
PciBarTypeIo,
PciBarTypeMem,
PciBarTypeMaxType
} PCI_BAR_TYPE;
typedef struct {
UINT64 BaseAddress;
UINT64 Length;
UINT64 Alignment;
PCI_BAR_TYPE BarType;
BOOLEAN Prefetchable;
UINT8 MemType;
UINT8 Offset;
} PCI_BAR;
#define PCI_IO_DEVICE_SIGNATURE SIGNATURE_32 ('p','c','i','o')
#define EFI_BRIDGE_IO32_DECODE_SUPPORTED 0x0001
#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED 0x0002
#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED 0x0004
#define EFI_BRIDGE_IO16_DECODE_SUPPORTED 0x0008
#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED 0x0010
#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED 0x0020
#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED 0x0040
typedef struct _PCI_IO_DEVICE {
UINT32 Signature;
EFI_HANDLE Handle;
EFI_PCI_IO_PROTOCOL PciIo;
LIST_ENTRY Link;
EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
//
// PCI configuration space header type
//
PCI_TYPE00 Pci;
//
// Bus number, Device number, Function number
//
UINT8 BusNumber;
UINT8 DeviceNumber;
UINT8 FunctionNumber;
//
// BAR for this PCI Device
//
PCI_BAR PciBar[PCI_MAX_BAR];
//
// The bridge device this pci device is subject to
//
struct _PCI_IO_DEVICE *Parent;
//
// A linked list for children Pci Device if it is bridge device
//
LIST_ENTRY ChildList;
//
// TURE if the PCI bus driver creates the handle for this PCI device
//
BOOLEAN Registered;
//
// TRUE if the PCI bus driver successfully allocates the resource required by
// this PCI device
//
BOOLEAN Allocated;
//
// The attribute this PCI device currently set
//
UINT64 Attributes;
//
// The attributes this PCI device actually supports
//
UINT64 Supports;
//
// The resource decode the bridge supports
//
UINT32 Decodes;
//
// The OptionRom Size
//
UINT64 RomSize;
//
// TRUE if there is any EFI driver in the OptionRom
//
BOOLEAN BusOverride;
//
// A list tracking reserved resource on a bridge device
//
LIST_ENTRY ReservedResourceList;
//
// A list tracking image handle of platform specific overriding driver
//
LIST_ENTRY OptionRomDriverList;
BOOLEAN IsPciExp;
} PCI_IO_DEVICE;
#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE)
#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \
CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE)
#define PCI_IO_DEVICE_FROM_LINK(a) \
CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE)
//
// Global Variables
//
extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2;
extern EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding;
extern BOOLEAN gFullEnumeration;
extern UINT64 gAllOne;
extern UINT64 gAllZero;
#include "PciIo.h"
#include "PciCommand.h"
#include "PciDeviceSupport.h"
#include "PciEnumerator.h"
#include "PciEnumeratorSupport.h"
#include "PciDriverOverride.h"
#include "PciRomTable.h"
#include "PciOptionRomSupport.h"
#include "PciPowerManagement.h"
#define IS_ISA_BRIDGE(_p) IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA)
#define IS_INTEL_ISA_BRIDGE(_p) (IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE) && ((_p)->Hdr.VendorId == 0x8086) && ((_p)->Hdr.DeviceId == 0x7110))
#define IS_PCI_GFX(_p) IS_CLASS2 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_OTHER)
#endif

View File

@ -0,0 +1,72 @@
## @file
#
# Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
# 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:
#
# Abstract:
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PciBusNoEnumerationDxe
FILE_GUID = 35C0C168-2607-4e51-BB53-448E3ED1A87F
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = PciBusEntryPoint
[Packages]
MdePkg/MdePkg.dec
DuetPkg/DuetPkg.dec
[LibraryClasses]
DebugLib
BaseLib
UefiLib
UefiBootServicesTableLib
UefiDriverEntryPoint
BaseMemoryLib
ReportStatusCodeLib
DevicePathLib
PeCoffLib
[Sources]
PciBus.h
PciIo.h
PciCommand.h
PciDeviceSupport.h
PciEnumerator.h
PciEnumeratorSupport.h
PciOptionRomSupport.h
PciRomTable.h
PciPowerManagement.h
PciPowerManagement.c
PciRomTable.c
PciDriverOverride.h
PciDriverOverride.c
PciOptionRomSupport.c
PciEnumerator.c
PciEnumeratorSupport.c
PciCommand.c
ComponentName.c
PciDeviceSupport.c
PciBus.c
PciIo.c
[Protocols]
gEfiPciRootBridgeIoProtocolGuid
gEfiPciIoProtocolGuid
gEfiDevicePathProtocolGuid
gEfiBusSpecificDriverOverrideProtocolGuid
gEfiDecompressProtocolGuid
[Guids]
gEfiPciOptionRomTableGuid

View File

@ -0,0 +1,453 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciCommand.c
Abstract:
PCI Bus Driver
Revision History
--*/
#include "PciBus.h"
EFI_STATUS
PciReadCommandRegister (
IN PCI_IO_DEVICE *PciIoDevice,
OUT UINT16 *Command
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
EFI_PCI_IO_PROTOCOL *PciIo;
*Command = 0;
PciIo = &PciIoDevice->PciIo;
return PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint16,
PCI_COMMAND_OFFSET,
1,
Command
);
}
EFI_STATUS
PciSetCommandRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
UINT16 Temp;
EFI_PCI_IO_PROTOCOL *PciIo;
Temp = Command;
PciIo = &PciIoDevice->PciIo;
return PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint16,
PCI_COMMAND_OFFSET,
1,
&Temp
);
}
EFI_STATUS
PciEnableCommandRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
UINT16 OldCommand;
EFI_PCI_IO_PROTOCOL *PciIo;
OldCommand = 0;
PciIo = &PciIoDevice->PciIo;
PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint16,
PCI_COMMAND_OFFSET,
1,
&OldCommand
);
OldCommand = (UINT16) (OldCommand | Command);
return PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint16,
PCI_COMMAND_OFFSET,
1,
&OldCommand
);
}
EFI_STATUS
PciDisableCommandRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
UINT16 OldCommand;
EFI_PCI_IO_PROTOCOL *PciIo;
OldCommand = 0;
PciIo = &PciIoDevice->PciIo;
PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint16,
PCI_COMMAND_OFFSET,
1,
&OldCommand
);
OldCommand = (UINT16) (OldCommand & ~(Command));
return PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint16,
PCI_COMMAND_OFFSET,
1,
&OldCommand
);
}
EFI_STATUS
PciSetBridgeControlRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
UINT16 Temp;
EFI_PCI_IO_PROTOCOL *PciIo;
Temp = Command;
PciIo = &PciIoDevice->PciIo;
return PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint16,
PCI_BRIDGE_CONTROL_REGISTER_OFFSET,
1,
&Temp
);
}
EFI_STATUS
PciEnableBridgeControlRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
UINT16 OldCommand;
EFI_PCI_IO_PROTOCOL *PciIo;
OldCommand = 0;
PciIo = &PciIoDevice->PciIo;
PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint16,
PCI_BRIDGE_CONTROL_REGISTER_OFFSET,
1,
&OldCommand
);
OldCommand = (UINT16) (OldCommand | Command);
return PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint16,
PCI_BRIDGE_CONTROL_REGISTER_OFFSET,
1,
&OldCommand
);
}
EFI_STATUS
PciDisableBridgeControlRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
UINT16 OldCommand;
EFI_PCI_IO_PROTOCOL *PciIo;
OldCommand = 0;
PciIo = &PciIoDevice->PciIo;
PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint16,
PCI_BRIDGE_CONTROL_REGISTER_OFFSET,
1,
&OldCommand
);
OldCommand = (UINT16) (OldCommand & ~(Command));
return PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint16,
PCI_BRIDGE_CONTROL_REGISTER_OFFSET,
1,
&OldCommand
);
}
EFI_STATUS
PciReadBridgeControlRegister (
IN PCI_IO_DEVICE *PciIoDevice,
OUT UINT16 *Command
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
EFI_PCI_IO_PROTOCOL *PciIo;
*Command = 0;
PciIo = &PciIoDevice->PciIo;
return PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint16,
PCI_BRIDGE_CONTROL_REGISTER_OFFSET,
1,
Command
);
}
BOOLEAN
PciCapabilitySupport (
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
// TODO: PciIoDevice - add argument and description to function comment
{
if (PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) {
return TRUE;
}
return FALSE;
}
EFI_STATUS
LocateCapabilityRegBlock (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT8 CapId,
IN OUT UINT8 *Offset,
OUT UINT8 *NextRegBlock OPTIONAL
)
/*++
Routine Description:
Locate Capability register.
Arguments:
PciIoDevice - A pointer to the PCI_IO_DEVICE.
CapId - The capability ID.
Offset - A pointer to the offset.
As input: the default offset;
As output: the offset of the found block.
NextRegBlock - An optional pointer to return the value of next block.
Returns:
EFI_UNSUPPORTED - The Pci Io device is not supported.
EFI_NOT_FOUND - The Pci Io device cannot be found.
EFI_SUCCESS - The Pci Io device is successfully located.
--*/
{
UINT8 CapabilityPtr;
UINT16 CapabilityEntry;
UINT8 CapabilityID;
//
// To check the capability of this device supports
//
if (!PciCapabilitySupport (PciIoDevice)) {
return EFI_UNSUPPORTED;
}
if (*Offset != 0) {
CapabilityPtr = *Offset;
} else {
CapabilityPtr = 0;
if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
PciIoDevice->PciIo.Pci.Read (
&PciIoDevice->PciIo,
EfiPciIoWidthUint8,
EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,
1,
&CapabilityPtr
);
} else {
PciIoDevice->PciIo.Pci.Read (
&PciIoDevice->PciIo,
EfiPciIoWidthUint8,
PCI_CAPBILITY_POINTER_OFFSET,
1,
&CapabilityPtr
);
}
}
while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {
PciIoDevice->PciIo.Pci.Read (
&PciIoDevice->PciIo,
EfiPciIoWidthUint16,
CapabilityPtr,
1,
&CapabilityEntry
);
CapabilityID = (UINT8) CapabilityEntry;
if (CapabilityID == CapId) {
*Offset = CapabilityPtr;
if (NextRegBlock != NULL) {
*NextRegBlock = (UINT8) (CapabilityEntry >> 8);
}
return EFI_SUCCESS;
}
CapabilityPtr = (UINT8) (CapabilityEntry >> 8);
}
return EFI_NOT_FOUND;
}

View File

@ -0,0 +1,167 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciCommand.h
Abstract:
PCI Bus Driver
Revision History
--*/
#ifndef _EFI_PCI_COMMAND_H
#define _EFI_PCI_COMMAND_H
#include "PciBus.h"
//
// The PCI Command register bits owned by PCI Bus driver.
//
// They should be cleared at the beginning. The other registers
// are owned by chipset, we should not touch them.
//
#define EFI_PCI_COMMAND_BITS_OWNED ( \
EFI_PCI_COMMAND_IO_SPACE | \
EFI_PCI_COMMAND_MEMORY_SPACE | \
EFI_PCI_COMMAND_BUS_MASTER | \
EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE | \
EFI_PCI_COMMAND_VGA_PALETTE_SNOOP | \
EFI_PCI_COMMAND_FAST_BACK_TO_BACK \
)
//
// The PCI Bridge Control register bits owned by PCI Bus driver.
//
// They should be cleared at the beginning. The other registers
// are owned by chipset, we should not touch them.
//
#define EFI_PCI_BRIDGE_CONTROL_BITS_OWNED ( \
EFI_PCI_BRIDGE_CONTROL_ISA | \
EFI_PCI_BRIDGE_CONTROL_VGA | \
EFI_PCI_BRIDGE_CONTROL_VGA_16 | \
EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK \
)
//
// The PCCard Bridge Control register bits owned by PCI Bus driver.
//
// They should be cleared at the beginning. The other registers
// are owned by chipset, we should not touch them.
//
#define EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED ( \
EFI_PCI_BRIDGE_CONTROL_ISA | \
EFI_PCI_BRIDGE_CONTROL_VGA | \
EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK \
)
EFI_STATUS
PciReadCommandRegister (
IN PCI_IO_DEVICE *PciIoDevice,
OUT UINT16 *Command
);
EFI_STATUS
PciSetCommandRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
);
EFI_STATUS
PciEnableCommandRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
);
EFI_STATUS
PciDisableCommandRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
);
EFI_STATUS
PciDisableBridgeControlRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
);
EFI_STATUS
PciEnableBridgeControlRegister (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT16 Command
);
EFI_STATUS
PciReadBridgeControlRegister (
IN PCI_IO_DEVICE *PciIoDevice,
OUT UINT16 *Command
);
BOOLEAN
PciCapabilitySupport (
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
TODO: Add function description
Arguments:
PciIoDevice - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
LocateCapabilityRegBlock (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINT8 CapId,
IN OUT UINT8 *Offset,
OUT UINT8 *NextRegBlock OPTIONAL
)
/*++
Routine Description:
Locate Capability register.
Arguments:
PciIoDevice - A pointer to the PCI_IO_DEVICE.
CapId - The capability ID.
Offset - A pointer to the offset.
As input: the default offset;
As output: the offset of the found block.
NextRegBlock - An optional pointer to return the value of next block.
Returns:
EFI_UNSUPPORTED - The Pci Io device is not supported.
EFI_NOT_FOUND - The Pci Io device cannot be found.
EFI_SUCCESS - The Pci Io device is successfully located.
--*/
;
#endif

View File

@ -0,0 +1,973 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciDeviceSupport.c
Abstract:
This file provides routine to support Pci device node manipulation
Revision History
--*/
#include "PciBus.h"
//
// This device structure is serviced as a header.
// Its Next field points to the first root bridge device node
//
LIST_ENTRY gPciDevicePool;
EFI_STATUS
InitializePciDevicePool (
VOID
)
/*++
Routine Description:
Initialize the gPciDevicePool
Arguments:
Returns:
None
--*/
{
InitializeListHead (&gPciDevicePool);
return EFI_SUCCESS;
}
EFI_STATUS
InsertRootBridge (
IN PCI_IO_DEVICE *RootBridge
)
/*++
Routine Description:
Insert a root bridge into PCI device pool
Arguments:
RootBridge - A pointer to the PCI_IO_DEVICE.
Returns:
None
--*/
{
InsertTailList (&gPciDevicePool, &(RootBridge->Link));
return EFI_SUCCESS;
}
EFI_STATUS
InsertPciDevice (
PCI_IO_DEVICE *Bridge,
PCI_IO_DEVICE *PciDeviceNode
)
/*++
Routine Description:
This function is used to insert a PCI device node under
a bridge
Arguments:
Bridge - A pointer to the PCI_IO_DEVICE.
PciDeviceNode - A pointer to the PCI_IO_DEVICE.
Returns:
None
--*/
{
InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link));
PciDeviceNode->Parent = Bridge;
return EFI_SUCCESS;
}
EFI_STATUS
DestroyRootBridge (
IN PCI_IO_DEVICE *RootBridge
)
/*++
Routine Description:
Arguments:
RootBridge - A pointer to the PCI_IO_DEVICE.
Returns:
None
--*/
{
DestroyPciDeviceTree (RootBridge);
gBS->FreePool (RootBridge);
return EFI_SUCCESS;
}
EFI_STATUS
DestroyPciDeviceTree (
IN PCI_IO_DEVICE *Bridge
)
/*++
Routine Description:
Destroy all the pci device node under the bridge.
Bridge itself is not included.
Arguments:
Bridge - A pointer to the PCI_IO_DEVICE.
Returns:
None
--*/
{
LIST_ENTRY *CurrentLink;
PCI_IO_DEVICE *Temp;
while (!IsListEmpty (&Bridge->ChildList)) {
CurrentLink = Bridge->ChildList.ForwardLink;
//
// Remove this node from the linked list
//
RemoveEntryList (CurrentLink);
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (IS_PCI_BRIDGE (&(Temp->Pci))) {
DestroyPciDeviceTree (Temp);
}
gBS->FreePool (Temp);
}
return EFI_SUCCESS;
}
EFI_STATUS
DestroyRootBridgeByHandle (
EFI_HANDLE Controller
)
/*++
Routine Description:
Destroy all device nodes under the root bridge
specified by Controller.
The root bridge itself is also included.
Arguments:
Controller - An efi handle.
Returns:
None
--*/
{
LIST_ENTRY *CurrentLink;
PCI_IO_DEVICE *Temp;
CurrentLink = gPciDevicePool.ForwardLink;
while (CurrentLink && CurrentLink != &gPciDevicePool) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (Temp->Handle == Controller) {
RemoveEntryList (CurrentLink);
DestroyPciDeviceTree (Temp);
gBS->FreePool(Temp);
return EFI_SUCCESS;
}
CurrentLink = CurrentLink->ForwardLink;
}
return EFI_NOT_FOUND;
}
EFI_STATUS
RegisterPciDevice (
IN EFI_HANDLE Controller,
IN PCI_IO_DEVICE *PciIoDevice,
OUT EFI_HANDLE *Handle OPTIONAL
)
/*++
Routine Description:
This function registers the PCI IO device. It creates a handle for this PCI IO device
(if the handle does not exist), attaches appropriate protocols onto the handle, does
necessary initialization, and sets up parent/child relationship with its bus controller.
Arguments:
Controller - An EFI handle for the PCI bus controller.
PciIoDevice - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
Handle - A pointer to hold the EFI handle for the PCI IO device.
Returns:
EFI_SUCCESS - The PCI device is successfully registered.
Others - An error occurred when registering the PCI device.
--*/
{
EFI_STATUS Status;
UINT8 PciExpressCapRegOffset;
//
// Install the pciio protocol, device path protocol and
// Bus Specific Driver Override Protocol
//
if (PciIoDevice->BusOverride) {
Status = gBS->InstallMultipleProtocolInterfaces (
&PciIoDevice->Handle,
&gEfiDevicePathProtocolGuid,
PciIoDevice->DevicePath,
&gEfiPciIoProtocolGuid,
&PciIoDevice->PciIo,
&gEfiBusSpecificDriverOverrideProtocolGuid,
&PciIoDevice->PciDriverOverride,
NULL
);
} else {
Status = gBS->InstallMultipleProtocolInterfaces (
&PciIoDevice->Handle,
&gEfiDevicePathProtocolGuid,
PciIoDevice->DevicePath,
&gEfiPciIoProtocolGuid,
&PciIoDevice->PciIo,
NULL
);
}
if (EFI_ERROR (Status)) {
return Status;
} else {
Status = gBS->OpenProtocol (
Controller,
&gEfiPciRootBridgeIoProtocolGuid,
(VOID **)&(PciIoDevice->PciRootBridgeIo),
gPciBusDriverBinding.DriverBindingHandle,
PciIoDevice->Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
return Status;
}
}
if (Handle != NULL) {
*Handle = PciIoDevice->Handle;
}
//
// Detect if PCI Express Device
//
PciExpressCapRegOffset = 0;
Status = LocateCapabilityRegBlock (
PciIoDevice,
EFI_PCI_CAPABILITY_ID_PCIEXP,
&PciExpressCapRegOffset,
NULL
);
if (!EFI_ERROR (Status)) {
PciIoDevice->IsPciExp = TRUE;
DEBUG ((EFI_D_ERROR, "PciExp - %x (B-%x, D-%x, F-%x)\n", PciIoDevice->IsPciExp, PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber));
}
//
// Indicate the pci device is registered
//
PciIoDevice->Registered = TRUE;
return EFI_SUCCESS;
}
EFI_STATUS
DeRegisterPciDevice (
IN EFI_HANDLE Controller,
IN EFI_HANDLE Handle
)
/*++
Routine Description:
This function is used to de-register the PCI device from the EFI,
That includes un-installing PciIo protocol from the specified PCI
device handle.
Arguments:
Controller - An efi handle.
Handle - An efi handle.
Returns:
None
--*/
{
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status;
PCI_IO_DEVICE *PciIoDevice;
PCI_IO_DEVICE *Node;
LIST_ENTRY *CurrentLink;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
Status = gBS->OpenProtocol (
Handle,
&gEfiPciIoProtocolGuid,
(VOID **) &PciIo,
gPciBusDriverBinding.DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (!EFI_ERROR (Status)) {
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
//
// If it is already de-registered
//
if (!PciIoDevice->Registered) {
return EFI_SUCCESS;
}
//
// If it is PPB, first de-register its children
//
if (IS_PCI_BRIDGE (&(PciIoDevice->Pci))) {
CurrentLink = PciIoDevice->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
Node = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
Status = DeRegisterPciDevice (Controller, Node->Handle);
if (EFI_ERROR (Status)) {
return Status;
}
CurrentLink = CurrentLink->ForwardLink;
}
}
//
// First disconnect this device
//
// PciIoDevice->PciIo.Attributes(&(PciIoDevice->PciIo),
// EfiPciIoAttributeOperationDisable,
// EFI_PCI_DEVICE_ENABLE,
// NULL
// );
//
// Close the child handle
//
Status = gBS->CloseProtocol (
Controller,
&gEfiPciRootBridgeIoProtocolGuid,
gPciBusDriverBinding.DriverBindingHandle,
Handle
);
//
// Un-install the device path protocol and pci io protocol
//
if (PciIoDevice->BusOverride) {
Status = gBS->UninstallMultipleProtocolInterfaces (
Handle,
&gEfiDevicePathProtocolGuid,
PciIoDevice->DevicePath,
&gEfiPciIoProtocolGuid,
&PciIoDevice->PciIo,
&gEfiBusSpecificDriverOverrideProtocolGuid,
&PciIoDevice->PciDriverOverride,
NULL
);
} else {
Status = gBS->UninstallMultipleProtocolInterfaces (
Handle,
&gEfiDevicePathProtocolGuid,
PciIoDevice->DevicePath,
&gEfiPciIoProtocolGuid,
&PciIoDevice->PciIo,
NULL
);
}
if (EFI_ERROR (Status)) {
gBS->OpenProtocol (
Controller,
&gEfiPciRootBridgeIoProtocolGuid,
(VOID **) &PciRootBridgeIo,
gPciBusDriverBinding.DriverBindingHandle,
Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
return Status;
}
//
// The Device Driver should disable this device after disconnect
// so the Pci Bus driver will not touch this device any more.
// Restore the register field to the original value
//
PciIoDevice->Registered = FALSE;
PciIoDevice->Handle = NULL;
} else {
//
// Handle may be closed before
//
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}
EFI_STATUS
EnableBridgeAttributes (
IN PCI_IO_DEVICE *PciIoDevice
)
{
PCI_TYPE01 PciData;
//
// NOTE: We should not set EFI_PCI_DEVICE_ENABLE for a bridge
// directly, because some legacy BIOS will NOT assign
// IO or Memory resource for a bridge who has no child
// device. So we add check IO or Memory here.
//
PciIoDevice->PciIo.Pci.Read (
&PciIoDevice->PciIo,
EfiPciIoWidthUint8,
0,
sizeof (PciData),
&PciData
);
if ((((PciData.Bridge.IoBase & 0xF) == 0) &&
(PciData.Bridge.IoBase != 0 || PciData.Bridge.IoLimit != 0)) ||
(((PciData.Bridge.IoBase & 0xF) == 1) &&
((PciData.Bridge.IoBase & 0xF0) != 0 || (PciData.Bridge.IoLimit & 0xF0) != 0 || PciData.Bridge.IoBaseUpper16 != 0 || PciData.Bridge.IoLimitUpper16 != 0))) {
PciIoDevice->PciIo.Attributes(
&(PciIoDevice->PciIo),
EfiPciIoAttributeOperationEnable,
(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
NULL
);
}
if ((PciData.Bridge.MemoryBase & 0xFFF0) != 0 || (PciData.Bridge.MemoryLimit & 0xFFF0) != 0) {
PciIoDevice->PciIo.Attributes(
&(PciIoDevice->PciIo),
EfiPciIoAttributeOperationEnable,
(EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
NULL
);
}
if ((((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 0) &&
(PciData.Bridge.PrefetchableMemoryBase != 0 || PciData.Bridge.PrefetchableMemoryLimit != 0)) ||
(((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 1) &&
((PciData.Bridge.PrefetchableMemoryBase & 0xFFF0) != 0 || (PciData.Bridge.PrefetchableMemoryLimit & 0xFFF0) != 0 || PciData.Bridge.PrefetchableBaseUpper32 != 0 || PciData.Bridge.PrefetchableLimitUpper32 != 0))) {
PciIoDevice->PciIo.Attributes(
&(PciIoDevice->PciIo),
EfiPciIoAttributeOperationEnable,
(EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
NULL
);
}
return EFI_SUCCESS;
}
EFI_STATUS
StartPciDevicesOnBridge (
IN EFI_HANDLE Controller,
IN PCI_IO_DEVICE *RootBridge,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
Arguments:
Controller - An efi handle.
RootBridge - A pointer to the PCI_IO_DEVICE.
RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
NumberOfChildren - Children number.
ChildHandleBuffer - A pointer to the child handle buffer.
Returns:
None
--*/
{
PCI_IO_DEVICE *Temp;
PCI_IO_DEVICE *PciIoDevice;
EFI_DEV_PATH_PTR Node;
EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
EFI_STATUS Status;
LIST_ENTRY *CurrentLink;
CurrentLink = RootBridge->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (RemainingDevicePath != NULL) {
Node.DevPath = RemainingDevicePath;
if (Node.Pci->Device != Temp->DeviceNumber ||
Node.Pci->Function != Temp->FunctionNumber) {
CurrentLink = CurrentLink->ForwardLink;
continue;
}
//
// Check if the device has been assigned with required resource
//
if (!Temp->Allocated) {
return EFI_NOT_READY;
}
//
// Check if the current node has been registered before
// If it is not, register it
//
if (!Temp->Registered) {
PciIoDevice = Temp;
Status = RegisterPciDevice (
Controller,
PciIoDevice,
NULL
);
}
//
// Get the next device path
//
CurrentDevicePath = NextDevicePathNode (RemainingDevicePath);
if (IsDevicePathEnd (CurrentDevicePath)) {
return EFI_SUCCESS;
}
//
// If it is a PPB
//
if (IS_PCI_BRIDGE (&(Temp->Pci))) {
Status = StartPciDevicesOnBridge (
Controller,
Temp,
CurrentDevicePath
);
EnableBridgeAttributes (Temp);
return Status;
} else {
//
// Currently, the PCI bus driver only support PCI-PCI bridge
//
return EFI_UNSUPPORTED;
}
} else {
//
// If remaining device path is NULL,
// try to enable all the pci devices under this bridge
//
if (!Temp->Registered && Temp->Allocated) {
PciIoDevice = Temp;
Status = RegisterPciDevice (
Controller,
PciIoDevice,
NULL
);
}
if (IS_PCI_BRIDGE (&(Temp->Pci))) {
Status = StartPciDevicesOnBridge (
Controller,
Temp,
RemainingDevicePath
);
EnableBridgeAttributes (Temp);
}
CurrentLink = CurrentLink->ForwardLink;
continue;
}
}
return EFI_NOT_FOUND;
}
EFI_STATUS
StartPciDevices (
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Start to manage the PCI device according to RemainingDevicePath
If RemainingDevicePath == NULL, the PCI bus driver will start
to manage all the PCI devices it found previously
Arguments:
Controller - An efi handle.
RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
Returns:
None
--*/
{
EFI_DEV_PATH_PTR Node;
PCI_IO_DEVICE *RootBridge;
LIST_ENTRY *CurrentLink;
if (RemainingDevicePath != NULL) {
//
// Check if the RemainingDevicePath is valid
//
Node.DevPath = RemainingDevicePath;
if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
Node.DevPath->SubType != HW_PCI_DP ||
DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)
) {
return EFI_UNSUPPORTED;
}
}
CurrentLink = gPciDevicePool.ForwardLink;
while (CurrentLink && CurrentLink != &gPciDevicePool) {
RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
//
// Locate the right root bridge to start
//
if (RootBridge->Handle == Controller) {
StartPciDevicesOnBridge (
Controller,
RootBridge,
RemainingDevicePath
);
}
CurrentLink = CurrentLink->ForwardLink;
}
return EFI_SUCCESS;
}
PCI_IO_DEVICE *
CreateRootBridge (
IN EFI_HANDLE RootBridgeHandle
)
/*++
Routine Description:
Arguments:
RootBridgeHandle - An efi handle.
Returns:
None
--*/
{
EFI_STATUS Status;
PCI_IO_DEVICE *Dev;
Dev = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (PCI_IO_DEVICE),
(VOID **) &Dev
);
if (EFI_ERROR (Status)) {
return NULL;
}
ZeroMem (Dev, sizeof (PCI_IO_DEVICE));
Dev->Signature = PCI_IO_DEVICE_SIGNATURE;
Dev->Handle = RootBridgeHandle;
InitializeListHead (&Dev->ChildList);
return Dev;
}
PCI_IO_DEVICE *
GetRootBridgeByHandle (
EFI_HANDLE RootBridgeHandle
)
/*++
Routine Description:
Arguments:
RootBridgeHandle - An efi handle.
Returns:
None
--*/
{
PCI_IO_DEVICE *RootBridgeDev;
LIST_ENTRY *CurrentLink;
CurrentLink = gPciDevicePool.ForwardLink;
while (CurrentLink && CurrentLink != &gPciDevicePool) {
RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (RootBridgeDev->Handle == RootBridgeHandle) {
return RootBridgeDev;
}
CurrentLink = CurrentLink->ForwardLink;
}
return NULL;
}
BOOLEAN
RootBridgeExisted (
IN EFI_HANDLE RootBridgeHandle
)
/*++
Routine Description:
This function searches if RootBridgeHandle has already existed
in current device pool.
If so, it means the given root bridge has been already enumerated.
Arguments:
RootBridgeHandle - An efi handle.
Returns:
None
--*/
{
PCI_IO_DEVICE *Bridge;
Bridge = GetRootBridgeByHandle (RootBridgeHandle);
if (Bridge != NULL) {
return TRUE;
}
return FALSE;
}
BOOLEAN
PciDeviceExisted (
IN PCI_IO_DEVICE *Bridge,
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Arguments:
Bridge - A pointer to the PCI_IO_DEVICE.
PciIoDevice - A pointer to the PCI_IO_DEVICE.
Returns:
None
--*/
{
PCI_IO_DEVICE *Temp;
LIST_ENTRY *CurrentLink;
CurrentLink = Bridge->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &Bridge->ChildList) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (Temp == PciIoDevice) {
return TRUE;
}
if (!IsListEmpty (&Temp->ChildList)) {
if (PciDeviceExisted (Temp, PciIoDevice)) {
return TRUE;
}
}
CurrentLink = CurrentLink->ForwardLink;
}
return FALSE;
}
PCI_IO_DEVICE *
ActiveVGADeviceOnTheSameSegment (
IN PCI_IO_DEVICE *VgaDevice
)
/*++
Routine Description:
Arguments:
VgaDevice - A pointer to the PCI_IO_DEVICE.
Returns:
None
--*/
{
LIST_ENTRY *CurrentLink;
PCI_IO_DEVICE *Temp;
CurrentLink = gPciDevicePool.ForwardLink;
while (CurrentLink && CurrentLink != &gPciDevicePool) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {
Temp = ActiveVGADeviceOnTheRootBridge (Temp);
if (Temp != NULL) {
return Temp;
}
}
CurrentLink = CurrentLink->ForwardLink;
}
return NULL;
}
PCI_IO_DEVICE *
ActiveVGADeviceOnTheRootBridge (
IN PCI_IO_DEVICE *RootBridge
)
/*++
Routine Description:
Arguments:
RootBridge - A pointer to the PCI_IO_DEVICE.
Returns:
None
--*/
{
LIST_ENTRY *CurrentLink;
PCI_IO_DEVICE *Temp;
CurrentLink = RootBridge->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (IS_PCI_VGA(&Temp->Pci) &&
(Temp->Attributes &
(EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |
EFI_PCI_IO_ATTRIBUTE_VGA_IO |
EFI_PCI_IO_ATTRIBUTE_VGA_IO_16))) {
return Temp;
}
if (IS_PCI_BRIDGE (&Temp->Pci)) {
Temp = ActiveVGADeviceOnTheRootBridge (Temp);
if (Temp != NULL) {
return Temp;
}
}
CurrentLink = CurrentLink->ForwardLink;
}
return NULL;
}

View File

@ -0,0 +1,324 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciDeviceSupport.h
Abstract:
Revision History
--*/
#ifndef _EFI_PCI_DEVICE_SUPPORT_H
#define _EFI_PCI_DEVICE_SUPPORT_H
EFI_STATUS
InitializePciDevicePool (
VOID
)
/*++
Routine Description:
TODO: Add function description
Arguments:
None
Returns:
TODO: add return values
--*/
;
EFI_STATUS
InsertPciDevice (
PCI_IO_DEVICE *Bridge,
PCI_IO_DEVICE *PciDeviceNode
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Bridge - TODO: add argument description
PciDeviceNode - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
DestroyPciDeviceTree (
IN PCI_IO_DEVICE *Bridge
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Bridge - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
DestroyRootBridgeByHandle (
EFI_HANDLE Controller
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Controller - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
RegisterPciDevice (
IN EFI_HANDLE Controller,
IN PCI_IO_DEVICE *PciIoDevice,
OUT EFI_HANDLE *Handle OPTIONAL
)
/*++
Routine Description:
This function registers the PCI IO device. It creates a handle for this PCI IO device
(if the handle does not exist), attaches appropriate protocols onto the handle, does
necessary initialization, and sets up parent/child relationship with its bus controller.
Arguments:
Controller - An EFI handle for the PCI bus controller.
PciIoDevice - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
Handle - A pointer to hold the EFI handle for the PCI IO device.
Returns:
EFI_SUCCESS - The PCI device is successfully registered.
Others - An error occurred when registering the PCI device.
--*/
;
EFI_STATUS
DeRegisterPciDevice (
IN EFI_HANDLE Controller,
IN EFI_HANDLE Handle
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Controller - TODO: add argument description
Handle - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
StartPciDevices (
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Controller - TODO: add argument description
RemainingDevicePath - TODO: add argument description
Returns:
TODO: add return values
--*/
;
PCI_IO_DEVICE *
CreateRootBridge (
IN EFI_HANDLE RootBridgeHandle
)
/*++
Routine Description:
TODO: Add function description
Arguments:
RootBridgeHandle - TODO: add argument description
Returns:
TODO: add return values
--*/
;
PCI_IO_DEVICE *
GetRootBridgeByHandle (
EFI_HANDLE RootBridgeHandle
)
/*++
Routine Description:
TODO: Add function description
Arguments:
RootBridgeHandle - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
InsertRootBridge (
PCI_IO_DEVICE *RootBridge
);
EFI_STATUS
DestroyRootBridge (
IN PCI_IO_DEVICE *RootBridge
);
BOOLEAN
RootBridgeExisted (
IN EFI_HANDLE RootBridgeHandle
)
/*++
Routine Description:
TODO: Add function description
Arguments:
RootBridgeHandle - TODO: add argument description
Returns:
TODO: add return values
--*/
;
BOOLEAN
PciDeviceExisted (
IN PCI_IO_DEVICE *Bridge,
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Bridge - TODO: add argument description
PciIoDevice - TODO: add argument description
Returns:
TODO: add return values
--*/
;
PCI_IO_DEVICE *
ActiveVGADeviceOnTheSameSegment (
IN PCI_IO_DEVICE *VgaDevice
)
/*++
Routine Description:
TODO: Add function description
Arguments:
VgaDevice - TODO: add argument description
Returns:
TODO: add return values
--*/
;
PCI_IO_DEVICE *
ActiveVGADeviceOnTheRootBridge (
IN PCI_IO_DEVICE *RootBridge
)
/*++
Routine Description:
TODO: Add function description
Arguments:
RootBridge - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

View File

@ -0,0 +1,176 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation. All rights reserved.<BR>
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:
PciDriverOverride.c
Abstract:
PCI Bus Driver
Revision History
--*/
#include "PciBus.h"
EFI_STATUS
EFIAPI
GetDriver(
IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,
IN OUT EFI_HANDLE *DriverImageHandle
);
EFI_STATUS
InitializePciDriverOverrideInstance (
PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Initializes a PCI Driver Override Instance
Arguments:
Returns:
None
--*/
{
PciIoDevice->PciDriverOverride.GetDriver = GetDriver;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
GetDriver (
IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,
IN OUT EFI_HANDLE *DriverImageHandle
)
/*++
Routine Description:
Get a overriding driver image
Arguments:
Returns:
None
--*/
{
PCI_IO_DEVICE *PciIoDevice;
LIST_ENTRY *CurrentLink;
PCI_DRIVER_OVERRIDE_LIST *Node;
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);
CurrentLink = PciIoDevice->OptionRomDriverList.ForwardLink;
while (CurrentLink && CurrentLink != &PciIoDevice->OptionRomDriverList) {
Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink);
if (*DriverImageHandle == NULL) {
*DriverImageHandle = Node->DriverImageHandle;
return EFI_SUCCESS;
}
if (*DriverImageHandle == Node->DriverImageHandle) {
if (CurrentLink->ForwardLink == &PciIoDevice->OptionRomDriverList ||
CurrentLink->ForwardLink == NULL) {
return EFI_NOT_FOUND;
}
//
// Get next node
//
Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink->ForwardLink);
*DriverImageHandle = Node->DriverImageHandle;
return EFI_SUCCESS;
}
CurrentLink = CurrentLink->ForwardLink;
}
return EFI_INVALID_PARAMETER;
}
EFI_STATUS
AddDriver (
IN PCI_IO_DEVICE *PciIoDevice,
IN EFI_HANDLE DriverImageHandle
)
/*++
Routine Description:
Add a overriding driver image
Arguments:
Returns:
None
--*/
{
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
PCI_DRIVER_OVERRIDE_LIST *Node;
Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);
if (EFI_ERROR (Status)) {
return Status;
}
Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST));
if (Node == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Node->Signature = DRIVER_OVERRIDE_SIGNATURE;
Node->DriverImageHandle = DriverImageHandle;
InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link));
PciIoDevice->BusOverride = TRUE;
ImageContext.Handle = LoadedImage->ImageBase;
ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
//
// Get information about the image
//
Status = PeCoffLoaderGetImageInfo (&ImageContext);
if (EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
if (ImageContext.Machine != EFI_IMAGE_MACHINE_EBC) {
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,110 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciDriverOverride.h
Abstract:
Revision History
--*/
#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H
#define _EFI_PCI_DRIVER_OVERRRIDE_H
#include "PciBus.h"
#define DRIVER_OVERRIDE_SIGNATURE SIGNATURE_32 ('d', 'r', 'o', 'v')
typedef struct {
UINT32 Signature;
LIST_ENTRY Link;
EFI_HANDLE DriverImageHandle;
} PCI_DRIVER_OVERRIDE_LIST;
#define DRIVER_OVERRIDE_FROM_LINK(a) \
CR (a, PCI_DRIVER_OVERRIDE_LIST, Link, DRIVER_OVERRIDE_SIGNATURE)
EFI_STATUS
InitializePciDriverOverrideInstance (
PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
TODO: Add function description
Arguments:
PciIoDevice - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
AddDriver (
IN PCI_IO_DEVICE *PciIoDevice,
IN EFI_HANDLE DriverImageHandle
)
/*++
Routine Description:
TODO: Add function description
Arguments:
PciIoDevice - TODO: add argument description
DriverImageHandle - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
EFIAPI
GetDriver (
IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,
IN OUT EFI_HANDLE *DriverImageHandle
)
/*++
Routine Description:
TODO: Add function description
Arguments:
This - TODO: add argument description
DriverImageHandle - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

View File

@ -0,0 +1,57 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciEnumerator.c
Abstract:
PCI Bus Driver
Revision History
--*/
#include "PciBus.h"
EFI_STATUS
PciEnumerator (
IN EFI_HANDLE Controller
)
/*++
Routine Description:
This routine is used to enumerate entire pci bus system
in a given platform
Arguments:
Returns:
None
--*/
{
//
// This PCI bus driver depends on the legacy BIOS
// to do the resource allocation
//
gFullEnumeration = FALSE;
return PciEnumeratorLight (Controller) ;
}

View File

@ -0,0 +1,47 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciEnumerator.h
Abstract:
PCI Bus Driver
Revision History
--*/
#ifndef _EFI_PCI_ENUMERATOR_H
#define _EFI_PCI_ENUMERATOR_H
EFI_STATUS
PciEnumerator (
IN EFI_HANDLE Controller
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Controller - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciEnumeratorSupport.h
Abstract:
PCI Bus Driver
Revision History
--*/
#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H
#define _EFI_PCI_ENUMERATOR_SUPPORT_H
#include "PciBus.h"
EFI_STATUS
PciPciDeviceInfoCollector (
IN PCI_IO_DEVICE *Bridge,
UINT8 StartBusNumber
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Bridge - TODO: add argument description
StartBusNumber - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
PciDevicePresent(
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
);
EFI_STATUS
PciEnumeratorLight (
IN EFI_HANDLE Controller
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Controller - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
PciGetBusRange (
IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
OUT UINT16 *MinBus,
OUT UINT16 *MaxBus,
OUT UINT16 *BusRange
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Descriptors - TODO: add argument description
MinBus - TODO: add argument description
MaxBus - TODO: add argument description
BusRange - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciIo.h
Abstract:
PCI Bus Driver
Revision History
--*/
#ifndef _EFI_PCI_IO_PROTOCOL_H
#define _EFI_PCI_IO_PROTOCOL_H
EFI_STATUS
InitializePciIoInstance (
PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
TODO: Add function description
Arguments:
PciIoDevice - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

View File

@ -0,0 +1,557 @@
/*++
Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
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:
PciOptionRomSupport.c
Abstract:
PCI Bus Driver
Revision History
--*/
#include "PciBus.h"
EFI_STATUS
RomDecode (
IN PCI_IO_DEVICE *PciDevice,
IN UINT8 RomBarIndex,
IN UINT32 RomBar,
IN BOOLEAN Enable
);
EFI_STATUS
GetOpRomInfo (
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
UINT8 RomBarIndex;
UINT32 AllOnes;
UINT64 Address;
EFI_STATUS Status;
UINT8 Bus;
UINT8 Device;
UINT8 Function;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
Bus = PciIoDevice->BusNumber;
Device = PciIoDevice->DeviceNumber;
Function = PciIoDevice->FunctionNumber;
PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
//
// offset is 0x30 if is not ppb
//
//
// 0x30
//
RomBarIndex = PCI_EXPANSION_ROM_BASE;
if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
//
// if is ppb
//
//
// 0x38
//
RomBarIndex = PCI_BRIDGE_ROMBAR;
}
//
// the bit0 is 0 to prevent the enabling of the Rom address decoder
//
AllOnes = 0xfffffffe;
Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);
Status = PciRootBridgeIo->Pci.Write (
PciRootBridgeIo,
EfiPciWidthUint32,
Address,
1,
&AllOnes
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// read back
//
Status = PciRootBridgeIo->Pci.Read (
PciRootBridgeIo,
EfiPciWidthUint32,
Address,
1,
&AllOnes
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Bits [1, 10] are reserved
//
AllOnes &= 0xFFFFF800;
if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {
return EFI_NOT_FOUND;
}
DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: OPROM detected!\n"));
DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: B-%x, D-%x, F-%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Function));
PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);
return EFI_SUCCESS;
}
EFI_STATUS
LoadOpRomImage (
IN PCI_IO_DEVICE *PciDevice,
IN UINT64 ReservedMemoryBase
)
/*++
Routine Description:
Load option rom image for specified PCI device
Arguments:
Returns:
--*/
{
UINT8 RomBarIndex;
UINT8 Indicator;
UINT16 OffsetPcir;
UINT32 RomBarOffset;
UINT32 RomBar;
EFI_STATUS retStatus;
BOOLEAN FirstCheck;
UINT8 *Image;
PCI_EXPANSION_ROM_HEADER *RomHeader;
PCI_DATA_STRUCTURE *RomPcir;
UINT64 RomSize;
UINT64 RomImageSize;
UINT32 LegacyImageLength;
UINT8 *RomInMemory;
UINT8 CodeType;
RomSize = PciDevice->RomSize;
Indicator = 0;
RomImageSize = 0;
RomInMemory = NULL;
CodeType = 0xFF;
//
// Get the RomBarIndex
//
//
// 0x30
//
RomBarIndex = PCI_EXPANSION_ROM_BASE;
if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {
//
// if is ppb
//
//
// 0x38
//
RomBarIndex = PCI_BRIDGE_ROMBAR;
}
//
// Allocate memory for Rom header and PCIR
//
RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));
if (RomHeader == NULL) {
return EFI_OUT_OF_RESOURCES;
}
RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));
if (RomPcir == NULL) {
gBS->FreePool (RomHeader);
return EFI_OUT_OF_RESOURCES;
}
RomBar = (UINT32)ReservedMemoryBase;
//
// Enable RomBar
//
RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);
RomBarOffset = RomBar;
retStatus = EFI_NOT_FOUND;
FirstCheck = TRUE;
LegacyImageLength = 0;
do {
PciDevice->PciRootBridgeIo->Mem.Read (
PciDevice->PciRootBridgeIo,
EfiPciWidthUint8,
RomBarOffset,
sizeof (PCI_EXPANSION_ROM_HEADER),
(UINT8 *) RomHeader
);
if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
RomBarOffset = RomBarOffset + 512;
if (FirstCheck) {
break;
} else {
RomImageSize = RomImageSize + 512;
continue;
}
}
FirstCheck = FALSE;
OffsetPcir = RomHeader->PcirOffset;
//
// If the pointer to the PCI Data Structure is invalid, no further images can be located.
// The PCI Data Structure must be DWORD aligned.
//
if (OffsetPcir == 0 ||
(OffsetPcir & 3) != 0 ||
RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > RomSize) {
break;
}
PciDevice->PciRootBridgeIo->Mem.Read (
PciDevice->PciRootBridgeIo,
EfiPciWidthUint8,
RomBarOffset + OffsetPcir,
sizeof (PCI_DATA_STRUCTURE),
(UINT8 *) RomPcir
);
//
// If a valid signature is not present in the PCI Data Structure, no further images can be located.
//
if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
break;
}
if (RomImageSize + RomPcir->ImageLength * 512 > RomSize) {
break;
}
if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
CodeType = PCI_CODE_TYPE_PCAT_IMAGE;
LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512;
}
Indicator = RomPcir->Indicator;
RomImageSize = RomImageSize + RomPcir->ImageLength * 512;
RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512;
} while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));
//
// Some Legacy Cards do not report the correct ImageLength so used the maximum
// of the legacy length and the PCIR Image Length
//
if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
RomImageSize = MAX (RomImageSize, LegacyImageLength);
}
if (RomImageSize > 0) {
retStatus = EFI_SUCCESS;
Image = AllocatePool ((UINT32) RomImageSize);
if (Image == NULL) {
RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
gBS->FreePool (RomHeader);
gBS->FreePool (RomPcir);
return EFI_OUT_OF_RESOURCES;
}
//
// Copy Rom image into memory
//
PciDevice->PciRootBridgeIo->Mem.Read (
PciDevice->PciRootBridgeIo,
EfiPciWidthUint8,
RomBar,
(UINT32) RomImageSize,
Image
);
RomInMemory = Image;
}
RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
PciDevice->PciIo.RomSize = RomImageSize;
PciDevice->PciIo.RomImage = RomInMemory;
//
// Free allocated memory
//
gBS->FreePool (RomHeader);
gBS->FreePool (RomPcir);
return retStatus;
}
EFI_STATUS
RomDecode (
IN PCI_IO_DEVICE *PciDevice,
IN UINT8 RomBarIndex,
IN UINT32 RomBar,
IN BOOLEAN Enable
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
UINT16 CommandValue;
UINT32 Value32;
UINT64 Address;
//EFI_STATUS Status;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
PciRootBridgeIo = PciDevice->PciRootBridgeIo;
if (Enable) {
Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);
//
// set the Rom base address: now is hardcode
//
PciRootBridgeIo->Pci.Write(
PciRootBridgeIo,
EfiPciWidthUint32,
Address,
1,
&RomBar);
//
// enable its decoder
//
Value32 = RomBar | 0x1;
PciRootBridgeIo->Pci.Write(
PciRootBridgeIo,
EfiPciWidthUint32,
Address,
1,
&Value32);
//
//setting the memory space bit in the function's command register
//
Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, 0x04);
PciRootBridgeIo->Pci.Read(
PciRootBridgeIo,
EfiPciWidthUint16,
Address,
1,
&CommandValue);
CommandValue = (UINT16)(CommandValue | 0x0002); //0x0003
PciRootBridgeIo->Pci.Write(
PciRootBridgeIo,
EfiPciWidthUint16,
Address,
1,
&CommandValue);
} else {
//
// disable rom decode
//
Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);
Value32 = 0xfffffffe;
PciRootBridgeIo->Pci.Write(
PciRootBridgeIo,
EfiPciWidthUint32,
Address,
1,
&Value32);
}
return EFI_SUCCESS;
}
EFI_STATUS
ProcessOpRomImage (
PCI_IO_DEVICE *PciDevice
)
/*++
Routine Description:
Process the oprom image.
Arguments:
PciDevice A pointer to a pci device.
Returns:
EFI Status.
--*/
{
UINT8 Indicator;
UINT32 ImageSize;
UINT16 ImageOffset;
VOID *RomBar;
UINT8 *RomBarOffset;
EFI_HANDLE ImageHandle;
EFI_STATUS Status;
EFI_STATUS retStatus;
BOOLEAN SkipImage;
UINT32 DestinationSize;
UINT32 ScratchSize;
UINT8 *Scratch;
VOID *ImageBuffer;
VOID *DecompressedImageBuffer;
UINT32 ImageLength;
EFI_DECOMPRESS_PROTOCOL *Decompress;
EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
PCI_DATA_STRUCTURE *Pcir;
UINT32 InitializationSize;
Indicator = 0;
//
// Get the Address of the Rom image
//
RomBar = PciDevice->PciIo.RomImage;
RomBarOffset = (UINT8 *) RomBar;
retStatus = EFI_NOT_FOUND;
if (RomBarOffset == NULL) {
return retStatus;
}
ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset)->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE);
do {
EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;
if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
RomBarOffset = RomBarOffset + 512;
continue;
}
Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);
ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);
ImageSize = (UINT32) (Pcir->ImageLength * 512);
Indicator = Pcir->Indicator;
if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
(EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
(EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {
ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
InitializationSize = EfiRomHeader->InitializationSize * 512;
if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {
ImageBuffer = (VOID *) (RomBarOffset + ImageOffset);
ImageLength = InitializationSize - (UINT32)ImageOffset;
DecompressedImageBuffer = NULL;
//
// decompress here if needed
//
SkipImage = FALSE;
if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
SkipImage = TRUE;
}
if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
if (EFI_ERROR (Status)) {
SkipImage = TRUE;
} else {
SkipImage = TRUE;
Status = Decompress->GetInfo (
Decompress,
ImageBuffer,
ImageLength,
&DestinationSize,
&ScratchSize
);
if (!EFI_ERROR (Status)) {
DecompressedImageBuffer = NULL;
DecompressedImageBuffer = AllocatePool (DestinationSize);
if (DecompressedImageBuffer != NULL) {
Scratch = AllocatePool (ScratchSize);
if (Scratch != NULL) {
Status = Decompress->Decompress (
Decompress,
ImageBuffer,
ImageLength,
DecompressedImageBuffer,
DestinationSize,
Scratch,
ScratchSize
);
if (!EFI_ERROR (Status)) {
ImageBuffer = DecompressedImageBuffer;
ImageLength = DestinationSize;
SkipImage = FALSE;
}
gBS->FreePool (Scratch);
}
}
}
}
}
if (!SkipImage) {
//
// load image and start image
//
Status = gBS->LoadImage (
FALSE,
gPciBusDriverBinding.DriverBindingHandle,
NULL,
ImageBuffer,
ImageLength,
&ImageHandle
);
if (!EFI_ERROR (Status)) {
Status = gBS->StartImage (ImageHandle, NULL, NULL);
if (!EFI_ERROR (Status)) {
AddDriver (PciDevice, ImageHandle);
retStatus = EFI_SUCCESS;
}
}
}
RomBarOffset = RomBarOffset + ImageSize;
} else {
RomBarOffset = RomBarOffset + ImageSize;
}
} else {
RomBarOffset = RomBarOffset + ImageSize;
}
} while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));
return retStatus;
}

View File

@ -0,0 +1,92 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciOptionRomSupport.h
Abstract:
PCI Bus Driver
Revision History
--*/
#ifndef _EFI_PCI_OP_ROM_SUPPORT_H
#define _EFI_PCI_OP_ROM_SUPPORT_H
EFI_STATUS
GetOpRomInfo (
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
TODO: Add function description
Arguments:
PciIoDevice - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
LoadOpRomImage (
IN PCI_IO_DEVICE *PciDevice,
IN UINT64 ReservedMemoryBase
)
/*++
Routine Description:
TODO: Add function description
Arguments:
PciDevice - TODO: add argument description
RomBase - TODO: add argument description
Returns:
TODO: add return values
--*/
;
EFI_STATUS
ProcessOpRomImage (
PCI_IO_DEVICE *PciDevice
)
/*++
Routine Description:
TODO: Add function description
Arguments:
PciDevice - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

View File

@ -0,0 +1,100 @@
/*++
Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
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:
PciPowerManagement.c
Abstract:
PCI Bus Driver
Revision History
--*/
#include "PciBus.h"
EFI_STATUS
EFIAPI
ResetPowerManagementFeature (
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
This function is intended to turn off PWE assertion and
put the device to D0 state if the device supports
PCI Power Management.
Arguments:
Returns:
None
--*/
{
EFI_STATUS Status;
UINT8 PowerManagementRegBlock;
UINT16 PowerManagementCSR;
PowerManagementRegBlock = 0;
Status = LocateCapabilityRegBlock (
PciIoDevice,
EFI_PCI_CAPABILITY_ID_PMI,
&PowerManagementRegBlock,
NULL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
//
// Turn off the PWE assertion and put the device into D0 State
//
//
// Read PMCSR
//
Status = PciIoDevice->PciIo.Pci.Read (
&PciIoDevice->PciIo,
EfiPciIoWidthUint16,
PowerManagementRegBlock + 4,
1,
&PowerManagementCSR
);
if (!EFI_ERROR (Status)) {
//
// Clear PME_Status bit
//
PowerManagementCSR |= BIT15;
//
// Clear PME_En bit. PowerState = D0.
//
PowerManagementCSR &= ~(BIT8 | BIT1 | BIT0);
//
// Write PMCSR
//
Status = PciIoDevice->PciIo.Pci.Write (
&PciIoDevice->PciIo,
EfiPciIoWidthUint16,
PowerManagementRegBlock + 4,
1,
&PowerManagementCSR
);
}
return Status;
}

View File

@ -0,0 +1,49 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciPowerManagement.h
Abstract:
PCI Bus Driver
Revision History
--*/
#ifndef _EFI_PCI_POWER_MANAGEMENT_H
#define _EFI_PCI_POWER_MANAGEMENT_H
EFI_STATUS
EFIAPI
ResetPowerManagementFeature (
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
TODO: Add function description
Arguments:
PciIoDevice - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

View File

@ -0,0 +1,393 @@
/*++
Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
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:
PciRomTable.c
Abstract:
Option Rom Support for PCI Bus Driver
Revision History
--*/
#include "PciBus.h"
typedef struct {
EFI_HANDLE ImageHandle;
UINTN Seg;
UINT8 Bus;
UINT8 Dev;
UINT8 Func;
} EFI_PCI_ROM_IMAGE_MAPPING;
UINTN mNumberOfPciRomImages = 0;
UINTN mMaxNumberOfPciRomImages = 0;
EFI_PCI_ROM_IMAGE_MAPPING *mRomImageTable = NULL;
CHAR16 mHexDigit[17] = L"0123456789ABCDEF";
VOID
PciRomAddImageMapping (
IN EFI_HANDLE ImageHandle,
IN UINTN Seg,
IN UINT8 Bus,
IN UINT8 Dev,
IN UINT8 Func
)
{
EFI_PCI_ROM_IMAGE_MAPPING *TempMapping;
if (mNumberOfPciRomImages >= mMaxNumberOfPciRomImages) {
mMaxNumberOfPciRomImages += 0x20;
TempMapping = NULL;
TempMapping = AllocatePool (mMaxNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));
if (TempMapping == NULL) {
return ;
}
CopyMem (TempMapping, mRomImageTable, mNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));
if (mRomImageTable != NULL) {
gBS->FreePool (mRomImageTable);
}
mRomImageTable = TempMapping;
}
mRomImageTable[mNumberOfPciRomImages].ImageHandle = ImageHandle;
mRomImageTable[mNumberOfPciRomImages].Seg = Seg;
mRomImageTable[mNumberOfPciRomImages].Bus = Bus;
mRomImageTable[mNumberOfPciRomImages].Dev = Dev;
mRomImageTable[mNumberOfPciRomImages].Func = Func;
mNumberOfPciRomImages++;
}
VOID
HexToString (
CHAR16 *String,
UINTN Value,
UINTN Digits
)
{
for (; Digits > 0; Digits--, String++) {
*String = mHexDigit[((Value >> (4*(Digits-1))) & 0x0f)];
}
}
EFI_STATUS
PciRomLoadEfiDriversFromRomImage (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor
)
/*++
Routine Description:
Command entry point.
Arguments:
ImageHandle The image handle.
SystemTable The system table.
Returns:
EFI_SUCCESS - The command completed successfully
EFI_INVALID_PARAMETER - Command usage error
EFI_UNSUPPORTED - Protocols unsupported
EFI_OUT_OF_RESOURCES - Out of memory
Other value - Unknown error
--*/
{
VOID *RomBar;
UINTN RomSize;
CHAR16 *FileName;
EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
PCI_DATA_STRUCTURE *Pcir;
UINTN ImageIndex;
UINTN RomBarOffset;
UINT32 ImageSize;
UINT16 ImageOffset;
EFI_HANDLE ImageHandle;
EFI_STATUS Status;
EFI_STATUS retStatus;
EFI_DEVICE_PATH_PROTOCOL *FilePath;
BOOLEAN SkipImage;
UINT32 DestinationSize;
UINT32 ScratchSize;
UINT8 *Scratch;
VOID *ImageBuffer;
VOID *DecompressedImageBuffer;
UINT32 ImageLength;
EFI_DECOMPRESS_PROTOCOL *Decompress;
UINT32 InitializationSize;
RomBar = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
FileName = L"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";
HexToString (&FileName[11], PciOptionRomDescriptor->Seg, 8);
HexToString (&FileName[24], PciOptionRomDescriptor->Bus, 2);
HexToString (&FileName[31], PciOptionRomDescriptor->Dev, 2);
HexToString (&FileName[39], PciOptionRomDescriptor->Func, 2);
ImageIndex = 0;
retStatus = EFI_NOT_FOUND;
RomBarOffset = (UINTN) RomBar;
do {
EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
return retStatus;
}
//
// If the pointer to the PCI Data Structure is invalid, no further images can be located.
// The PCI Data Structure must be DWORD aligned.
//
if (EfiRomHeader->PcirOffset == 0 ||
(EfiRomHeader->PcirOffset & 3) != 0 ||
RomBarOffset - (UINTN)RomBar + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) {
break;
}
Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
//
// If a valid signature is not present in the PCI Data Structure, no further images can be located.
//
if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
break;
}
ImageSize = Pcir->ImageLength * 512;
if (RomBarOffset - (UINTN)RomBar + ImageSize > RomSize) {
break;
}
if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
(EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
(EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {
ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
InitializationSize = EfiRomHeader->InitializationSize * 512;
if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {
ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
ImageLength = InitializationSize - ImageOffset;
DecompressedImageBuffer = NULL;
//
// decompress here if needed
//
SkipImage = FALSE;
if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
SkipImage = TRUE;
}
if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
if (EFI_ERROR (Status)) {
SkipImage = TRUE;
} else {
SkipImage = TRUE;
Status = Decompress->GetInfo (
Decompress,
ImageBuffer,
ImageLength,
&DestinationSize,
&ScratchSize
);
if (!EFI_ERROR (Status)) {
DecompressedImageBuffer = NULL;
DecompressedImageBuffer = AllocatePool (DestinationSize);
if (DecompressedImageBuffer != NULL) {
Scratch = AllocatePool (ScratchSize);
if (Scratch != NULL) {
Status = Decompress->Decompress (
Decompress,
ImageBuffer,
ImageLength,
DecompressedImageBuffer,
DestinationSize,
Scratch,
ScratchSize
);
if (!EFI_ERROR (Status)) {
ImageBuffer = DecompressedImageBuffer;
ImageLength = DestinationSize;
SkipImage = FALSE;
}
gBS->FreePool (Scratch);
}
}
}
}
}
if (!SkipImage) {
//
// load image and start image
//
HexToString (&FileName[48], ImageIndex, 4);
FilePath = FileDevicePath (NULL, FileName);
Status = gBS->LoadImage (
FALSE,
This->ImageHandle,
FilePath,
ImageBuffer,
ImageLength,
&ImageHandle
);
if (!EFI_ERROR (Status)) {
Status = gBS->StartImage (ImageHandle, NULL, NULL);
if (!EFI_ERROR (Status)) {
PciRomAddImageMapping (
ImageHandle,
PciOptionRomDescriptor->Seg,
PciOptionRomDescriptor->Bus,
PciOptionRomDescriptor->Dev,
PciOptionRomDescriptor->Func
);
retStatus = Status;
}
}
if (FilePath != NULL) {
gBS->FreePool (FilePath);
}
}
if (DecompressedImageBuffer != NULL) {
gBS->FreePool (DecompressedImageBuffer);
}
}
}
RomBarOffset = RomBarOffset + ImageSize;
ImageIndex++;
} while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
return retStatus;
}
EFI_STATUS
PciRomLoadEfiDriversFromOptionRomTable (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
EFI_STATUS Status;
EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
UINTN Index;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
UINT16 MinBus;
UINT16 MaxBus;
Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
Status = EFI_NOT_FOUND;
for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
if (!PciOptionRomDescriptor->DontLoadEfiRom) {
if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber) {
Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
if (EFI_ERROR (Status)) {
return Status;
}
PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL);
if ((MinBus <= PciOptionRomDescriptor->Bus) && (PciOptionRomDescriptor->Bus <= MaxBus)) {
Status = PciRomLoadEfiDriversFromRomImage (This, PciOptionRomDescriptor);
PciOptionRomDescriptor->DontLoadEfiRom |= 2;
}
}
}
}
return Status;
}
EFI_STATUS
PciRomGetRomResourceFromPciOptionRomTable (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
EFI_STATUS Status;
EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
UINTN Index;
Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber &&
PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber &&
PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber &&
PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) {
PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
PciIoDevice->PciIo.RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
}
}
for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber &&
mRomImageTable[Index].Bus == PciIoDevice->BusNumber &&
mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber &&
mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) {
AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
}
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,58 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PciRomTable.h
Abstract:
Option Rom Support for PCI Bus Driver
Revision History
--*/
#ifndef _EFI_PCI_ROM_TABLE_H
#define _EFI_PCI_ROM_TABLE_H
EFI_STATUS
PciRomLoadEfiDriversFromOptionRomTable (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo
);
EFI_STATUS
PciRomGetRomResourceFromPciOptionRomTable (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
TODO: Add function description
Arguments:
This - TODO: add argument description
PciRootBridgeIo - TODO: add argument description
PciIoDevice - TODO: add argument description
Returns:
TODO: add return values
--*/
;
#endif

View File

@ -0,0 +1,845 @@
/*++
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
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:
DeviceIo.c
Abstract:
EFI PC-AT PCI Device IO driver
--*/
#include "PcatPciRootBridge.h"
#include "DeviceIo.h"
EFI_STATUS
DeviceIoConstructor (
IN EFI_HANDLE Handle,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN UINT16 PrimaryBus,
IN UINT16 SubordinateBus
)
/*++
Routine Description:
Initialize and install a Device IO protocol on a empty device path handle.
Arguments:
Handle - Handle of PCI RootBridge IO instance
PciRootBridgeIo - PCI RootBridge IO instance
DevicePath - Device Path of PCI RootBridge IO instance
PrimaryBus - Primary Bus
SubordinateBus - Subordinate Bus
Returns:
EFI_SUCCESS - This driver is added to ControllerHandle.
EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
Others - This driver does not support this device.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
//
// Initialize the Device IO device instance.
//
Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA));
if (Private == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Private->Signature = DEVICE_IO_PRIVATE_DATA_SIGNATURE;
Private->Handle = Handle;
Private->PciRootBridgeIo = PciRootBridgeIo;
Private->DevicePath = DevicePath;
Private->PrimaryBus = PrimaryBus;
Private->SubordinateBus = SubordinateBus;
Private->DeviceIo.Mem.Read = DeviceIoMemRead;
Private->DeviceIo.Mem.Write = DeviceIoMemWrite;
Private->DeviceIo.Io.Read = DeviceIoIoRead;
Private->DeviceIo.Io.Write = DeviceIoIoWrite;
Private->DeviceIo.Pci.Read = DeviceIoPciRead;
Private->DeviceIo.Pci.Write = DeviceIoPciWrite;
Private->DeviceIo.PciDevicePath = DeviceIoPciDevicePath;
Private->DeviceIo.Map = DeviceIoMap;
Private->DeviceIo.Unmap = DeviceIoUnmap;
Private->DeviceIo.AllocateBuffer = DeviceIoAllocateBuffer;
Private->DeviceIo.Flush = DeviceIoFlush;
Private->DeviceIo.FreeBuffer = DeviceIoFreeBuffer;
//
// Install protocol interfaces for the Device IO device.
//
Status = gBS->InstallMultipleProtocolInterfaces (
&Private->Handle,
&gEfiDeviceIoProtocolGuid,
&Private->DeviceIo,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoMemRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading memory mapped I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Width > MMIO_COPY_UINT64) {
return EFI_INVALID_PARAMETER;
}
if (Width >= MMIO_COPY_UINT8) {
Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
Status = Private->PciRootBridgeIo->CopyMem (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
(UINT64)(UINTN) Buffer,
Address,
Count
);
} else {
Status = Private->PciRootBridgeIo->Mem.Read (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
}
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoMemWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing memory mapped I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Width > MMIO_COPY_UINT64) {
return EFI_INVALID_PARAMETER;
}
if (Width >= MMIO_COPY_UINT8) {
Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
Status = Private->PciRootBridgeIo->CopyMem (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
(UINT64)(UINTN) Buffer,
Count
);
} else {
Status = Private->PciRootBridgeIo->Mem.Write (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
}
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoIoRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Width >= MMIO_COPY_UINT8) {
return EFI_INVALID_PARAMETER;
}
Status = Private->PciRootBridgeIo->Io.Read (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoIoWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if (Width >= MMIO_COPY_UINT8) {
return EFI_INVALID_PARAMETER;
}
Status = Private->PciRootBridgeIo->Io.Write (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoPciRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading PCI configuration space of device
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if ((UINT32)Width >= MMIO_COPY_UINT8) {
return EFI_INVALID_PARAMETER;
}
Status = Private->PciRootBridgeIo->Pci.Read (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoPciWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing PCI configuration space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if ((UINT32)Width >= MMIO_COPY_UINT8) {
return EFI_INVALID_PARAMETER;
}
Status = Private->PciRootBridgeIo->Pci.Write (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Address,
Count,
Buffer
);
return Status;
}
EFI_DEVICE_PATH_PROTOCOL *
AppendPciDevicePath (
IN DEVICE_IO_PRIVATE_DATA *Private,
IN UINT8 Bus,
IN UINT8 Device,
IN UINT8 Function,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN OUT UINT16 *BridgePrimaryBus,
IN OUT UINT16 *BridgeSubordinateBus
)
/*++
Routine Description:
Append a PCI device path node to another device path.
Arguments:
Private - A pointer to DEVICE_IO_PRIVATE_DATA instance.
Bus - PCI bus number of the device.
Device - PCI device number of the device.
Function - PCI function number of the device.
DevicePath - Original device path which will be appended a PCI device path node.
BridgePrimaryBus - Primary bus number of the bridge.
BridgeSubordinateBus - Subordinate bus number of the bridge.
Returns:
Pointer to the appended PCI device path.
--*/
{
UINT16 ThisBus;
UINT8 ThisDevice;
UINT8 ThisFunc;
UINT64 Address;
PCI_TYPE01 PciBridge;
PCI_TYPE01 *PciPtr;
EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
PCI_DEVICE_PATH PciNode;
PciPtr = &PciBridge;
for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
ZeroMem (PciPtr, sizeof (PCI_TYPE01));
Private->DeviceIo.Pci.Read (
&Private->DeviceIo,
IO_UINT32,
Address,
1,
&(PciPtr->Hdr.VendorId)
);
if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
break;
}
if (PciPtr->Hdr.VendorId == 0xffff) {
continue;
}
Private->DeviceIo.Pci.Read (
&Private->DeviceIo,
IO_UINT32,
Address,
sizeof (PCI_TYPE01) / sizeof (UINT32),
PciPtr
);
if (IS_PCI_BRIDGE (PciPtr)) {
if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
PciNode.Header.Type = HARDWARE_DEVICE_PATH;
PciNode.Header.SubType = HW_PCI_DP;
SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
PciNode.Device = ThisDevice;
PciNode.Function = ThisFunc;
ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
*BridgePrimaryBus = PciPtr->Bridge.SecondaryBus;
*BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
return ReturnDevicePath;
}
}
if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {
//
// Skip sub functions, this is not a multi function device
//
break;
}
}
}
}
ZeroMem (&PciNode, sizeof (PciNode));
PciNode.Header.Type = HARDWARE_DEVICE_PATH;
PciNode.Header.SubType = HW_PCI_DP;
SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
PciNode.Device = Device;
PciNode.Function = Function;
ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
*BridgePrimaryBus = 0xffff;
*BridgeSubordinateBus = 0xffff;
return ReturnDevicePath;
}
EFI_STATUS
EFIAPI
DeviceIoPciDevicePath (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN UINT64 Address,
IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
)
/*++
Routine Description:
Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Address - The PCI configuration space address of the device whose Device Path
is going to be returned.
PciDevicePath - A pointer to the pointer for the EFI Device Path for PciAddress.
Memory for the Device Path is allocated from the pool.
Returns:
EFI_SUCCESS - The PciDevicePath returns a pointer to a valid EFI Device Path.
EFI_UNSUPPORTED - The PciAddress does not map to a valid EFI Device Path.
EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
--*/
{
DEVICE_IO_PRIVATE_DATA *Private;
UINT16 PrimaryBus;
UINT16 SubordinateBus;
UINT8 Bus;
UINT8 Device;
UINT8 Func;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
Bus = (UINT8) (((UINT32) Address >> 24) & 0xff);
Device = (UINT8) (((UINT32) Address >> 16) & 0xff);
Func = (UINT8) (((UINT32) Address >> 8) & 0xff);
if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
return EFI_UNSUPPORTED;
}
*PciDevicePath = Private->DevicePath;
PrimaryBus = Private->PrimaryBus;
SubordinateBus = Private->SubordinateBus;
do {
*PciDevicePath = AppendPciDevicePath (
Private,
Bus,
Device,
Func,
*PciDevicePath,
&PrimaryBus,
&SubordinateBus
);
if (*PciDevicePath == NULL) {
return EFI_OUT_OF_RESOURCES;
}
} while (PrimaryBus != 0xffff);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
DeviceIoMap (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_OPERATION_TYPE Operation,
IN EFI_PHYSICAL_ADDRESS *HostAddress,
IN OUT UINTN *NumberOfBytes,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT VOID **Mapping
)
/*++
Routine Description:
Provides the device-specific addresses needed to access system memory.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Operation - Indicates if the bus master is going to read or write to system memory.
HostAddress - The system memory address to map to the device.
NumberOfBytes - On input the number of bytes to map. On output the number of bytes
that were mapped.
DeviceAddress - The resulting map address for the bus master device to use to access the
hosts HostAddress.
Mapping - A resulting value to pass to Unmap().
Returns:
EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.
EFI_DEVICE_ERROR - The system hardware could not map the requested address.
EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
if ((UINT32)Operation > EfiBusMasterCommonBuffer) {
return EFI_INVALID_PARAMETER;
}
if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
return EFI_UNSUPPORTED;
}
Status = Private->PciRootBridgeIo->Map (
Private->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
(VOID *) (UINTN) (*HostAddress),
NumberOfBytes,
DeviceAddress,
Mapping
);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoUnmap (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN VOID *Mapping
)
/*++
Routine Description:
Completes the Map() operation and releases any corresponding resources.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Mapping - The mapping value returned from Map().
Returns:
EFI_SUCCESS - The range was unmapped.
EFI_DEVICE_ERROR - The data was not committed to the target system memory.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
Status = Private->PciRootBridgeIo->Unmap (
Private->PciRootBridgeIo,
Mapping
);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoAllocateBuffer (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress
)
/*++
Routine Description:
Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Type - The type allocation to perform.
MemoryType - The type of memory to allocate, EfiBootServicesData or
EfiRuntimeServicesData.
Pages - The number of pages to allocate.
PhysicalAddress - A pointer to store the base address of the allocated range.
Returns:
EFI_SUCCESS - The requested memory pages were allocated.
EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
EFI_INVALID_PARAMETER - The requested memory type is invalid.
EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on
this platform.
--*/
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS HostAddress;
HostAddress = *PhysicalAddress;
if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
return EFI_INVALID_PARAMETER;
}
if ((UINT32)Type >= MaxAllocateType) {
return EFI_INVALID_PARAMETER;
}
if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
return EFI_UNSUPPORTED;
}
if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
Type = AllocateMaxAddress;
HostAddress = MAX_COMMON_BUFFER;
}
Status = gBS->AllocatePages (
Type,
MemoryType,
Pages,
&HostAddress
);
if (EFI_ERROR (Status)) {
return Status;
}
*PhysicalAddress = HostAddress;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
DeviceIoFlush (
IN EFI_DEVICE_IO_PROTOCOL *This
)
/*++
Routine Description:
Flushes any posted write data to the device.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Returns:
EFI_SUCCESS - The buffers were flushed.
EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
--*/
{
EFI_STATUS Status;
DEVICE_IO_PRIVATE_DATA *Private;
Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
Status = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
return Status;
}
EFI_STATUS
EFIAPI
DeviceIoFreeBuffer (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN UINTN Pages,
IN EFI_PHYSICAL_ADDRESS HostAddress
)
/*++
Routine Description:
Frees pages that were allocated with AllocateBuffer().
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Pages - The number of pages to free.
HostAddress - The base address of the range to free.
Returns:
EFI_SUCCESS - The requested memory pages were freed.
EFI_NOT_FOUND - The requested memory pages were not allocated with
AllocateBuffer().
EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.
--*/
{
if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
return EFI_INVALID_PARAMETER;
}
return gBS->FreePages (HostAddress, Pages);
}

View File

@ -0,0 +1,449 @@
/*++
Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
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:
DeviceIo.h
Abstract:
Private Data definition for Device IO driver
--*/
#ifndef _DEVICE_IO_H
#define _DEVICE_IO_H
#define DEVICE_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('d', 'e', 'v', 'I')
#define MAX_COMMON_BUFFER 0x00000000FFFFFFFF
typedef struct {
UINTN Signature;
EFI_HANDLE Handle;
EFI_DEVICE_IO_PROTOCOL DeviceIo;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
UINT16 PrimaryBus;
UINT16 SubordinateBus;
} DEVICE_IO_PRIVATE_DATA;
#define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)
EFI_STATUS
DeviceIoConstructor (
IN EFI_HANDLE Handle,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN UINT16 PrimaryBus,
IN UINT16 SubordinateBus
)
/*++
Routine Description:
Initialize and install a Device IO protocol on a empty device path handle.
Arguments:
Handle - Handle of PCI RootBridge IO instance
PciRootBridgeIo - PCI RootBridge IO instance
DevicePath - Device Path of PCI RootBridge IO instance
PrimaryBus - Primary Bus
SubordinateBus - Subordinate Bus
Returns:
EFI_SUCCESS - This driver is added to ControllerHandle.
EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
Others - This driver does not support this device.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoMemRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading memory mapped I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoMemWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing memory mapped I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoIoRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoIoWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing I/O space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoPciRead (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform reading PCI configuration space of device
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The destination buffer to store results.
Returns:
EFI_SUCCESS - The data was read from the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoPciWrite (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Perform writing PCI configuration space of device.
Arguments:
This - A pointer to EFI_DEVICE_IO protocol instance.
Width - Width of I/O operations.
Address - The base address of I/O operations.
Count - The number of I/O operations to perform.
Bytes moves is Width size * Count, starting at Address.
Buffer - The source buffer of data to be written.
Returns:
EFI_SUCCESS - The data was written to the device.
EFI_INVALID_PARAMETER - Width is invalid.
EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoPciDevicePath (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN UINT64 Address,
IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
)
/*++
Routine Description:
Append a PCI device path node to another device path.
Arguments:
This - A pointer to EFI_DEVICE_IO_PROTOCOL.
Address - PCI bus,device, function.
PciDevicePath - PCI device path.
Returns:
Pointer to the appended PCI device path.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoMap (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_IO_OPERATION_TYPE Operation,
IN EFI_PHYSICAL_ADDRESS *HostAddress,
IN OUT UINTN *NumberOfBytes,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT VOID **Mapping
)
/*++
Routine Description:
Provides the device-specific addresses needed to access system memory.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Operation - Indicates if the bus master is going to read or write to system memory.
HostAddress - The system memory address to map to the device.
NumberOfBytes - On input the number of bytes to map. On output the number of bytes
that were mapped.
DeviceAddress - The resulting map address for the bus master device to use to access the
hosts HostAddress.
Mapping - A resulting value to pass to Unmap().
Returns:
EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.
EFI_DEVICE_ERROR - The system hardware could not map the requested address.
EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoUnmap (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN VOID *Mapping
)
/*++
Routine Description:
Completes the Map() operation and releases any corresponding resources.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Mapping - The mapping value returned from Map().
Returns:
EFI_SUCCESS - The range was unmapped.
EFI_DEVICE_ERROR - The data was not committed to the target system memory.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoAllocateBuffer (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT EFI_PHYSICAL_ADDRESS *HostAddress
)
/*++
Routine Description:
Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Type - The type allocation to perform.
MemoryType - The type of memory to allocate, EfiBootServicesData or
EfiRuntimeServicesData.
Pages - The number of pages to allocate.
HostAddress - A pointer to store the base address of the allocated range.
Returns:
EFI_SUCCESS - The requested memory pages were allocated.
EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
EFI_INVALID_PARAMETER - The requested memory type is invalid.
EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on
this platform.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoFlush (
IN EFI_DEVICE_IO_PROTOCOL *This
)
/*++
Routine Description:
Flushes any posted write data to the device.
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Returns:
EFI_SUCCESS - The buffers were flushed.
EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
--*/
;
EFI_STATUS
EFIAPI
DeviceIoFreeBuffer (
IN EFI_DEVICE_IO_PROTOCOL *This,
IN UINTN Pages,
IN EFI_PHYSICAL_ADDRESS HostAddress
)
/*++
Routine Description:
Frees pages that were allocated with AllocateBuffer().
Arguments:
This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
Pages - The number of pages to free.
HostAddress - The base address of the range to free.
Returns:
EFI_SUCCESS - The requested memory pages were freed.
EFI_NOT_FOUND - The requested memory pages were not allocated with
AllocateBuffer().
EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.
--*/
;
#endif

View File

@ -0,0 +1,738 @@
/*++
Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
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:
PcatPciRootBridgeIo.c
Abstract:
EFI PC AT PCI Root Bridge Io Protocol
Revision History
--*/
#include "PcatPciRootBridge.h"
BOOLEAN mPciOptionRomTableInstalled = FALSE;
EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};
EFI_STATUS
EFIAPI
PcatRootBridgeIoIoRead (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
return gCpuIo->Io.Read (
gCpuIo,
(EFI_CPU_IO_PROTOCOL_WIDTH) Width,
UserAddress,
Count,
UserBuffer
);
}
EFI_STATUS
EFIAPI
PcatRootBridgeIoIoWrite (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
return gCpuIo->Io.Write (
gCpuIo,
(EFI_CPU_IO_PROTOCOL_WIDTH) Width,
UserAddress,
Count,
UserBuffer
);
}
EFI_STATUS
PcatRootBridgeIoGetIoPortMapping (
OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
)
/*++
Get the IO Port Mapping. For IA-32 it is always 0.
--*/
{
*IoPortMapping = 0;
*MemoryPortMapping = 0;
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoPciRW (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN BOOLEAN Write,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
PCI_CONFIG_ACCESS_CF8 Pci;
PCI_CONFIG_ACCESS_CF8 PciAligned;
UINT32 InStride;
UINT32 OutStride;
UINTN PciData;
UINTN PciDataStride;
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
UINT64 PciExpressRegAddr;
BOOLEAN UsePciExpressAccess;
if ((UINT32)Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
if ((Width & 0x03) >= EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
InStride = 0;
}
if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
OutStride = 0;
}
UsePciExpressAccess = FALSE;
CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
if (PciAddress.ExtendedRegister > 0xFF) {
//
// Check PciExpressBaseAddress
//
if ((PrivateData->PciExpressBaseAddress == 0) ||
(PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) {
return EFI_UNSUPPORTED;
} else {
UsePciExpressAccess = TRUE;
}
} else {
if (PciAddress.ExtendedRegister != 0) {
Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;
} else {
Pci.Bits.Reg = PciAddress.Register;
}
//
// Note: We can also use PciExpress access here, if wanted.
//
}
if (!UsePciExpressAccess) {
Pci.Bits.Func = PciAddress.Function;
Pci.Bits.Dev = PciAddress.Device;
Pci.Bits.Bus = PciAddress.Bus;
Pci.Bits.Reserved = 0;
Pci.Bits.Enable = 1;
//
// PCI Config access are all 32-bit alligned, but by accessing the
// CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
// are possible on PCI.
//
// To read a byte of PCI config space you load 0xcf8 and
// read 0xcfc, 0xcfd, 0xcfe, 0xcff
//
PciDataStride = Pci.Bits.Reg & 0x03;
while (Count) {
PciAligned = Pci;
PciAligned.Bits.Reg &= 0xfc;
PciData = (UINTN)PrivateData->PciData + PciDataStride;
EfiAcquireLock(&PrivateData->PciLock);
This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
if (Write) {
This->Io.Write (This, Width, PciData, 1, UserBuffer);
} else {
This->Io.Read (This, Width, PciData, 1, UserBuffer);
}
EfiReleaseLock(&PrivateData->PciLock);
UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
PciDataStride = (PciDataStride + InStride) % 4;
Pci.Bits.Reg += InStride;
Count -= 1;
}
} else {
//
// Access PCI-Express space by using memory mapped method.
//
PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
(PciAddress.Bus << 20) |
(PciAddress.Device << 15) |
(PciAddress.Function << 12);
if (PciAddress.ExtendedRegister != 0) {
PciExpressRegAddr += PciAddress.ExtendedRegister;
} else {
PciExpressRegAddr += PciAddress.Register;
}
while (Count) {
if (Write) {
This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
} else {
This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
}
UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
PciExpressRegAddr += InStride;
Count -= 1;
}
}
return EFI_SUCCESS;
}
VOID
ScanPciBus(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
EFI_PCI_BUS_SCAN_CALLBACK Callback,
VOID *Context
)
{
UINT16 Bus;
UINT16 Device;
UINT16 Func;
UINT64 Address;
PCI_TYPE00 PciHeader;
//
// Loop through all busses
//
for (Bus = MinBus; Bus <= MaxBus; Bus++) {
//
// Loop 32 devices per bus
//
for (Device = MinDevice; Device <= MaxDevice; Device++) {
//
// Loop through 8 functions per device
//
for (Func = MinFunc; Func <= MaxFunc; Func++) {
//
// Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
//
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
//
// Read the VendorID from this PCI Device's Confioguration Header
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
//
// If VendorId = 0xffff, there does not exist a device at this
// location. For each device, if there is any function on it,
// there must be 1 function at Function 0. So if Func = 0, there
// will be no more functions in the same device, so we can break
// loop to deal with the next device.
//
if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
break;
}
if (PciHeader.Hdr.VendorId != 0xffff) {
//
// Read the HeaderType to determine if this is a multi-function device
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);
//
// Call the callback function for the device that was found
//
Callback(
IoDev,
MinBus, MaxBus,
MinDevice, MaxDevice,
MinFunc, MaxFunc,
Bus,
Device,
Func,
Context
);
//
// If this is not a multi-function device, we can leave the loop
// to deal with the next device.
//
if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
break;
}
}
}
}
}
}
VOID
CheckForRom (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
EFI_STATUS Status;
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
PCI_TYPE00 PciHeader;
PCI_TYPE01 *PciBridgeHeader;
UINT32 Register;
UINT32 RomBar;
UINT32 RomBarSize;
EFI_PHYSICAL_ADDRESS RomBuffer;
UINT32 MaxRomSize;
EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;
PCI_DATA_STRUCTURE Pcir;
EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;
BOOLEAN LastImage;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
//
// Save the contents of the PCI Configuration Header
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
if (IS_PCI_BRIDGE(&PciHeader)) {
PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);
//
// See if the PCI-PCI Bridge has its secondary interface enabled.
//
if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {
//
// Disable the Prefetchable Memory Window
//
Register = 0x00000000;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
Register = 0xffffffff;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);
//
// Program Memory Window to the PCI Root Bridge Memory Window
//
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);
//
// Enable the Memory decode for the PCI-PCI Bridge
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register |= 0x02;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
//
// Recurse on the Secondary Bus Number
//
ScanPciBus(
IoDev,
PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
CheckForRom, Context
);
}
} else {
//
// Check if an Option ROM Register is present and save the Option ROM Window Register
//
RomBar = 0xffffffff;
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
RomBarSize = (~(RomBar & 0xfffff800)) + 1;
//
// Make sure the size of the ROM is between 0 and 16 MB
//
if (RomBarSize > 0 && RomBarSize <= 0x01000000) {
//
// Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
//
RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
RomBar = RomBar + 1;
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
RomBar = RomBar - 1;
//
// Enable the Memory decode for the PCI Device
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register |= 0x02;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
//
// Follow the chain of images to determine the size of the Option ROM present
// Keep going until the last image is found by looking at the Indicator field
// or the size of an image is 0, or the size of all the images is bigger than the
// size of the window programmed into the PPB.
//
RomBarSize = 0;
do {
LastImage = TRUE;
ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
IoDev->Mem.Read (
IoDev,
EfiPciWidthUint8,
RomBar + RomBarSize,
sizeof(EfiRomHeader),
&EfiRomHeader
);
Pcir.ImageLength = 0;
if (EfiRomHeader.Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE &&
EfiRomHeader.PcirOffset != 0 &&
(EfiRomHeader.PcirOffset & 3) == 0 &&
RomBarSize + EfiRomHeader.PcirOffset + sizeof (PCI_DATA_STRUCTURE) <= MaxRomSize) {
ZeroMem (&Pcir, sizeof(Pcir));
IoDev->Mem.Read (
IoDev,
EfiPciWidthUint8,
RomBar + RomBarSize + EfiRomHeader.PcirOffset,
sizeof(Pcir),
&Pcir
);
if (Pcir.Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
break;
}
if (RomBarSize + Pcir.ImageLength * 512 > MaxRomSize) {
break;
}
if ((Pcir.Indicator & 0x80) == 0x00) {
LastImage = FALSE;
}
RomBarSize += Pcir.ImageLength * 512;
}
} while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);
if (RomBarSize > 0) {
//
// Allocate a memory buffer for the Option ROM contents.
//
Status = gBS->AllocatePages(
AllocateAnyPages,
EfiBootServicesData,
EFI_SIZE_TO_PAGES(RomBarSize),
&RomBuffer
);
if (!EFI_ERROR (Status)) {
//
// Copy the contents of the Option ROM to the memory buffer
//
IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);
Status = gBS->AllocatePool(
EfiBootServicesData,
((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
(VOID*)&TempPciOptionRomDescriptors
);
if (mPciOptionRomTable.PciOptionRomCount > 0) {
CopyMem(
TempPciOptionRomDescriptors,
mPciOptionRomTable.PciOptionRomDescriptors,
(UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
);
gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
}
mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors;
TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);
TempPciOptionRomDescriptors->RomAddress = RomBuffer;
TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;
TempPciOptionRomDescriptors->RomLength = RomBarSize;
TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;
TempPciOptionRomDescriptors->Bus = (UINT8)Bus;
TempPciOptionRomDescriptors->Dev = (UINT8)Device;
TempPciOptionRomDescriptors->Func = (UINT8)Func;
TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;
mPciOptionRomTable.PciOptionRomCount++;
}
}
//
// Disable the Memory decode for the PCI-PCI Bridge
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register &= (~0x02);
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
}
}
}
//
// Restore the PCI Configuration Header
//
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
}
VOID
SaveCommandRegister (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
UINTN Index;
UINT16 Command;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
//
// Clear the memory enable bit
//
Command = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
}
VOID
RestoreCommandRegister (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
UINTN Index;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
}
EFI_STATUS
ScanPciRootBridgeForRoms(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
)
{
EFI_STATUS Status;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
UINT16 MinBus;
UINT16 MaxBus;
UINT64 RootWindowBase;
UINT64 RootWindowLimit;
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;
if (mPciOptionRomTableInstalled == FALSE) {
gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);
mPciOptionRomTableInstalled = TRUE;
}
Status = IoDev->Configuration(IoDev, (VOID **)&Descriptors);
if (EFI_ERROR (Status) || Descriptors == NULL) {
return EFI_NOT_FOUND;
}
MinBus = 0xffff;
MaxBus = 0xffff;
RootWindowBase = 0;
RootWindowLimit = 0;
while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
//
// Find bus range
//
if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
MinBus = (UINT16)Descriptors->AddrRangeMin;
MaxBus = (UINT16)Descriptors->AddrRangeMax;
}
//
// Find memory descriptors that are not prefetchable
//
if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {
//
// Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices
//
if (Descriptors->AddrRangeMax < 0x100000000ULL) {
//
// Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB
//
if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {
RootWindowBase = Descriptors->AddrRangeMin;
RootWindowLimit = Descriptors->AddrRangeMax;
}
}
}
Descriptors ++;
}
//
// Make sure a bus range was found
//
if (MinBus == 0xffff || MaxBus == 0xffff) {
return EFI_NOT_FOUND;
}
//
// Make sure a non-prefetchable memory region was found
//
if (RootWindowBase == 0 && RootWindowLimit == 0) {
return EFI_NOT_FOUND;
}
//
// Round the Base and Limit values to 1 MB boudaries
//
RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;
RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;
//
// Make sure that the size of the rounded window is greater than zero
//
if (RootWindowLimit <= RootWindowBase) {
return EFI_NOT_FOUND;
}
//
// Allocate buffer to save the Command register from all the PCI devices
//
Context.CommandRegisterBuffer = NULL;
Status = gBS->AllocatePool(
EfiBootServicesData,
sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),
(VOID **)&Context.CommandRegisterBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);
//
// Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits
//
ScanPciBus(
IoDev,
MinBus, MaxBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
SaveCommandRegister, &Context
);
//
// Recursively scan all the busses for PCI Option ROMs
//
ScanPciBus(
IoDev,
MinBus, MinBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
CheckForRom, &Context
);
//
// Restore the Command register in all the PCI devices
//
ScanPciBus(
IoDev,
MinBus, MaxBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
RestoreCommandRegister, &Context
);
//
// Free the buffer used to save all the Command register values
//
gBS->FreePool(Context.CommandRegisterBuffer);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,459 @@
/*++
Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
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:
PcatPciRootBridgeIo.c
Abstract:
EFI PC AT PCI Root Bridge Io Protocol
Revision History
--*/
#include "PcatPciRootBridge.h"
#include <IndustryStandard/Pci.h>
#include "SalProc.h"
#include EFI_GUID_DEFINITION (SalSystemTable)
//
// Might be good to put this in an include file, but people may start
// using it! They should always access the EFI abstraction that is
// contained in this file. Just a little information hiding.
//
#define PORT_TO_MEM(_Port) ( ((_Port) & 0xffffffffffff0000) | (((_Port) & 0xfffc) << 10) | ((_Port) & 0x0fff) )
//
// Macro's with casts make this much easier to use and read.
//
#define PORT_TO_MEM8(_Port) (*(UINT8 *)(PORT_TO_MEM(_Port)))
#define PORT_TO_MEM16(_Port) (*(UINT16 *)(PORT_TO_MEM(_Port)))
#define PORT_TO_MEM32(_Port) (*(UINT32 *)(PORT_TO_MEM(_Port)))
#define EFI_PCI_ADDRESS_IA64(_seg, _bus,_dev,_func,_reg) \
( (UINT64) ( (((UINTN)_seg) << 24) + (((UINTN)_bus) << 16) + (((UINTN)_dev) << 11) + (((UINTN)_func) << 8) + ((UINTN)_reg)) )
//
// Local variables for performing SAL Proc calls
//
PLABEL mSalProcPlabel;
CALL_SAL_PROC mGlobalSalProc;
EFI_STATUS
PcatRootBridgeIoIoRead (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
UINTN InStride;
UINTN OutStride;
UINTN AlignMask;
UINTN Address;
PTR Buffer;
UINT16 Data16;
UINT32 Data32;
if ( UserBuffer == NULL ) {
return EFI_INVALID_PARAMETER;
}
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
Address = (UINTN) UserAddress;
Buffer.buf = (UINT8 *)UserBuffer;
if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
return EFI_INVALID_PARAMETER;
}
if ((UINT32)Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
if ((Width & 0x03) == EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
AlignMask = (1 << (Width & 0x03)) - 1;
if ( Address & AlignMask ) {
return EFI_INVALID_PARAMETER;
}
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
InStride = 0;
}
if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
OutStride = 0;
}
Width = Width & 0x03;
Address += PrivateData->PhysicalIoBase;
//
// Loop for each iteration and move the data
//
switch (Width) {
case EfiPciWidthUint8:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
*Buffer.ui8 = PORT_TO_MEM8(Address);
MEMORY_FENCE();
}
break;
case EfiPciWidthUint16:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
if (Buffer.ui & 0x1) {
Data16 = PORT_TO_MEM16(Address);
*Buffer.ui8 = (UINT8)(Data16 & 0xff);
*(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff);
} else {
*Buffer.ui16 = PORT_TO_MEM16(Address);
}
MEMORY_FENCE();
}
break;
case EfiPciWidthUint32:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
if (Buffer.ui & 0x3) {
Data32 = PORT_TO_MEM32(Address);
*Buffer.ui8 = (UINT8)(Data32 & 0xff);
*(Buffer.ui8+1) = (UINT8)((Data32 >> 8) & 0xff);
*(Buffer.ui8+2) = (UINT8)((Data32 >> 16) & 0xff);
*(Buffer.ui8+3) = (UINT8)((Data32 >> 24) & 0xff);
} else {
*Buffer.ui32 = PORT_TO_MEM32(Address);
}
MEMORY_FENCE();
}
break;
}
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoIoWrite (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
UINTN InStride;
UINTN OutStride;
UINTN AlignMask;
UINTN Address;
PTR Buffer;
UINT16 Data16;
UINT32 Data32;
if ( UserBuffer == NULL ) {
return EFI_INVALID_PARAMETER;
}
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
Address = (UINTN) UserAddress;
Buffer.buf = (UINT8 *)UserBuffer;
if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
return EFI_INVALID_PARAMETER;
}
if (Width < 0 || Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
if ((Width & 0x03) == EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
AlignMask = (1 << (Width & 0x03)) - 1;
if ( Address & AlignMask ) {
return EFI_INVALID_PARAMETER;
}
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
InStride = 0;
}
if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
OutStride = 0;
}
Width = Width & 0x03;
Address += PrivateData->PhysicalIoBase;
//
// Loop for each iteration and move the data
//
switch (Width) {
case EfiPciWidthUint8:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
PORT_TO_MEM8(Address) = *Buffer.ui8;
MEMORY_FENCE();
}
break;
case EfiPciWidthUint16:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
if (Buffer.ui & 0x1) {
Data16 = *Buffer.ui8;
Data16 = Data16 | (*(Buffer.ui8+1) << 8);
PORT_TO_MEM16(Address) = Data16;
} else {
PORT_TO_MEM16(Address) = *Buffer.ui16;
}
MEMORY_FENCE();
}
break;
case EfiPciWidthUint32:
for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
MEMORY_FENCE();
if (Buffer.ui & 0x3) {
Data32 = *Buffer.ui8;
Data32 = Data32 | (*(Buffer.ui8+1) << 8);
Data32 = Data32 | (*(Buffer.ui8+2) << 16);
Data32 = Data32 | (*(Buffer.ui8+3) << 24);
PORT_TO_MEM32(Address) = Data32;
} else {
PORT_TO_MEM32(Address) = *Buffer.ui32;
}
MEMORY_FENCE();
}
break;
}
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoGetIoPortMapping (
OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
)
/*++
Get the IO Port Map from the SAL System Table.
--*/
{
SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable;
SAL_ST_MEMORY_DESCRIPTOR_ENTRY *SalMemDesc;
EFI_STATUS Status;
//
// On all Itanium architectures, bit 63 is the I/O bit for performming Memory Mapped I/O operations
//
*MemoryPortMapping = 0x8000000000000000;
Status = EfiLibGetSystemConfigurationTable(&gEfiSalSystemTableGuid, &SalSystemTable);
if (EFI_ERROR(Status)) {
return EFI_NOT_FOUND;
}
//
// BugBug: Add code to test checksum on the Sal System Table
//
if (SalSystemTable->Entry0.Type != 0) {
return EFI_UNSUPPORTED;
}
mSalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry;
mSalProcPlabel.GP = SalSystemTable->Entry0.GlobalDataPointer;
mGlobalSalProc = (CALL_SAL_PROC)&mSalProcPlabel.ProcEntryPoint;
//
// The SalSystemTable pointer includes the Type 0 entry.
// The SalMemDesc is Type 1 so it comes next.
//
SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);
while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {
if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) {
*IoPortMapping = SalMemDesc->PhysicalMemoryAddress;
*IoPortMapping |= 0x8000000000000000;
return EFI_SUCCESS;
}
SalMemDesc++;
}
return EFI_UNSUPPORTED;
}
EFI_STATUS
PcatRootBridgeIoPciRW (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN BOOLEAN Write,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT UINT8 *UserBuffer
)
{
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
UINTN AlignMask;
UINTN InStride;
UINTN OutStride;
UINT64 Address;
DEFIO_PCI_ADDR *Defio;
PTR Buffer;
UINT32 Data32;
UINT16 Data16;
rArg Return;
if (Width < 0 || Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
if ((Width & 0x03) == EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
AlignMask = (1 << (Width & 0x03)) - 1;
if ( UserAddress & AlignMask ) {
return EFI_INVALID_PARAMETER;
}
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
InStride = 0;
}
if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
OutStride = 0;
}
Width = Width & 0x03;
Defio = (DEFIO_PCI_ADDR *)&UserAddress;
if ((Defio->Function > PCI_MAX_FUNC) || (Defio->Device > PCI_MAX_DEVICE)) {
return EFI_UNSUPPORTED;
}
Buffer.buf = (UINT8 *)UserBuffer;
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
Address = EFI_PCI_ADDRESS_IA64(
This->SegmentNumber,
Defio->Bus,
Defio->Device,
Defio->Function,
Defio->Register
);
//
// PCI Config access are all 32-bit alligned, but by accessing the
// CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
// are possible on PCI.
//
// SalProc takes care of reading the proper register depending on stride
//
EfiAcquireLock(&PrivateData->PciLock);
while (Count) {
if(Write) {
if (Buffer.ui & 0x3) {
Data32 = (*(Buffer.ui8+0) << 0);
Data32 |= (*(Buffer.ui8+1) << 8);
Data32 |= (*(Buffer.ui8+2) << 16);
Data32 |= (*(Buffer.ui8+3) << 24);
} else {
Data32 = *Buffer.ui32;
}
Return.p0 = -3;
Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_WRITE,
Address, 1 << Width, Data32, 0, 0, 0, 0);
if(Return.p0) {
EfiReleaseLock(&PrivateData->PciLock);
return EFI_UNSUPPORTED;
}
} else {
Return.p0 = -3;
Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_READ,
Address, 1 << Width, 0, 0, 0, 0, 0);
if(Return.p0) {
EfiReleaseLock(&PrivateData->PciLock);
return EFI_UNSUPPORTED;
}
switch (Width) {
case EfiPciWidthUint8:
*Buffer.ui8 = (UINT8)Return.p1;
break;
case EfiPciWidthUint16:
if (Buffer.ui & 0x1) {
Data16 = (UINT16)Return.p1;
*(Buffer.ui8 + 0) = Data16 & 0xff;
*(Buffer.ui8 + 1) = (Data16 >> 8) & 0xff;
} else {
*Buffer.ui16 = (UINT16)Return.p1;
}
break;
case EfiPciWidthUint32:
if (Buffer.ui & 0x3) {
Data32 = (UINT32)Return.p1;
*(Buffer.ui8 + 0) = (UINT8)(Data32 & 0xff);
*(Buffer.ui8 + 1) = (UINT8)((Data32 >> 8) & 0xff);
*(Buffer.ui8 + 2) = (UINT8)((Data32 >> 16) & 0xff);
*(Buffer.ui8 + 3) = (UINT8)((Data32 >> 24) & 0xff);
} else {
*Buffer.ui32 = (UINT32)Return.p1;
}
break;
}
}
Address += InStride;
Buffer.buf += OutStride;
Count -= 1;
}
EfiReleaseLock(&PrivateData->PciLock);
return EFI_SUCCESS;
}
EFI_STATUS
ScanPciRootBridgeForRoms(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
)
{
return EFI_UNSUPPORTED;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,244 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PcatPciRootBridge.h
Abstract:
The driver for the host to pci bridge (root bridge).
--*/
#ifndef _PCAT_PCI_ROOT_BRIDGE_H_
#define _PCAT_PCI_ROOT_BRIDGE_H_
#include <PiDxe.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Protocol/DeviceIo.h>
#include <Protocol/CpuIo2.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DevicePathLib.h>
#include <Library/HobLib.h>
#include <Guid/PciOptionRomTable.h>
#include <Guid/HobList.h>
#include <Guid/PciExpressBaseAddress.h>
#include <IndustryStandard/Acpi.h>
#include <IndustryStandard/Pci.h>
#define PCI_MAX_SEGMENT 0
//
// Driver Instance Data Prototypes
//
#define PCAT_PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32('p', 'c', 'r', 'b')
typedef struct {
UINT32 Signature;
EFI_HANDLE Handle;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
EFI_CPU_IO2_PROTOCOL *CpuIo;
UINT32 RootBridgeNumber;
UINT32 PrimaryBus;
UINT32 SubordinateBus;
UINT64 MemBase; // Offsets host to bus memory addr.
UINT64 MemLimit; // Max allowable memory access
UINT64 IoBase; // Offsets host to bus io addr.
UINT64 IoLimit; // Max allowable io access
UINT64 PciAddress;
UINT64 PciData;
UINT64 PhysicalMemoryBase;
UINT64 PhysicalIoBase;
EFI_LOCK PciLock;
UINT64 Attributes;
UINT64 Mem32Base;
UINT64 Mem32Limit;
UINT64 Pmem32Base;
UINT64 Pmem32Limit;
UINT64 Mem64Base;
UINT64 Mem64Limit;
UINT64 Pmem64Base;
UINT64 Pmem64Limit;
UINT64 PciExpressBaseAddress;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
LIST_ENTRY MapInfo;
} PCAT_PCI_ROOT_BRIDGE_INSTANCE;
//
// Driver Instance Data Macros
//
#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \
CR(a, PCAT_PCI_ROOT_BRIDGE_INSTANCE, Io, PCAT_PCI_ROOT_BRIDGE_SIGNATURE)
//
// Private data types
//
typedef union {
UINT8 volatile *buf;
UINT8 volatile *ui8;
UINT16 volatile *ui16;
UINT32 volatile *ui32;
UINT64 volatile *ui64;
UINTN volatile ui;
} PTR;
typedef struct {
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;
UINTN NumberOfBytes;
UINTN NumberOfPages;
EFI_PHYSICAL_ADDRESS HostAddress;
EFI_PHYSICAL_ADDRESS MappedHostAddress;
} MAP_INFO;
typedef struct {
LIST_ENTRY Link;
MAP_INFO * Map;
} MAP_INFO_INSTANCE;
typedef
VOID
(*EFI_PCI_BUS_SCAN_CALLBACK) (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *Context
);
typedef struct {
UINT16 *CommandRegisterBuffer;
UINT32 PpbMemoryWindow;
} PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT;
typedef struct {
UINT8 Register;
UINT8 Function;
UINT8 Device;
UINT8 Bus;
UINT8 Reserved[4];
} DEFIO_PCI_ADDR;
//
// Driver Protocol Constructor Prototypes
//
EFI_STATUS
ConstructConfiguration(
IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData
);
EFI_STATUS
PcatPciRootBridgeParseBars (
IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
IN UINT16 Command,
IN UINTN Bus,
IN UINTN Device,
IN UINTN Function
);
EFI_STATUS
ScanPciRootBridgeForRoms(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
);
EFI_STATUS
PcatRootBridgeDevicePathConstructor (
IN EFI_DEVICE_PATH_PROTOCOL **Protocol,
IN UINTN RootBridgeNumber,
IN BOOLEAN IsPciExpress
);
EFI_STATUS
PcatRootBridgeIoConstructor (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
IN UINTN SegmentNumber
);
EFI_STATUS
PcatRootBridgeIoGetIoPortMapping (
OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
);
EFI_STATUS
PcatRootBridgeIoPciRW (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN BOOLEAN Write,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
);
UINT64
GetPciExpressBaseAddressForRootBridge (
IN UINTN HostBridgeNumber,
IN UINTN RootBridgeNumber
);
EFI_STATUS
EFIAPI
PcatRootBridgeIoIoRead (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
);
EFI_STATUS
EFIAPI
PcatRootBridgeIoIoWrite (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
);
//
// Driver entry point prototype
//
EFI_STATUS
EFIAPI
InitializePcatPciRootBridge (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
extern EFI_CPU_IO2_PROTOCOL *gCpuIo;
#endif

View File

@ -0,0 +1,93 @@
/*++
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
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:
PcatPciRootBridgeDevicePath.c
Abstract:
EFI PCAT PCI Root Bridge Device Path Protocol
Revision History
--*/
#include "PcatPciRootBridge.h"
//
// Static device path declarations for this driver.
//
typedef struct {
ACPI_HID_DEVICE_PATH AcpiDevicePath;
EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
{
{
ACPI_DEVICE_PATH,
ACPI_DP,
{
(UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
(UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8),
}
},
EISA_PNP_ID(0x0A03),
0
},
{
END_DEVICE_PATH_TYPE,
END_ENTIRE_DEVICE_PATH_SUBTYPE,
{
END_DEVICE_PATH_LENGTH,
0
}
}
};
EFI_STATUS
PcatRootBridgeDevicePathConstructor (
IN EFI_DEVICE_PATH_PROTOCOL **Protocol,
IN UINTN RootBridgeNumber,
IN BOOLEAN IsPciExpress
)
/*++
Routine Description:
Construct the device path protocol
Arguments:
Protocol - protocol to initialize
Returns:
None
--*/
{
ACPI_HID_DEVICE_PATH *AcpiDevicePath;
*Protocol = DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL *)(&mEfiPciRootBridgeDevicePath));
AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)(*Protocol);
AcpiDevicePath->UID = (UINT32)RootBridgeNumber;
if (IsPciExpress) {
AcpiDevicePath->HID = EISA_PNP_ID(0x0A08);
}
return EFI_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
## @file
#
# Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
# 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:
#
# Abstract:
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PcatPciRootBridge
FILE_GUID = 0F7EC77A-1EE1-400f-A99D-7CBD1FEB181E
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = InitializePcatPciRootBridge
[Packages]
MdePkg/MdePkg.dec
DuetPkg/DuetPkg.dec
[LibraryClasses]
UefiDriverEntryPoint
UefiLib
MemoryAllocationLib
UefiBootServicesTableLib
DebugLib
BaseMemoryLib
DevicePathLib
HobLib
[Sources]
PcatPciRootBridge.h
PcatPciRootBridge.c
PcatPciRootBridgeDevicePath.c
PcatPciRootBridgeIo.c
DeviceIo.h
DeviceIo.c
[Sources.ia32]
Ia32/PcatIo.c
[Sources.x64]
X64/PcatIo.c
[Sources.ipf]
Ipf/PcatIo.c
[Protocols]
gEfiPciRootBridgeIoProtocolGuid
gEfiDeviceIoProtocolGuid
gEfiCpuIo2ProtocolGuid
[Guids]
gEfiPciOptionRomTableGuid
gEfiPciExpressBaseAddressGuid
[Depex]
gEfiCpuIo2ProtocolGuid

View File

@ -0,0 +1,738 @@
/*++
Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
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:
PcatPciRootBridgeIo.c
Abstract:
EFI PC AT PCI Root Bridge Io Protocol
Revision History
--*/
#include "PcatPciRootBridge.h"
BOOLEAN mPciOptionRomTableInstalled = FALSE;
EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};
EFI_STATUS
EFIAPI
PcatRootBridgeIoIoRead (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
return gCpuIo->Io.Read (
gCpuIo,
(EFI_CPU_IO_PROTOCOL_WIDTH) Width,
UserAddress,
Count,
UserBuffer
);
}
EFI_STATUS
EFIAPI
PcatRootBridgeIoIoWrite (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
return gCpuIo->Io.Write (
gCpuIo,
(EFI_CPU_IO_PROTOCOL_WIDTH) Width,
UserAddress,
Count,
UserBuffer
);
}
EFI_STATUS
PcatRootBridgeIoGetIoPortMapping (
OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
)
/*++
Get the IO Port Mapping. For IA-32 it is always 0.
--*/
{
*IoPortMapping = 0;
*MemoryPortMapping = 0;
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoPciRW (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN BOOLEAN Write,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
{
PCI_CONFIG_ACCESS_CF8 Pci;
PCI_CONFIG_ACCESS_CF8 PciAligned;
UINT32 InStride;
UINT32 OutStride;
UINTN PciData;
UINTN PciDataStride;
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
UINT64 PciExpressRegAddr;
BOOLEAN UsePciExpressAccess;
if ((UINT32)Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
if ((Width & 0x03) >= EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
InStride = 0;
}
if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
OutStride = 0;
}
UsePciExpressAccess = FALSE;
CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
if (PciAddress.ExtendedRegister > 0xFF) {
//
// Check PciExpressBaseAddress
//
if ((PrivateData->PciExpressBaseAddress == 0) ||
(PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) {
return EFI_UNSUPPORTED;
} else {
UsePciExpressAccess = TRUE;
}
} else {
if (PciAddress.ExtendedRegister != 0) {
Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;
} else {
Pci.Bits.Reg = PciAddress.Register;
}
//
// Note: We can also use PciExpress access here, if wanted.
//
}
if (!UsePciExpressAccess) {
Pci.Bits.Func = PciAddress.Function;
Pci.Bits.Dev = PciAddress.Device;
Pci.Bits.Bus = PciAddress.Bus;
Pci.Bits.Reserved = 0;
Pci.Bits.Enable = 1;
//
// PCI Config access are all 32-bit alligned, but by accessing the
// CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
// are possible on PCI.
//
// To read a byte of PCI config space you load 0xcf8 and
// read 0xcfc, 0xcfd, 0xcfe, 0xcff
//
PciDataStride = Pci.Bits.Reg & 0x03;
while (Count) {
PciAligned = Pci;
PciAligned.Bits.Reg &= 0xfc;
PciData = (UINTN)PrivateData->PciData + PciDataStride;
EfiAcquireLock(&PrivateData->PciLock);
This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
if (Write) {
This->Io.Write (This, Width, PciData, 1, UserBuffer);
} else {
This->Io.Read (This, Width, PciData, 1, UserBuffer);
}
EfiReleaseLock(&PrivateData->PciLock);
UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
PciDataStride = (PciDataStride + InStride) % 4;
Pci.Bits.Reg += InStride;
Count -= 1;
}
} else {
//
// Access PCI-Express space by using memory mapped method.
//
PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
(PciAddress.Bus << 20) |
(PciAddress.Device << 15) |
(PciAddress.Function << 12);
if (PciAddress.ExtendedRegister != 0) {
PciExpressRegAddr += PciAddress.ExtendedRegister;
} else {
PciExpressRegAddr += PciAddress.Register;
}
while (Count) {
if (Write) {
This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
} else {
This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
}
UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
PciExpressRegAddr += InStride;
Count -= 1;
}
}
return EFI_SUCCESS;
}
VOID
ScanPciBus(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
EFI_PCI_BUS_SCAN_CALLBACK Callback,
VOID *Context
)
{
UINT16 Bus;
UINT16 Device;
UINT16 Func;
UINT64 Address;
PCI_TYPE00 PciHeader;
//
// Loop through all busses
//
for (Bus = MinBus; Bus <= MaxBus; Bus++) {
//
// Loop 32 devices per bus
//
for (Device = MinDevice; Device <= MaxDevice; Device++) {
//
// Loop through 8 functions per device
//
for (Func = MinFunc; Func <= MaxFunc; Func++) {
//
// Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
//
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
//
// Read the VendorID from this PCI Device's Confioguration Header
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
//
// If VendorId = 0xffff, there does not exist a device at this
// location. For each device, if there is any function on it,
// there must be 1 function at Function 0. So if Func = 0, there
// will be no more functions in the same device, so we can break
// loop to deal with the next device.
//
if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
break;
}
if (PciHeader.Hdr.VendorId != 0xffff) {
//
// Read the HeaderType to determine if this is a multi-function device
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);
//
// Call the callback function for the device that was found
//
Callback(
IoDev,
MinBus, MaxBus,
MinDevice, MaxDevice,
MinFunc, MaxFunc,
Bus,
Device,
Func,
Context
);
//
// If this is not a multi-function device, we can leave the loop
// to deal with the next device.
//
if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
break;
}
}
}
}
}
}
VOID
CheckForRom (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
EFI_STATUS Status;
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
PCI_TYPE00 PciHeader;
PCI_TYPE01 *PciBridgeHeader;
UINT32 Register;
UINT32 RomBar;
UINT32 RomBarSize;
EFI_PHYSICAL_ADDRESS RomBuffer;
UINT32 MaxRomSize;
EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;
PCI_DATA_STRUCTURE Pcir;
EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;
BOOLEAN LastImage;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
//
// Save the contents of the PCI Configuration Header
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
if (IS_PCI_BRIDGE(&PciHeader)) {
PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);
//
// See if the PCI-PCI Bridge has its secondary interface enabled.
//
if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {
//
// Disable the Prefetchable Memory Window
//
Register = 0x00000000;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
Register = 0xffffffff;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);
//
// Program Memory Window to the PCI Root Bridge Memory Window
//
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);
//
// Enable the Memory decode for the PCI-PCI Bridge
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register |= 0x02;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
//
// Recurse on the Secondary Bus Number
//
ScanPciBus(
IoDev,
PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
CheckForRom, Context
);
}
} else {
//
// Check if an Option ROM Register is present and save the Option ROM Window Register
//
RomBar = 0xffffffff;
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
RomBarSize = (~(RomBar & 0xfffff800)) + 1;
//
// Make sure the size of the ROM is between 0 and 16 MB
//
if (RomBarSize > 0 && RomBarSize <= 0x01000000) {
//
// Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
//
RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
RomBar = RomBar + 1;
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
RomBar = RomBar - 1;
//
// Enable the Memory decode for the PCI Device
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register |= 0x02;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
//
// Follow the chain of images to determine the size of the Option ROM present
// Keep going until the last image is found by looking at the Indicator field
// or the size of an image is 0, or the size of all the images is bigger than the
// size of the window programmed into the PPB.
//
RomBarSize = 0;
do {
LastImage = TRUE;
ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
IoDev->Mem.Read (
IoDev,
EfiPciWidthUint8,
RomBar + RomBarSize,
sizeof(EfiRomHeader),
&EfiRomHeader
);
Pcir.ImageLength = 0;
if (EfiRomHeader.Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE &&
EfiRomHeader.PcirOffset != 0 &&
(EfiRomHeader.PcirOffset & 3) == 0 &&
RomBarSize + EfiRomHeader.PcirOffset + sizeof (PCI_DATA_STRUCTURE) <= MaxRomSize) {
ZeroMem (&Pcir, sizeof(Pcir));
IoDev->Mem.Read (
IoDev,
EfiPciWidthUint8,
RomBar + RomBarSize + EfiRomHeader.PcirOffset,
sizeof(Pcir),
&Pcir
);
if (Pcir.Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
break;
}
if (RomBarSize + Pcir.ImageLength * 512 > MaxRomSize) {
break;
}
if ((Pcir.Indicator & 0x80) == 0x00) {
LastImage = FALSE;
}
RomBarSize += Pcir.ImageLength * 512;
}
} while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);
if (RomBarSize > 0) {
//
// Allocate a memory buffer for the Option ROM contents.
//
Status = gBS->AllocatePages(
AllocateAnyPages,
EfiBootServicesData,
EFI_SIZE_TO_PAGES(RomBarSize),
&RomBuffer
);
if (!EFI_ERROR (Status)) {
//
// Copy the contents of the Option ROM to the memory buffer
//
IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);
Status = gBS->AllocatePool(
EfiBootServicesData,
((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
(VOID **) &TempPciOptionRomDescriptors
);
if (mPciOptionRomTable.PciOptionRomCount > 0) {
CopyMem(
TempPciOptionRomDescriptors,
mPciOptionRomTable.PciOptionRomDescriptors,
(UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
);
gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
}
mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors;
TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);
TempPciOptionRomDescriptors->RomAddress = RomBuffer;
TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;
TempPciOptionRomDescriptors->RomLength = RomBarSize;
TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;
TempPciOptionRomDescriptors->Bus = (UINT8)Bus;
TempPciOptionRomDescriptors->Dev = (UINT8)Device;
TempPciOptionRomDescriptors->Func = (UINT8)Func;
TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;
mPciOptionRomTable.PciOptionRomCount++;
}
}
//
// Disable the Memory decode for the PCI-PCI Bridge
//
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
Register &= (~0x02);
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
}
}
}
//
// Restore the PCI Configuration Header
//
IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
}
VOID
SaveCommandRegister (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
UINTN Index;
UINT16 Command;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
//
// Clear the memory enable bit
//
Command = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
}
VOID
RestoreCommandRegister (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
UINT16 MinBus,
UINT16 MaxBus,
UINT16 MinDevice,
UINT16 MaxDevice,
UINT16 MinFunc,
UINT16 MaxFunc,
UINT16 Bus,
UINT16 Device,
UINT16 Func,
IN VOID *VoidContext
)
{
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
UINT64 Address;
UINTN Index;
Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
}
EFI_STATUS
ScanPciRootBridgeForRoms(
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
)
{
EFI_STATUS Status;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
UINT16 MinBus;
UINT16 MaxBus;
UINT64 RootWindowBase;
UINT64 RootWindowLimit;
PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;
if (mPciOptionRomTableInstalled == FALSE) {
gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);
mPciOptionRomTableInstalled = TRUE;
}
Status = IoDev->Configuration(IoDev, (VOID **) &Descriptors);
if (EFI_ERROR (Status) || Descriptors == NULL) {
return EFI_NOT_FOUND;
}
MinBus = 0xffff;
MaxBus = 0xffff;
RootWindowBase = 0;
RootWindowLimit = 0;
while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
//
// Find bus range
//
if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
MinBus = (UINT16)Descriptors->AddrRangeMin;
MaxBus = (UINT16)Descriptors->AddrRangeMax;
}
//
// Find memory descriptors that are not prefetchable
//
if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {
//
// Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices
//
if (Descriptors->AddrRangeMax < 0x100000000ULL) {
//
// Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB
//
if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {
RootWindowBase = Descriptors->AddrRangeMin;
RootWindowLimit = Descriptors->AddrRangeMax;
}
}
}
Descriptors ++;
}
//
// Make sure a bus range was found
//
if (MinBus == 0xffff || MaxBus == 0xffff) {
return EFI_NOT_FOUND;
}
//
// Make sure a non-prefetchable memory region was found
//
if (RootWindowBase == 0 && RootWindowLimit == 0) {
return EFI_NOT_FOUND;
}
//
// Round the Base and Limit values to 1 MB boudaries
//
RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;
RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;
//
// Make sure that the size of the rounded window is greater than zero
//
if (RootWindowLimit <= RootWindowBase) {
return EFI_NOT_FOUND;
}
//
// Allocate buffer to save the Command register from all the PCI devices
//
Context.CommandRegisterBuffer = NULL;
Status = gBS->AllocatePool(
EfiBootServicesData,
sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),
(VOID **) &Context.CommandRegisterBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);
//
// Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits
//
ScanPciBus(
IoDev,
MinBus, MaxBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
SaveCommandRegister, &Context
);
//
// Recursively scan all the busses for PCI Option ROMs
//
ScanPciBus(
IoDev,
MinBus, MinBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
CheckForRom, &Context
);
//
// Restore the Command register in all the PCI devices
//
ScanPciBus(
IoDev,
MinBus, MaxBus,
0, PCI_MAX_DEVICE,
0, PCI_MAX_FUNC,
RestoreCommandRegister, &Context
);
//
// Free the buffer used to save all the Command register values
//
gBS->FreePool(Context.CommandRegisterBuffer);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,176 @@
/** @file
UEFI Component Name(2) protocol implementation for Sata Controller driver.
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
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.
**/
#include "SataController.h"
//
/// EFI Component Name Protocol
///
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSataControllerComponentName = {
SataControllerComponentNameGetDriverName,
SataControllerComponentNameGetControllerName,
"eng"
};
//
/// EFI Component Name 2 Protocol
///
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSataControllerComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SataControllerComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SataControllerComponentNameGetControllerName,
"en"
};
//
/// Driver Name Strings
///
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSataControllerDriverNameTable[] = {
{
"eng;en",
(CHAR16 *)L"Sata Controller Init Driver"
},
{
NULL,
NULL
}
};
///
/// Controller Name Strings
///
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSataControllerControllerNameTable[] = {
{
"eng;en",
(CHAR16 *)L"Sata Controller"
},
{
NULL,
NULL
}
};
/**
Retrieves a Unicode string that is the user readable name of the UEFI Driver.
@param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
@param Language A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that that the caller
is requesting, and it must match one of the languages specified
in SupportedLanguages. The number of languages supported by a
driver is up to the driver writer.
@param DriverName A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support the
language specified by Language.
**/
EFI_STATUS
EFIAPI
SataControllerComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mSataControllerDriverNameTable,
DriverName,
(BOOLEAN)(This == &gSataControllerComponentName)
);
}
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an UEFI Driver.
@param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
@param ControllerHandle The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
@param ChildHandle OPTIONAL The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
@param Language A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that that the caller is requesting, and it must match one
of the languages specified in SupportedLanguages. The
number of languages supported by a driver is up to the
driver writer.
@param ControllerName A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language
specified by Language from the point of view of the
driver specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in the
language specified by Language for the driver
specified by This was returned in DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support the
language specified by Language.
**/
EFI_STATUS
EFIAPI
SataControllerComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
EFI_STATUS Status;
//
// Make sure this driver is currently managing ControllHandle
//
Status = EfiTestManagedDevice (
ControllerHandle,
gSataControllerDriverBinding.DriverBindingHandle,
&gEfiPciIoProtocolGuid
);
if (EFI_ERROR (Status)) {
return Status;
}
if (ChildHandle != NULL) {
return EFI_UNSUPPORTED;
}
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mSataControllerControllerNameTable,
ControllerName,
(BOOLEAN)(This == &gSataControllerComponentName)
);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,542 @@
/** @file
Header file for Sata Controller driver.
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
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.
**/
#ifndef _SATA_CONTROLLER_H_
#define _SATA_CONTROLLER_H_
#include <Uefi.h>
#include <Protocol/ComponentName.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/PciIo.h>
#include <Protocol/IdeControllerInit.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <IndustryStandard/Pci.h>
//
// Global Variables definitions
//
extern EFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL gSataControllerComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gSataControllerComponentName2;
#define AHCI_BAR_INDEX 0x05
#define R_AHCI_CAP 0x0
#define B_AHCI_CAP_NPS (BIT4 | BIT3 | BIT2 | BIT1 | BIT0) // Number of Ports
#define B_AHCI_CAP_SPM BIT17 // Supports Port Multiplier
///
/// AHCI each channel can have up to 1 device
///
#define AHCI_MAX_DEVICES 0x01
///
/// AHCI each channel can have 15 devices in the presence of a multiplier
///
#define AHCI_MULTI_MAX_DEVICES 0x0F
///
/// IDE supports 2 channel max
///
#define IDE_MAX_CHANNEL 0x02
///
/// IDE supports 2 devices max
///
#define IDE_MAX_DEVICES 0x02
#define SATA_ENUMER_ALL FALSE
//
// Sata Controller driver private data structure
//
#define SATA_CONTROLLER_SIGNATURE SIGNATURE_32('S','A','T','A')
typedef struct _EFI_SATA_CONTROLLER_PRIVATE_DATA {
//
// Standard signature used to identify Sata Controller private data
//
UINT32 Signature;
//
// Protocol instance of IDE_CONTROLLER_INIT produced by this driver
//
EFI_IDE_CONTROLLER_INIT_PROTOCOL IdeInit;
//
// Copy of protocol pointers used by this driver
//
EFI_PCI_IO_PROTOCOL *PciIo;
//
// The number of devices that are supported by this channel
//
UINT8 DeviceCount;
//
// The highest disqulified mode for each attached device,
// From ATA/ATAPI spec, if a mode is not supported,
// the modes higher than it is also not supported
//
EFI_ATA_COLLECTIVE_MODE *DisqualifiedModes;
//
// A copy of EFI_IDENTIFY_DATA data for each attached SATA device and its flag
//
EFI_IDENTIFY_DATA *IdentifyData;
BOOLEAN *IdentifyValid;
} EFI_SATA_CONTROLLER_PRIVATE_DATA;
#define SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_SATA_CONTROLLER_PRIVATE_DATA, IdeInit, SATA_CONTROLLER_SIGNATURE)
//
// Driver binding functions declaration
//
/**
Supported function of Driver Binding protocol for this driver.
Test to see if this driver supports ControllerHandle.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
@param RemainingDevicePath A pointer to the device path. Should be ignored by
device driver.
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_ALREADY_STARTED This driver is already running on this device.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
SataControllerSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
;
/**
This routine is called right after the .Supported() called and
Start this driver on ControllerHandle.
@param This Protocol instance pointer.
@param Controller Handle of device to bind driver to.
@param RemainingDevicePath A pointer to the device path. Should be ignored by
device driver.
@retval EFI_SUCCESS This driver is added to this device.
@retval EFI_ALREADY_STARTED This driver is already running on this device.
@retval other Some error occurs when binding this driver to this device.
**/
EFI_STATUS
EFIAPI
SataControllerStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
;
/**
Stop this driver on ControllerHandle.
@param This Protocol instance pointer.
@param Controller Handle of device to stop driver on.
@param NumberOfChildren Not used.
@param ChildHandleBuffer Not used.
@retval EFI_SUCCESS This driver is removed from this device.
@retval other Some error occurs when removing this driver from this device.
**/
EFI_STATUS
EFIAPI
SataControllerStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
;
//
// IDE controller init functions declaration
//
/**
Returns the information about the specified IDE channel.
This function can be used to obtain information about a particular IDE channel.
The driver entity uses this information during the enumeration process.
If Enabled is set to FALSE, the driver entity will not scan the channel. Note
that it will not prevent an operating system driver from scanning the channel.
For most of today's controllers, MaxDevices will either be 1 or 2. For SATA
controllers, this value will always be 1. SATA configurations can contain SATA
port multipliers. SATA port multipliers behave like SATA bridges and can support
up to 16 devices on the other side. If a SATA port out of the IDE controller
is connected to a port multiplier, MaxDevices will be set to the number of SATA
devices that the port multiplier supports. Because today's port multipliers
support up to fifteen SATA devices, this number can be as large as fifteen. The IDE
bus driver is required to scan for the presence of port multipliers behind an SATA
controller and enumerate up to MaxDevices number of devices behind the port
multiplier.
In this context, the devices behind a port multiplier constitute a channel.
@param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
@param[in] Channel Zero-based channel number.
@param[out] Enabled TRUE if this channel is enabled. Disabled channels
are not scanned to see if any devices are present.
@param[out] MaxDevices The maximum number of IDE devices that the bus driver
can expect on this channel. For the ATA/ATAPI
specification, version 6, this number will either be
one or two. For Serial ATA (SATA) configurations with a
port multiplier, this number can be as large as fifteen.
@retval EFI_SUCCESS Information was returned without any errors.
@retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
**/
EFI_STATUS
EFIAPI
IdeInitGetChannelInfo (
IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
IN UINT8 Channel,
OUT BOOLEAN *Enabled,
OUT UINT8 *MaxDevices
)
;
/**
The notifications from the driver entity that it is about to enter a certain
phase of the IDE channel enumeration process.
This function can be used to notify the IDE controller driver to perform
specific actions, including any chipset-specific initialization, so that the
chipset is ready to enter the next phase. Seven notification points are defined
at this time.
More synchronization points may be added as required in the future.
@param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
@param[in] Phase The phase during enumeration.
@param[in] Channel Zero-based channel number.
@retval EFI_SUCCESS The notification was accepted without any errors.
@retval EFI_UNSUPPORTED Phase is not supported.
@retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
@retval EFI_NOT_READY This phase cannot be entered at this time; for
example, an attempt was made to enter a Phase
without having entered one or more previous
Phase.
**/
EFI_STATUS
EFIAPI
IdeInitNotifyPhase (
IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase,
IN UINT8 Channel
)
;
/**
Submits the device information to the IDE controller driver.
This function is used by the driver entity to pass detailed information about
a particular device to the IDE controller driver. The driver entity obtains
this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData
is the pointer to the response data buffer. The IdentifyData buffer is owned
by the driver entity, and the IDE controller driver must make a local copy
of the entire buffer or parts of the buffer as needed. The original IdentifyData
buffer pointer may not be valid when
- EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or
- EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point.
The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to
compute the optimum mode for the device. These fields are not limited to the
timing information. For example, an implementation of the IDE controller driver
may examine the vendor and type/mode field to match known bad drives.
The driver entity may submit drive information in any order, as long as it
submits information for all the devices belonging to the enumeration group
before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device
in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
should be called with IdentifyData set to NULL. The IDE controller driver may
not have any other mechanism to know whether a device is present or not. Therefore,
setting IdentifyData to NULL does not constitute an error condition.
EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a
given (Channel, Device) pair.
@param[in] This A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
@param[in] Channel Zero-based channel number.
@param[in] Device Zero-based device number on the Channel.
@param[in] IdentifyData The device's response to the ATA IDENTIFY_DEVICE command.
@retval EFI_SUCCESS The information was accepted without any errors.
@retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
@retval EFI_INVALID_PARAMETER Device is invalid.
**/
EFI_STATUS
EFIAPI
IdeInitSubmitData (
IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
IN UINT8 Channel,
IN UINT8 Device,
IN EFI_IDENTIFY_DATA *IdentifyData
)
;
/**
Disqualifies specific modes for an IDE device.
This function allows the driver entity or other drivers (such as platform
drivers) to reject certain timing modes and request the IDE controller driver
to recalculate modes. This function allows the driver entity and the IDE
controller driver to negotiate the timings on a per-device basis. This function
is useful in the case of drives that lie about their capabilities. An example
is when the IDE device fails to accept the timing modes that are calculated
by the IDE controller driver based on the response to the Identify Drive command.
If the driver entity does not want to limit the ATA timing modes and leave that
decision to the IDE controller driver, it can either not call this function for
the given device or call this function and set the Valid flag to FALSE for all
modes that are listed in EFI_ATA_COLLECTIVE_MODE.
The driver entity may disqualify modes for a device in any order and any number
of times.
This function can be called multiple times to invalidate multiple modes of the
same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI
specification for more information on PIO modes.
For Serial ATA (SATA) controllers, this member function can be used to disqualify
a higher transfer rate mode on a given channel. For example, a platform driver
may inform the IDE controller driver to not use second-generation (Gen2) speeds
for a certain SATA drive.
@param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
@param[in] Channel The zero-based channel number.
@param[in] Device The zero-based device number on the Channel.
@param[in] BadModes The modes that the device does not support and that
should be disqualified.
@retval EFI_SUCCESS The modes were accepted without any errors.
@retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
@retval EFI_INVALID_PARAMETER Device is invalid.
@retval EFI_INVALID_PARAMETER IdentifyData is NULL.
**/
EFI_STATUS
EFIAPI
IdeInitDisqualifyMode (
IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
IN UINT8 Channel,
IN UINT8 Device,
IN EFI_ATA_COLLECTIVE_MODE *BadModes
)
;
/**
Returns the information about the optimum modes for the specified IDE device.
This function is used by the driver entity to obtain the optimum ATA modes for
a specific device. The IDE controller driver takes into account the following
while calculating the mode:
- The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
- The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode()
The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
for all the devices that belong to an enumeration group before calling
EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group.
The IDE controller driver will use controller- and possibly platform-specific
algorithms to arrive at SupportedModes. The IDE controller may base its
decision on user preferences and other considerations as well. This function
may be called multiple times because the driver entity may renegotiate the mode
with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode().
The driver entity may collect timing information for various devices in any
order. The driver entity is responsible for making sure that all the dependencies
are satisfied. For example, the SupportedModes information for device A that
was previously returned may become stale after a call to
EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B.
The buffer SupportedModes is allocated by the callee because the caller does
not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE
is defined in a way that allows for future extensibility and can be of variable
length. This memory pool should be deallocated by the caller when it is no
longer necessary.
The IDE controller driver for a Serial ATA (SATA) controller can use this
member function to force a lower speed (first-generation [Gen1] speeds on a
second-generation [Gen2]-capable hardware). The IDE controller driver can
also allow the driver entity to stay with the speed that has been negotiated
by the physical layer.
@param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
@param[in] Channel A zero-based channel number.
@param[in] Device A zero-based device number on the Channel.
@param[out] SupportedModes The optimum modes for the device.
@retval EFI_SUCCESS SupportedModes was returned.
@retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
@retval EFI_INVALID_PARAMETER Device is invalid.
@retval EFI_INVALID_PARAMETER SupportedModes is NULL.
@retval EFI_NOT_READY Modes cannot be calculated due to a lack of
data. This error may happen if
EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData()
were not called for at least one drive in the
same enumeration group.
**/
EFI_STATUS
EFIAPI
IdeInitCalculateMode (
IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
IN UINT8 Channel,
IN UINT8 Device,
OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes
)
;
/**
Commands the IDE controller driver to program the IDE controller hardware
so that the specified device can operate at the specified mode.
This function is used by the driver entity to instruct the IDE controller
driver to program the IDE controller hardware to the specified modes. This
function can be called only once for a particular device. For a Serial ATA
(SATA) Advanced Host Controller Interface (AHCI) controller, no controller-
specific programming may be required.
@param[in] This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
@param[in] Channel Zero-based channel number.
@param[in] Device Zero-based device number on the Channel.
@param[in] Modes The modes to set.
@retval EFI_SUCCESS The command was accepted without any errors.
@retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
@retval EFI_INVALID_PARAMETER Device is invalid.
@retval EFI_NOT_READY Modes cannot be set at this time due to lack of data.
@retval EFI_DEVICE_ERROR Modes cannot be set due to hardware failure.
The driver entity should not use this device.
**/
EFI_STATUS
EFIAPI
IdeInitSetTiming (
IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
IN UINT8 Channel,
IN UINT8 Device,
IN EFI_ATA_COLLECTIVE_MODE *Modes
)
;
//
// Forward reference declaration
//
/**
Retrieves a Unicode string that is the user readable name of the UEFI Driver.
@param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
@param Language A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that that the caller
is requesting, and it must match one of the languages specified
in SupportedLanguages. The number of languages supported by a
driver is up to the driver writer.
@param DriverName A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support the
language specified by Language.
**/
EFI_STATUS
EFIAPI
SataControllerComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
;
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an UEFI Driver.
@param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
@param ControllerHandle The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
@param OPTIONAL ChildHandle The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
@param Language A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that that the caller is requesting, and it must match one
of the languages specified in SupportedLanguages. The
number of languages supported by a driver is up to the
driver writer.
@param ControllerName A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language
specified by Language from the point of view of the
driver specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in the
language specified by Language for the driver
specified by This was returned in DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support the
language specified by Language.
**/
EFI_STATUS
EFIAPI
SataControllerComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
;
#endif

View File

@ -0,0 +1,49 @@
## @file
#
# Component description file for the Sata Controller driver.
#
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
# 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.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SataController
FILE_GUID = 8F4CD826-A5A0-4e93-9522-CFB0AB72926C
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = InitializeSataControllerDriver
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
ComponentName.c
SataController.c
SataController.h
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
UefiDriverEntryPoint
DebugLib
UefiLib
BaseLib
BaseMemoryLib
MemoryAllocationLib
UefiBootServicesTableLib
[Protocols]
gEfiPciIoProtocolGuid
gEfiIdeControllerInitProtocolGuid

View File

@ -110,8 +110,8 @@ INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
#
# PCI Support
#
INF DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
INF DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
INF CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
INF CorebootModulePkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
#
# ISA Support
@ -132,7 +132,7 @@ INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
INF DuetPkg/SataControllerDxe/SataControllerDxe.inf
INF CorebootModulePkg/SataControllerDxe/SataControllerDxe.inf
INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf

View File

@ -317,8 +317,8 @@
#
# PCI Support
#
DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
CorebootModulePkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
#
# SCSI/ATA/IDE/DISK Support
@ -327,7 +327,7 @@
MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
FatPkg/EnhancedFatDxe/Fat.inf
DuetPkg/SataControllerDxe/SataControllerDxe.inf
CorebootModulePkg/SataControllerDxe/SataControllerDxe.inf
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf

View File

@ -319,8 +319,8 @@
#
# PCI Support
#
DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
CorebootModulePkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
#
# SCSI/ATA/IDE/DISK Support
@ -329,7 +329,7 @@
MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
FatPkg/EnhancedFatDxe/Fat.inf
DuetPkg/SataControllerDxe/SataControllerDxe.inf
CorebootModulePkg/SataControllerDxe/SataControllerDxe.inf
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf