diff options
author | qhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524> | 2007-06-28 14:02:17 +0000 |
---|---|---|
committer | qhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524> | 2007-06-28 14:02:17 +0000 |
commit | ead42efc6b7d264d5cb9b5eb81bbddc499e42a56 (patch) | |
tree | 6ba2e5aedca0cd76b16393edde325c02df411a74 | |
parent | 83f6d1a03b9037663fb1587d135020c7333235cb (diff) | |
download | edk2-platforms-ead42efc6b7d264d5cb9b5eb81bbddc499e42a56.tar.xz |
Add PciBus & IdeBus
PciBus cannot build for now for some definition missing.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2852 6f19259b-4bc3-4df7-8a09-765794883524
44 files changed, 32023 insertions, 1 deletions
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.c new file mode 100644 index 0000000000..12673c9c92 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.c @@ -0,0 +1,210 @@ +/** @file
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "idebus.h"
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName = {
+ IDEBusComponentNameGetDriverName,
+ IDEBusComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mIDEBusDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"PCI IDE/ATAPI Bus Driver" },
+ { NULL , NULL }
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mIDEBusControllerNameTable[] = {
+ { "eng", (CHAR16 *) L"PCI IDE/ATAPI Controller" },
+ { NULL , NULL }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the EFI 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
+IDEBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString (
+ Language,
+ gIDEBusComponentName.SupportedLanguages,
+ mIDEBusDriverNameTable,
+ DriverName
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI 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 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
+IDEBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ //
+ // Make sure this driver is currently managing ControllHandle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gIDEBusDriverBinding.DriverBindingHandle,
+ &gEfiIdeControllerInitProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (ChildHandle == NULL) {
+ return LookupUnicodeString (
+ Language,
+ gIDEBusComponentName.SupportedLanguages,
+ mIDEBusControllerNameTable,
+ ControllerName
+ );
+ }
+
+ Status = EfiTestChildHandle (
+ ControllerHandle,
+ ChildHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the child context
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ gIDEBusDriverBinding.DriverBindingHandle,
+ ChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlockIo);
+
+ return LookupUnicodeString (
+ Language,
+ gIDEBusComponentName.SupportedLanguages,
+ IdeBlkIoDevice->ControllerNameTable,
+ ControllerName
+ );
+}
+
+/**
+ Add the component name for the IDE/ATAPI device
+
+ @param IdeBlkIoDevicePtr A pointer to the IDE_BLK_IO_DEV instance.
+
+**/
+VOID
+AddName (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevicePtr
+ )
+{
+ UINTN StringIndex;
+ CHAR16 ModelName[41];
+
+ //
+ // Add Component Name for the IDE/ATAPI device that was discovered.
+ //
+ IdeBlkIoDevicePtr->ControllerNameTable = NULL;
+ for (StringIndex = 0; StringIndex < 41; StringIndex++) {
+ ModelName[StringIndex] = IdeBlkIoDevicePtr->ModelName[StringIndex];
+ }
+
+ AddUnicodeString (
+ "eng",
+ gIDEBusComponentName.SupportedLanguages,
+ &IdeBlkIoDevicePtr->ControllerNameTable,
+ ModelName
+ );
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.h new file mode 100644 index 0000000000..e6bf11f209 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.h @@ -0,0 +1,80 @@ +/** @file
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _IDE_BUS_COMPONENT_NAME_H
+#define _IDE_BUS_COMPONENT_NAME_H
+
+#define ADD_NAME(x) AddName ((x));
+
+extern EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName;
+
+
+//
+// EFI Component Name Functions
+//
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param Language TODO: add argument description
+ @param DriverName TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param ControllerHandle TODO: add argument description
+ @param ChildHandle TODO: add argument description
+ @param Language TODO: add argument description
+ @param ControllerName TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeBlkIoDevicePtr TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+AddName (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevicePtr
+ )
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/DriverConfiguration.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/DriverConfiguration.c new file mode 100644 index 0000000000..47288ac484 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/DriverConfiguration.c @@ -0,0 +1,322 @@ +/** @file
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "idebus.h"
+
+CHAR16 *OptionString[4] = {
+ L"Enable Primary Master (Y/N)? -->",
+ L"Enable Primary Slave (Y/N)? -->",
+ L"Enable Secondary Master (Y/N)? -->",
+ L"Enable Secondary Slave (Y/N)? -->"
+};
+
+//
+// EFI Driver Configuration Protocol
+//
+EFI_DRIVER_CONFIGURATION_PROTOCOL gIDEBusDriverConfiguration = {
+ IDEBusDriverConfigurationSetOptions,
+ IDEBusDriverConfigurationOptionsValid,
+ IDEBusDriverConfigurationForceDefaults,
+ "eng"
+};
+
+/**
+ TODO: Add function description
+
+ @retval EFI_ABORTED TODO: Add description for return value
+ @retval EFI_SUCCESS TODO: Add description for return value
+ @retval EFI_NOT_FOUND TODO: Add description for return value
+
+**/
+STATIC
+EFI_STATUS
+GetResponse (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+
+ while (TRUE) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (Status)) {
+ if (Key.ScanCode == SCAN_ESC) {
+ return EFI_ABORTED;
+ }
+
+ switch (Key.UnicodeChar) {
+
+ //
+ // fall through
+ //
+ case L'y':
+ case L'Y':
+ gST->ConOut->OutputString (gST->ConOut, L"Y\n");
+ return EFI_SUCCESS;
+
+ //
+ // fall through
+ //
+ case L'n':
+ case L'N':
+ gST->ConOut->OutputString (gST->ConOut, L"N\n");
+ return EFI_NOT_FOUND;
+ }
+
+ }
+ }
+}
+
+/**
+ Allows the user to set controller specific options for a controller that a
+ driver is currently managing.
+
+ @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL
+ instance.
+ @param ControllerHandle The handle of the controller to set options on.
+ @param ChildHandle The handle of the child controller to set options on.
+ This is an optional parameter that may be NULL.
+ It will be NULL for device drivers, and for a bus drivers
+ that wish to set options for the bus controller.
+ It will not be NULL for a bus driver that wishes to set
+ options for one of its child controllers.
+ @param Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the user interface
+ that should be presented to the user, 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 ActionRequired A pointer to the action that the calling agent is
+ required to perform when this function returns.
+ See "Related Definitions" for a list of the actions that
+ the calling agent is required to perform prior to
+ accessing ControllerHandle again.
+
+ @retval EFI_SUCCESS The driver specified by This successfully set the
+ configuration options for the controller specified
+ by ControllerHandle..
+ @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 ActionRequired is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ setting configuration options for the controller
+ specified by ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempt to set the
+ configuration options for the controller specified
+ by ControllerHandle and ChildHandle.
+ @retval EFI_OUT_RESOURCES There are not enough resources available to set the
+ configuration options for the controller specified
+ by ControllerHandle and ChildHandle.
+
+**/
+EFI_STATUS
+IDEBusDriverConfigurationSetOptions (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Value;
+ UINT8 NewValue;
+ UINTN DataSize;
+ UINTN Index;
+
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *ActionRequired = EfiDriverConfigurationActionNone;
+
+ DataSize = sizeof (Value);
+ Status = gRT->GetVariable (
+ L"Configuration",
+ &gEfiCallerIdGuid,
+ NULL,
+ &DataSize,
+ &Value
+ );
+
+ gST->ConOut->OutputString (gST->ConOut, L"IDE Bus Driver Configuration\n");
+ gST->ConOut->OutputString (gST->ConOut, L"===============================\n");
+
+ NewValue = 0;
+ for (Index = 0; Index < 4; Index++) {
+ gST->ConOut->OutputString (gST->ConOut, OptionString[Index]);
+
+ Status = GetResponse ();
+ if (Status == EFI_ABORTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ NewValue = (UINT8) (NewValue | (1 << Index));
+ }
+ }
+
+ if (EFI_ERROR (Status) || (NewValue != Value)) {
+ gRT->SetVariable (
+ L"Configuration",
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (NewValue),
+ &NewValue
+ );
+
+ *ActionRequired = EfiDriverConfigurationActionRestartController;
+ } else {
+ *ActionRequired = EfiDriverConfigurationActionNone;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Tests to see if a controller's current configuration options are valid.
+
+ @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL
+ instance.
+ @param ControllerHandle The handle of the controller to test if it's current
+ configuration options are valid.
+ @param ChildHandle The handle of the child controller to test if it's
+ current
+ configuration options are valid. 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 test the configuration options for the bus
+ controller. It will not be NULL for a bus driver that
+ wishes to test configuration options for one of
+ its child controllers.
+
+ @retval EFI_SUCCESS The controller specified by ControllerHandle and
+ ChildHandle that is being managed by the driver
+ specified by This has a valid set of configuration
+ options.
+ @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_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and
+ ChildHandle that is being managed by the driver
+ specified by This has an invalid set of
+ configuration options.
+
+**/
+EFI_STATUS
+IDEBusDriverConfigurationOptionsValid (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Value;
+ UINTN DataSize;
+
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DataSize = sizeof (Value);
+ Status = gRT->GetVariable (
+ L"Configuration",
+ &gEfiCallerIdGuid,
+ NULL,
+ &DataSize,
+ &Value
+ );
+ if (EFI_ERROR (Status) || Value > 0x0f) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Forces a driver to set the default configuration options for a controller.
+
+ @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL
+ instance.
+ @param ControllerHandle The handle of the controller to force default
+ configuration options on.
+ @param ChildHandle The handle of the child controller to force default
+ configuration options on 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
+ force default configuration options for the bus
+ controller. It will not be NULL for a bus driver that
+ wishes to force default configuration options for one
+ of its child controllers.
+ @param DefaultType The type of default configuration options to force on
+ the controller specified by ControllerHandle and
+ ChildHandle. See Table 9-1 for legal values.
+ A DefaultType of 0x00000000 must be supported
+ by this protocol.
+ @param ActionRequired A pointer to the action that the calling agent
+ is required to perform when this function returns.
+
+ @retval EFI_SUCCESS The driver specified by This successfully forced
+ the default configuration options on the
+ controller specified by ControllerHandle and
+ ChildHandle.
+ @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 ActionRequired is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ forcing the default configuration options on
+ the controller specified by ControllerHandle
+ and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the configuration type specified by DefaultType.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempt to force
+ the default configuration options on the controller
+ specified by ControllerHandle and ChildHandle.
+ @retval EFI_OUT_RESOURCES There are not enough resources available to force
+ the default configuration options on the controller
+ specified by ControllerHandle and ChildHandle.
+
+**/
+EFI_STATUS
+IDEBusDriverConfigurationForceDefaults (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN UINT32 DefaultType,
+ OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired
+ )
+{
+ UINT8 Value;
+
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Value = 0x0f;
+ gRT->SetVariable (
+ L"Configuration",
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (Value),
+ &Value
+ );
+ *ActionRequired = EfiDriverConfigurationActionRestartController;
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/DriverDiagnostics.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/DriverDiagnostics.c new file mode 100644 index 0000000000..8aa6d05712 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/DriverDiagnostics.c @@ -0,0 +1,200 @@ +/** @file
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "idebus.h"
+
+#define IDE_BUS_DIAGNOSTIC_ERROR L"PCI IDE/ATAPI Driver Diagnostics Failed"
+
+//
+// EFI Driver Diagnostics Protocol
+//
+EFI_DRIVER_DIAGNOSTICS_PROTOCOL gIDEBusDriverDiagnostics = {
+ IDEBusDriverDiagnosticsRunDiagnostics,
+ "eng"
+};
+
+/**
+ Runs diagnostics on a controller.
+
+ @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOL
+ instance.
+ @param ControllerHandle The handle of the controller to run diagnostics on.
+ @param ChildHandle The handle of the child controller to run diagnostics on
+ 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 run diagnostics on the bus
+ controller. It will not be NULL for a bus driver that
+ wishes to run diagnostics on one of its child
+ controllers.
+ @param DiagnosticType Indicates type of diagnostics to perform on the
+ controller specified by ControllerHandle and ChildHandle.
+ See "Related Definitions" for the list of supported
+ types.
+ @param Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language in which the optional
+ error message should be returned in Buffer, 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 ErrorType A GUID that defines the format of the data returned in
+ Buffer.
+ @param BufferSize The size, in bytes, of the data returned in Buffer.
+ @param Buffer A buffer that contains a Null-terminated Unicode string
+ plus some additional data whose format is defined by
+ ErrorType. Buffer is allocated by this function with
+ AllocatePool(), and it is the caller's responsibility
+ to free it with a call to FreePool().
+
+ @retval EFI_SUCCESS The controller specified by ControllerHandle and
+ ChildHandle passed the diagnostic.
+ @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 ErrorType is NULL.
+ @retval EFI_INVALID_PARAMETER BufferType is NULL.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ running diagnostics for the controller specified
+ by ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ type of diagnostic specified by DiagnosticType.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete
+ the diagnostics.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return
+ the status information in ErrorType, BufferSize,
+ and Buffer.
+ @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and
+ ChildHandle did not pass the diagnostic.
+
+**/
+EFI_STATUS
+IDEBusDriverDiagnosticsRunDiagnostics (
+ IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,
+ IN CHAR8 *Language,
+ OUT EFI_GUID **ErrorType,
+ OUT UINTN *BufferSize,
+ OUT CHAR16 **Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ UINT32 VendorDeviceId;
+ VOID *BlockBuffer;
+
+ *ErrorType = NULL;
+ *BufferSize = 0;
+
+ if (ChildHandle == NULL) {
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiCallerIdGuid,
+ NULL,
+ gIDEBusDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ gIDEBusDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Use services of PCI I/O Protocol to test the PCI IDE/ATAPI Controller
+ // The following test simply reads the Device ID and Vendor ID.
+ // It should never fail. A real test would perform more advanced
+ // diagnostics.
+ //
+
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &VendorDeviceId);
+ if (EFI_ERROR (Status) || VendorDeviceId == 0xffffffff) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo,
+ gIDEBusDriverBinding.DriverBindingHandle,
+ ChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
+
+ //
+ // Use services available from IdeBlkIoDevice to test the IDE/ATAPI device
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ IdeBlkIoDevice->BlkMedia.BlockSize,
+ (VOID **) &BlockBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = IdeBlkIoDevice->BlkIo.ReadBlocks (
+ &IdeBlkIoDevice->BlkIo,
+ IdeBlkIoDevice->BlkMedia.MediaId,
+ 0,
+ IdeBlkIoDevice->BlkMedia.BlockSize,
+ BlockBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ *ErrorType = &gEfiCallerIdGuid;
+ *BufferSize = sizeof (IDE_BUS_DIAGNOSTIC_ERROR);
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ (UINTN) (*BufferSize),
+ (VOID **) Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (*Buffer, IDE_BUS_DIAGNOSTIC_ERROR, *BufferSize);
+
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ gBS->FreePool (BlockBuffer);
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c new file mode 100644 index 0000000000..3c94c87d6f --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c @@ -0,0 +1,2624 @@ +/** @file
+ Copyright (c) 2006 - 2007 Intel Corporation. <BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including
+ update - ATAIdentity() func
+ update - AtaBlockIoReadBlocks() func
+ update - AtaBlockIoWriteBlocks() func
+ add - AtaAtapi6Identify() func
+ add - AtaReadSectorsExt() func
+ add - AtaWriteSectorsExt() func
+ add - AtaPioDataInExt() func
+ add - AtaPioDataOutExt() func
+
+**/
+
+#include "idebus.h"
+
+/**
+ Sends out an ATA Identify Command to the specified device.
+
+ This function is called by DiscoverIdeDevice() during its device
+ identification. It sends out the ATA Identify Command to the
+ specified device. Only ATA device responses to this command. If
+ the command succeeds, it returns the Identify data structure which
+ contains information about the device. This function extracts the
+ information it needs to fill the IDE_BLK_IO_DEV data structure,
+ including device type, media block size, media capacity, and etc.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure,used
+ to record all the information of the IDE device.
+
+ @retval EFI_SUCCESS Identify ATA device successfully.
+
+ @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or
+ device is not ATA device.
+
+ @note
+ parameter IdeDev will be updated in this function.
+
+**/
+EFI_STATUS
+ATAIdentify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ EFI_STATUS Status;
+ EFI_IDENTIFY_DATA *AtaIdentifyPointer;
+ UINT32 Capacity;
+ UINT8 DeviceSelect;
+
+ //
+ // AtaIdentifyPointer is used for accommodating returned IDENTIFY data of
+ // the ATA Identify command
+ //
+ AtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));
+
+ //
+ // use ATA PIO Data In protocol to send ATA Identify command
+ // and receive data from device
+ //
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
+ Status = AtaPioDataIn (
+ IdeDev,
+ (VOID *) AtaIdentifyPointer,
+ sizeof (EFI_IDENTIFY_DATA),
+ IDENTIFY_DRIVE_CMD,
+ DeviceSelect,
+ 0,
+ 0,
+ 0,
+ 0
+ );
+ //
+ // If ATA Identify command succeeds, then according to the received
+ // IDENTIFY data,
+ // identify the device type ( ATA or not ).
+ // If ATA device, fill the information in IdeDev.
+ // If not ATA device, return IDE_DEVICE_ERROR
+ //
+ if (!EFI_ERROR (Status)) {
+
+ IdeDev->pIdData = AtaIdentifyPointer;
+
+ //
+ // Print ATA Module Name
+ //
+ PrintAtaModuleName (IdeDev);
+
+ //
+ // bit 15 of pAtaIdentify->config is used to identify whether device is
+ // ATA device or ATAPI device.
+ // if 0, means ATA device; if 1, means ATAPI device.
+ //
+ if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) {
+ //
+ // Detect if support S.M.A.R.T. If yes, enable it as default
+ //
+ AtaSMARTSupport (IdeDev);
+
+ //
+ // Check whether this device needs 48-bit addressing (ATAPI-6 ata device)
+ //
+ Status = AtaAtapi6Identify (IdeDev);
+ if (!EFI_ERROR (Status)) {
+ //
+ // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify()
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // This is a hard disk <= 120GB capacity, treat it as normal hard disk
+ //
+ IdeDev->Type = IdeHardDisk;
+
+ //
+ // Block Media Information:
+ // Media->LogicalPartition , Media->WriteCaching will be filled
+ // in the DiscoverIdeDevcie() function.
+ //
+ IdeDev->BlkIo.Media->IoAlign = 4;
+ IdeDev->BlkIo.Media->MediaId = 1;
+ IdeDev->BlkIo.Media->RemovableMedia = FALSE;
+ IdeDev->BlkIo.Media->MediaPresent = TRUE;
+ IdeDev->BlkIo.Media->ReadOnly = FALSE;
+ IdeDev->BlkIo.Media->BlockSize = 0x200;
+
+ //
+ // Calculate device capacity
+ //
+ Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) |
+ AtaIdentifyPointer->AtaData.user_addressable_sectors_lo ;
+ IdeDev->BlkIo.Media->LastBlock = Capacity - 1;
+
+ return EFI_SUCCESS;
+
+ }
+ }
+
+ gBS->FreePool (AtaIdentifyPointer);
+ //
+ // Make sure the pIdData will not be freed again.
+ //
+ IdeDev->pIdData = NULL;
+
+ return EFI_DEVICE_ERROR;
+}
+
+
+/**
+ This function is called by ATAIdentify() to identity whether this disk
+ supports ATA/ATAPI6 48bit addressing, ie support >120G capacity
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @retval EFI_SUCCESS The disk specified by IdeDev is a Atapi6 supported one
+ and 48-bit addressing must be used
+
+ @retval EFI_UNSUPPORTED The disk dosn't not support Atapi6 or it supports but
+ the capacity is below 120G, 48bit addressing is not
+ needed
+
+ @note
+ This function must be called after DEVICE_IDENTITY command has been
+ successfully returned
+
+**/
+EFI_STATUS
+AtaAtapi6Identify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ UINT8 Index;
+ EFI_LBA TmpLba;
+ EFI_LBA Capacity;
+ EFI_IDENTIFY_DATA *Atapi6IdentifyStruct;
+
+ if (IdeDev->pIdData == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Atapi6IdentifyStruct = IdeDev->pIdData;
+
+ if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & bit10) == 0) {
+ //
+ // The device dosn't support 48 bit addressing
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // 48 bit address feature set is supported, get maximum capacity
+ //
+ Capacity = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[0];
+ for (Index = 1; Index < 4; Index++) {
+ //
+ // Lower byte goes first: word[100] is the lowest word, word[103] is highest
+ //
+ TmpLba = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[Index];
+ Capacity |= LShiftU64 (TmpLba, 16 * Index);
+ }
+
+ if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {
+ //
+ // Capacity exceeds 120GB. 48-bit addressing is really needed
+ //
+ IdeDev->Type = Ide48bitAddressingHardDisk;
+
+ //
+ // Fill block media information:Media->LogicalPartition ,
+ // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function.
+ //
+ IdeDev->BlkIo.Media->IoAlign = 4;
+ IdeDev->BlkIo.Media->MediaId = 1;
+ IdeDev->BlkIo.Media->RemovableMedia = FALSE;
+ IdeDev->BlkIo.Media->MediaPresent = TRUE;
+ IdeDev->BlkIo.Media->ReadOnly = FALSE;
+ IdeDev->BlkIo.Media->BlockSize = 0x200;
+ IdeDev->BlkIo.Media->LastBlock = Capacity - 1;
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function is called by ATAIdentify() or ATAPIIdentify()
+ to print device's module name.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+**/
+VOID
+PrintAtaModuleName (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ if (IdeDev->pIdData == NULL) {
+ return ;
+ }
+
+ SwapStringChars (IdeDev->ModelName, IdeDev->pIdData->AtaData.ModelName, 40);
+ IdeDev->ModelName[40] = 0x00;
+}
+
+/**
+ This function is used to send out ATA commands conforms to the
+ PIO Data In Protocol.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *Buffer
+ buffer contained data transferred from device to host.
+
+ @param[in] ByteCount
+ data size in byte unit of the buffer.
+
+ @param[in] AtaCommand
+ value of the Command Register
+
+ @param[in] Head
+ value of the Head/Device Register
+
+ @param[in] SectorCount
+ value of the Sector Count Register
+
+ @param[in] SectorNumber
+ value of the Sector Number Register
+
+ @param[in] CylinderLsb
+ value of the low byte of the Cylinder Register
+
+ @param[in] CylinderMsb
+ value of the high byte of the Cylinder Register
+
+ @retval EFI_SUCCESS send out the ATA command and device send required
+ data successfully.
+
+ @retval EFI_DEVICE_ERROR command sent failed.
+
+**/
+EFI_STATUS
+AtaPioDataIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN UINT8 Head,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorNumber,
+ IN UINT8 CylinderLsb,
+ IN UINT8 CylinderMsb
+ )
+{
+ UINTN WordCount;
+ UINTN Increment;
+ UINT16 *Buffer16;
+ EFI_STATUS Status;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // e0:1110,0000-- bit7 and bit5 are reserved bits.
+ // bit6 set means LBA mode
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)
+ );
+
+ //
+ // All ATAPI device's ATA commands can be issued regardless of the
+ // state of the DRDY
+ //
+ if (IdeDev->Type == IdeHardDisk) {
+
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // set all the command parameters
+ // Before write to all the following registers, BSY and DRQ must be 0.
+ //
+ Status = DRQClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (AtaCommand == SET_FEATURES_CMD) {
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);
+ }
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb);
+
+ //
+ // send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ Buffer16 = (UINT16 *) Buffer;
+
+ //
+ // According to PIO data in protocol, host can perform a series of reads to
+ // the data register after each time device set DRQ ready;
+ // The data size of "a series of read" is command specific.
+ // For most ATA command, data size received from device will not exceed
+ // 1 sector, hence the data size for "a series of read" can be the whole data
+ // size of one command request.
+ // For ATA command such as Read Sector command, the data size of one ATA
+ // command request is often larger than 1 sector, according to the
+ // Read Sector command, the data size of "a series of read" is exactly 1
+ // sector.
+ // Here for simplification reason, we specify the data size for
+ // "a series of read" to 1 sector (256 words) if data size of one ATA command
+ // request is larger than 256 words.
+ //
+ Increment = 256;
+
+ //
+ // used to record bytes of currently transfered data
+ //
+ WordCount = 0;
+
+ while (WordCount < ByteCount / 2) {
+ //
+ // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
+ //
+ Status = DRQReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = CheckErrorStatus (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get the byte count for one series of read
+ //
+ if ((WordCount + Increment) > ByteCount / 2) {
+ Increment = ByteCount / 2 - WordCount;
+ }
+
+ IDEReadPortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ Increment,
+ Buffer16
+ );
+
+ WordCount += Increment;
+ Buffer16 += Increment;
+
+ }
+
+ DRQClear (IdeDev, ATATIMEOUT);
+
+ return CheckErrorStatus (IdeDev);
+}
+
+/**
+ This function is used to send out ATA commands conforms to the
+ PIO Data Out Protocol.
+
+ @param *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param *Buffer buffer contained data transferred from host to device.
+ @param ByteCount data size in byte unit of the buffer.
+ @param AtaCommand value of the Command Register
+ @param Head value of the Head/Device Register
+ @param SectorCount value of the Sector Count Register
+ @param SectorNumber value of the Sector Number Register
+ @param CylinderLsb value of the low byte of the Cylinder Register
+ @param CylinderMsb value of the high byte of the Cylinder Register
+
+ @retval EFI_SUCCESS send out the ATA command and device received required
+ data successfully.
+
+ @retval EFI_DEVICE_ERROR command sent failed.
+
+**/
+EFI_STATUS
+AtaPioDataOut (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN UINT8 Head,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorNumber,
+ IN UINT8 CylinderLsb,
+ IN UINT8 CylinderMsb
+ )
+{
+ UINTN WordCount;
+ UINTN Increment;
+ UINT16 *Buffer16;
+ EFI_STATUS Status;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // select device via Head/Device register.
+ // Before write Head/Device register, BSY and DRQ must be 0.
+ //
+ Status = DRQClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // e0:1110,0000-- bit7 and bit5 are reserved bits.
+ // bit6 set means LBA mode
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)
+ );
+
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // set all the command parameters
+ // Before write to all the following registers, BSY and DRQ must be 0.
+ //
+ Status = DRQClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb);
+
+ //
+ // send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ Buffer16 = (UINT16 *) Buffer;
+
+ //
+ // According to PIO data out protocol, host can perform a series of
+ // writes to the data register after each time device set DRQ ready;
+ // The data size of "a series of read" is command specific.
+ // For most ATA command, data size written to device will not exceed 1 sector,
+ // hence the data size for "a series of write" can be the data size of one
+ // command request.
+ // For ATA command such as Write Sector command, the data size of one
+ // ATA command request is often larger than 1 sector, according to the
+ // Write Sector command, the data size of "a series of read" is exactly
+ // 1 sector.
+ // Here for simplification reason, we specify the data size for
+ // "a series of write" to 1 sector (256 words) if data size of one ATA command
+ // request is larger than 256 words.
+ //
+ Increment = 256;
+ WordCount = 0;
+
+ while (WordCount < ByteCount / 2) {
+
+ //
+ // DRQReady2-- read Alternate Status Register to determine the DRQ bit
+ // data transfer can be performed only when DRQ is ready.
+ //
+ Status = DRQReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = CheckErrorStatus (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check the remaining byte count is less than 512 bytes
+ //
+ if ((WordCount + Increment) > ByteCount / 2) {
+ Increment = ByteCount / 2 - WordCount;
+ }
+ //
+ // perform a series of write without check DRQ ready
+ //
+
+ IDEWritePortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ Increment,
+ Buffer16
+ );
+ WordCount += Increment;
+ Buffer16 += Increment;
+
+ }
+
+ DRQClear (IdeDev, ATATIMEOUT);
+
+ return CheckErrorStatus (IdeDev);
+}
+
+/**
+ This function is used to analyze the Status Register and print out
+ some debug information and if there is ERR bit set in the Status
+ Register, the Error Register's value is also be parsed and print out.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @retval EFI_SUCCESS No err information in the Status Register.
+ @retval EFI_DEVICE_ERROR Any err information in the Status Register.
+
+**/
+EFI_STATUS
+CheckErrorStatus (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ UINT8 StatusRegister;
+ UINT8 ErrorRegister;
+
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ DEBUG_CODE_BEGIN ();
+
+ if (StatusRegister & DWF) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Write Fault\n",
+ StatusRegister)
+ );
+ }
+
+ if (StatusRegister & CORR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Corrected Data\n",
+ StatusRegister)
+ );
+ }
+
+ if (StatusRegister & ERR) {
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+
+ if (ErrorRegister & BBK_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & UNC_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & MC_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Media Change\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & ABRT_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Abort\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & TK0NF_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & AMNF_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n",
+ ErrorRegister)
+ );
+ }
+ }
+
+ DEBUG_CODE_END ();
+
+ if ((StatusRegister & (ERR | DWF | CORR)) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_DEVICE_ERROR;
+
+}
+
+/**
+ This function is called by the AtaBlkIoReadBlocks() to perform
+ reading from media in block unit.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer
+ A pointer to the destination buffer for the data.
+
+ @param[in] Lba
+ The starting logical block address to read from
+ on the device media.
+
+ @param[in] NumberOfBlocks
+ The number of transfer data blocks.
+
+ @return return status is fully dependent on the return status
+ of AtaPioDataIn() function.
+
+**/
+EFI_STATUS
+AtaReadSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+{
+ EFI_STATUS Status;
+ UINTN BlocksRemaining;
+ UINT32 Lba32;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+ UINT8 AtaCommand;
+ UINT8 SectorCount8;
+ UINT16 SectorCount;
+ UINTN ByteCount;
+ VOID *Buffer;
+
+ Buffer = DataBuffer;
+
+ //
+ // Using ATA Read Sector(s) command (opcode=0x20) with PIO DATA IN protocol
+ //
+ AtaCommand = READ_SECTORS_CMD;
+
+
+ BlocksRemaining = NumberOfBlocks;
+
+ Lba32 = (UINT32) Lba;
+
+ Status = EFI_SUCCESS;
+
+ while (BlocksRemaining > 0) {
+
+ //
+ // in ATA-3 spec, LBA is in 28 bit width
+ //
+ Lba0 = (UINT8) Lba32;
+ Lba1 = (UINT8) (Lba32 >> 8);
+ Lba2 = (UINT8) (Lba32 >> 16);
+ //
+ // low 4 bit of Lba3 stands for LBA bit24~bit27.
+ //
+ Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);
+
+ if (BlocksRemaining >= 0x100) {
+
+ //
+ // SectorCount8 is sent to Sector Count register, 0x00 means 256
+ // sectors to be read
+ //
+ SectorCount8 = 0x00;
+ //
+ // SectorCount is used to record the number of sectors to be read
+ //
+ SectorCount = 256;
+ } else {
+
+ SectorCount8 = (UINT8) BlocksRemaining;
+ SectorCount = (UINT16) BlocksRemaining;
+ }
+
+ //
+ // ByteCount is the number of bytes that will be read
+ //
+ ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);
+
+ //
+ // call AtaPioDataIn() to send Read Sector Command and receive data read
+ //
+ Status = AtaPioDataIn (
+ IdeDev,
+ Buffer,
+ (UINT32) ByteCount,
+ AtaCommand,
+ Lba3,
+ SectorCount8,
+ Lba0,
+ Lba1,
+ Lba2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ Buffer = ((UINT8 *) Buffer + ByteCount);
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+/**
+ This function is called by the AtaBlkIoWriteBlocks() to perform
+ writing onto media in block unit.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure,used
+ to record all the information of the IDE device.
+
+ @param[in] *BufferData
+ A pointer to the source buffer for the data.
+
+ @param[in] Lba
+ The starting logical block address to write onto
+ the device media.
+
+ @param[in] NumberOfBlocks
+ The number of transfer data blocks.
+
+ @return return status is fully dependent on the return status
+ of AtaPioDataOut() function.
+
+**/
+EFI_STATUS
+AtaWriteSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *BufferData,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+{
+ EFI_STATUS Status;
+ UINTN BlocksRemaining;
+ UINT32 Lba32;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+ UINT8 AtaCommand;
+ UINT8 SectorCount8;
+ UINT16 SectorCount;
+ UINTN ByteCount;
+ VOID *Buffer;
+
+ Buffer = BufferData;
+
+ //
+ // Using Write Sector(s) command (opcode=0x30) with PIO DATA OUT protocol
+ //
+ AtaCommand = WRITE_SECTORS_CMD;
+
+ BlocksRemaining = NumberOfBlocks;
+
+ Lba32 = (UINT32) Lba;
+
+ Status = EFI_SUCCESS;
+
+ while (BlocksRemaining > 0) {
+
+ Lba0 = (UINT8) Lba32;
+ Lba1 = (UINT8) (Lba32 >> 8);
+ Lba2 = (UINT8) (Lba32 >> 16);
+ Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);
+
+ if (BlocksRemaining >= 0x100) {
+
+ //
+ // SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors
+ // to be written
+ //
+ SectorCount8 = 0x00;
+ //
+ // SectorCount is used to record the number of sectors to be written
+ //
+ SectorCount = 256;
+ } else {
+
+ SectorCount8 = (UINT8) BlocksRemaining;
+ SectorCount = (UINT16) BlocksRemaining;
+ }
+
+ ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);
+
+ Status = AtaPioDataOut (
+ IdeDev,
+ Buffer,
+ (UINT32) ByteCount,
+ AtaCommand,
+ Lba3,
+ SectorCount8,
+ Lba0,
+ Lba1,
+ Lba2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ Buffer = ((UINT8 *) Buffer + ByteCount);
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+/**
+ This function is used to implement the Soft Reset on the specified
+ device. But, the ATA Soft Reset mechanism is so strong a reset method
+ that it will force resetting on both devices connected to the
+ same cable.
+
+ It is called by IdeBlkIoReset(), a interface function of Block
+ I/O protocol.
+
+ This function can also be used by the ATAPI device to perform reset when
+ ATAPI Reset command is failed.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @retval EFI_SUCCESS Soft reset completes successfully.
+ @retval EFI_DEVICE_ERROR Any step during the reset process is failed.
+
+ @note
+ The registers initial values after ATA soft reset are different
+ to the ATA device and ATAPI device.
+
+**/
+EFI_STATUS
+AtaSoftReset (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+
+ UINT8 DeviceControl;
+
+ DeviceControl = 0;
+ //
+ // set SRST bit to initiate soft reset
+ //
+ DeviceControl |= SRST;
+
+ //
+ // disable Interrupt
+ //
+ DeviceControl |= bit1;
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ //
+ // SRST should assert for at least 5 us, we use 10 us for
+ // better compatibility
+ //
+ gBS->Stall (10);
+
+ //
+ // Enable interrupt to support UDMA, and clear SRST bit
+ //
+ DeviceControl = 0;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ //
+ // Wait for at least 2 ms to check BSY status, we use 10 ms
+ // for better compatibility
+ //
+ gBS->Stall(10000);
+ //
+ // slave device needs at most 31s to clear BSY
+ //
+ if (WaitForBSYClear (IdeDev, 31000) == EFI_TIMEOUT) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is the ATA implementation for ReadBlocks in the
+ Block I/O Protocol interface.
+
+ @param[in] *IdeBlkIoDevice
+ Indicates the calling context.
+
+ @param[in] MediaId
+ The media id that the read request is for.
+
+ @param[in] LBA
+ The starting logical block address to read from
+ on the device.
+
+ @param[in] BufferSize
+ The size of the Buffer in bytes. This must be a
+ multiple of the intrinsic block size of the device.
+
+ @param[out] *Buffer
+ A pointer to the destination buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the memory that data is read into.
+
+ @retval EFI_SUCCESS Read Blocks successfully.
+ @retval EFI_DEVICE_ERROR Read Blocks failed.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.
+
+ @retval EFI_BAD_BUFFER_SIZE
+ The BufferSize parameter is not a multiple of the
+ intrinsic block size of the device.
+
+ @retval EFI_INVALID_PARAMETER
+ The read request contains LBAs that are not valid,
+ or the data buffer is not valid.
+
+ @note
+ If Read Block error because of device error, this function will call
+ AtaSoftReset() function to reset device.
+
+**/
+EFI_STATUS
+AtaBlkIoReadBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ EFI_STATUS Status;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Get the intrinsic block size
+ //
+ Media = IdeBlkIoDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (!(Media->MediaPresent)) {
+ return EFI_NO_MEDIA;
+ }
+
+ if (LBA > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+ //
+ // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism
+ //
+ if (IdeBlkIoDevice->UdmaMode.Valid) {
+ Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ } else {
+ Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ }
+ } else {
+ //
+ // For ATA-3 compatible device, use ATA-3 read block mechanism
+ //
+ if (IdeBlkIoDevice->UdmaMode.Valid) {
+ Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ } else {
+ Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ AtaSoftReset (IdeBlkIoDevice);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ This function is the ATA implementation for WriteBlocks in the
+ Block I/O Protocol interface.
+
+ @param[in] *IdeBlkIoDevice
+ Indicates the calling context.
+
+ @param[in] MediaId
+ The media id that the write request is for.
+
+ @param[in] LBA
+ The starting logical block address to write onto
+ the device.
+
+ @param[in] BufferSize
+ The size of the Buffer in bytes. This must be a
+ multiple of the intrinsic block size of the device.
+
+ @param[out] *Buffer
+ A pointer to the source buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the memory that data is
+ written from.
+
+ @retval EFI_SUCCESS Write Blocks successfully.
+ @retval EFI_DEVICE_ERROR Write Blocks failed.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.
+
+ @retval EFI_BAD_BUFFER_SIZE
+ The BufferSize parameter is not a multiple of the
+ intrinsic block size of the device.
+
+ @retval EFI_INVALID_PARAMETER
+ The write request contains LBAs that are not valid,
+ or the data buffer is not valid.
+
+ @note
+ If Write Block error because of device error, this function will call
+ AtaSoftReset() function to reset device.
+
+**/
+EFI_STATUS
+AtaBlkIoWriteBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ EFI_STATUS Status;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Get the intrinsic block size
+ //
+ Media = IdeBlkIoDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (LBA > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+ //
+ // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism
+ //
+ if (IdeBlkIoDevice->UdmaMode.Valid) {
+ Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ } else {
+ Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ }
+ } else {
+ //
+ // For ATA-3 compatible device, use ATA-3 write block mechanism
+ //
+ if (IdeBlkIoDevice->UdmaMode.Valid) {
+ Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ } else {
+ Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ AtaSoftReset (IdeBlkIoDevice);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is called by the AtaBlkIoReadBlocks() to perform
+ reading from media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer A pointer to the destination buffer for the data.
+ @param[in] StartLba The starting logical block address to read from
+ on the device media.
+ @param[in] NumberOfBlocks The number of transfer data blocks.
+
+ @return return status is fully dependent on the return status
+ of AtaPioDataInExt() function.
+
+**/
+EFI_STATUS
+AtaReadSectorsExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+{
+ EFI_STATUS Status;
+ UINTN BlocksRemaining;
+ EFI_LBA Lba64;
+ UINT8 AtaCommand;
+ UINT16 SectorCount;
+ UINT32 ByteCount;
+ VOID *Buffer;
+
+ //
+ // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol
+ //
+ AtaCommand = READ_SECTORS_EXT_CMD;
+ Buffer = DataBuffer;
+ BlocksRemaining = NumberOfBlocks;
+ Lba64 = StartLba;
+ Status = EFI_SUCCESS;
+
+ while (BlocksRemaining > 0) {
+
+ if (BlocksRemaining >= 0x10000) {
+ //
+ // SectorCount is used to record the number of sectors to be read
+ // Max 65536 sectors can be transfered at a time.
+ //
+ SectorCount = 0xffff;
+ } else {
+ SectorCount = (UINT16) BlocksRemaining;
+ }
+
+ //
+ // ByteCount is the number of bytes that will be read
+ //
+ ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);
+
+ //
+ // call AtaPioDataInExt() to send Read Sector Command and receive data read
+ //
+ Status = AtaPioDataInExt (
+ IdeDev,
+ Buffer,
+ ByteCount,
+ AtaCommand,
+ Lba64,
+ SectorCount
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba64 += SectorCount;
+ Buffer = ((UINT8 *) Buffer + ByteCount);
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+/**
+ This function is called by the AtaBlkIoWriteBlocks() to perform
+ writing onto media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure,used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer
+ A pointer to the source buffer for the data.
+
+ @param[in] Lba
+ The starting logical block address to write onto
+ the device media.
+
+ @param[in] NumberOfBlocks
+ The number of transfer data blocks.
+
+ @return status is fully dependent on the return status
+ of AtaPioDataOutExt() function.
+
+**/
+EFI_STATUS
+AtaWriteSectorsExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+{
+ EFI_STATUS Status;
+ EFI_LBA Lba64;
+ UINTN BlocksRemaining;
+ UINT8 AtaCommand;
+ UINT16 SectorCount;
+ UINT32 ByteCount;
+ VOID *Buffer;
+
+ //
+ // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol
+ //
+ AtaCommand = WRITE_SECTORS_EXT_CMD;
+ Lba64 = StartLba;
+ Buffer = DataBuffer;
+ BlocksRemaining = NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+
+ while (BlocksRemaining > 0) {
+
+ if (BlocksRemaining >= 0x10000) {
+ //
+ // SectorCount is used to record the number of sectors to be written.
+ // Max 65536 sectors can be transfered at a time.
+ //
+ SectorCount = 0xffff;
+ } else {
+ SectorCount = (UINT16) BlocksRemaining;
+ }
+
+ //
+ // ByteCount is the number of bytes that will be written
+ //
+ ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);
+
+ //
+ // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command
+ //
+ Status = AtaPioDataOutExt (
+ IdeDev,
+ Buffer,
+ ByteCount,
+ AtaCommand,
+ Lba64,
+ SectorCount
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba64 += SectorCount;
+ Buffer = ((UINT8 *) Buffer + ByteCount);
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+/**
+ This function is used to send out ATA commands conforms to the
+ PIO Data In Protocol, supporting ATA/ATAPI-6 standard
+
+ Comparing with ATA-3 data in protocol, we have two differents here:<BR>
+ 1. Do NOT wait for DRQ clear before sending command into IDE device.(the
+ wait will frequently fail... cause writing function return error)
+
+ 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly
+ slow down writing performance by 100 times!)
+
+ @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in,out] *Buffer buffer contained data transferred from device to host.
+ @param[in] ByteCount data size in byte unit of the buffer.
+ @param[in] AtaCommand value of the Command Register
+ @param[in] StartLba the start LBA of this transaction
+ @param[in] SectorCount the count of sectors to be transfered
+
+ @retval EFI_SUCCESS send out the ATA command and device send required
+ data successfully.
+
+ @retval EFI_DEVICE_ERROR command sent failed.
+
+**/
+EFI_STATUS
+AtaPioDataInExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN OUT VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN EFI_LBA StartLba,
+ IN UINT16 SectorCount
+ )
+{
+ UINT8 DevSel;
+ UINT8 SectorCount8;
+ UINT8 LbaLow;
+ UINT8 LbaMid;
+ UINT8 LbaHigh;
+ UINTN WordCount;
+ UINTN Increment;
+ UINT16 *Buffer16;
+ EFI_STATUS Status;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device, set bit6 as 1 to indicate LBA mode is used
+ //
+ DevSel = (UINT8) (IdeDev->Device << 4);
+ DevSel |= 0x40;
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ DevSel
+ );
+
+ //
+ // Wait for DRDY singnal asserting. ATAPI device needn't wait
+ //
+ if ( (IdeDev->Type == IdeHardDisk) ||
+ (IdeDev->Type == Ide48bitAddressingHardDisk)) {
+
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Fill feature register if needed
+ //
+ if (AtaCommand == SET_FEATURES_CMD) {
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);
+ }
+
+ //
+ // Fill the sector count register, which is a two-byte FIFO. Need write twice.
+ //
+ SectorCount8 = (UINT8) (SectorCount >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ SectorCount8 = (UINT8) SectorCount;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ //
+ // Fill the start LBA registers, which are also two-byte FIFO
+ //
+ LbaLow = (UINT8) RShiftU64 (StartLba, 24);
+ LbaMid = (UINT8) RShiftU64 (StartLba, 32);
+ LbaHigh = (UINT8) RShiftU64 (StartLba, 40);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ LbaLow = (UINT8) StartLba;
+ LbaMid = (UINT8) RShiftU64 (StartLba, 8);
+ LbaHigh = (UINT8) RShiftU64 (StartLba, 16);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ //
+ // Send command via Command Register, invoking the processing of this command
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ Buffer16 = (UINT16 *) Buffer;
+
+ //
+ // According to PIO data in protocol, host can perform a series of reads to
+ // the data register after each time device set DRQ ready;
+ //
+
+ //
+ // 256 words
+ //
+ Increment = 256;
+
+ //
+ // used to record bytes of currently transfered data
+ //
+ WordCount = 0;
+
+ while (WordCount < ByteCount / 2) {
+ //
+ // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
+ //
+ Status = DRQReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = CheckErrorStatus (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get the byte count for one series of read
+ //
+ if ((WordCount + Increment) > ByteCount / 2) {
+ Increment = ByteCount / 2 - WordCount;
+ }
+
+ IDEReadPortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ Increment,
+ Buffer16
+ );
+
+ WordCount += Increment;
+ Buffer16 += Increment;
+
+ }
+
+ return CheckErrorStatus (IdeDev);
+}
+
+/**
+ This function is used to send out ATA commands conforms to the
+ PIO Data Out Protocol, supporting ATA/ATAPI-6 standard
+
+ Comparing with ATA-3 data out protocol, we have two differents here:<BR>
+ 1. Do NOT wait for DRQ clear before sending command into IDE device.(the
+ wait will frequently fail... cause writing function return error)
+
+ 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly
+ slow down writing performance by 100 times!)
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *Buffer buffer contained data transferred from host to device.
+ @param[in] ByteCount data size in byte unit of the buffer.
+ @param[in] AtaCommand value of the Command Register
+ @param[in] StartLba the start LBA of this transaction
+ @param[in] SectorCount the count of sectors to be transfered
+
+ @retval EFI_SUCCESS send out the ATA command and device receive required
+ data successfully.
+
+ @retval EFI_DEVICE_ERROR command sent failed.
+
+**/
+EFI_STATUS
+AtaPioDataOutExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN EFI_LBA StartLba,
+ IN UINT16 SectorCount
+ )
+{
+ UINT8 DevSel;
+ UINT8 SectorCount8;
+ UINT8 LbaLow;
+ UINT8 LbaMid;
+ UINT8 LbaHigh;
+ UINTN WordCount;
+ UINTN Increment;
+ UINT16 *Buffer16;
+ EFI_STATUS Status;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device. Set bit6 as 1 to indicate LBA mode is used
+ //
+ DevSel = (UINT8) (IdeDev->Device << 4);
+ DevSel |= 0x40;
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ DevSel
+ );
+
+ //
+ // Wait for DRDY singnal asserting.
+ //
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Fill feature register if needed
+ //
+ if (AtaCommand == SET_FEATURES_CMD) {
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);
+ }
+
+ //
+ // Fill the sector count register, which is a two-byte FIFO. Need write twice.
+ //
+ SectorCount8 = (UINT8) (SectorCount >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ SectorCount8 = (UINT8) SectorCount;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ //
+ // Fill the start LBA registers, which are also two-byte FIFO
+ //
+ LbaLow = (UINT8) RShiftU64 (StartLba, 24);
+ LbaMid = (UINT8) RShiftU64 (StartLba, 32);
+ LbaHigh = (UINT8) RShiftU64 (StartLba, 40);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ LbaLow = (UINT8) StartLba;
+ LbaMid = (UINT8) RShiftU64 (StartLba, 8);
+ LbaHigh = (UINT8) RShiftU64 (StartLba, 16);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ //
+ // Send command via Command Register, invoking the processing of this command
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ Buffer16 = (UINT16 *) Buffer;
+
+ //
+ // According to PIO Data Out protocol, host can perform a series of writes to
+ // the data register after each time device set DRQ ready;
+ //
+ Increment = 256;
+
+ //
+ // used to record bytes of currently transfered data
+ //
+ WordCount = 0;
+
+ while (WordCount < ByteCount / 2) {
+ //
+ // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
+ //
+ Status = DRQReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = CheckErrorStatus (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Write data into device by one series of writing to data register
+ //
+ if ((WordCount + Increment) > ByteCount / 2) {
+ Increment = ByteCount / 2 - WordCount;
+ }
+
+ IDEWritePortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ Increment,
+ Buffer16
+ );
+
+ WordCount += Increment;
+ Buffer16 += Increment;
+
+ }
+ //
+ // while
+ //
+
+ return CheckErrorStatus (IdeDev);
+}
+
+
+/**
+ Enable SMART of the disk if supported
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure,used
+ to record all the information of the IDE device.
+
+**/
+VOID
+AtaSMARTSupport (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN SMARTSupported;
+ UINT8 Device;
+ EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer;
+ UINT8 DeviceSelect;
+ UINT8 LBAMid;
+ UINT8 LBAHigh;
+
+ //
+ // Detect if the device supports S.M.A.R.T.
+ //
+ if ((IdeDev->pIdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) {
+ //
+ // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one)
+ //
+ return ;
+ } else {
+ if ((IdeDev->pIdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {
+ //
+ // S.M.A.R.T is not supported by the device
+ //
+ SMARTSupported = FALSE;
+ } else {
+ SMARTSupported = TRUE;
+ }
+ }
+
+ if (!SMARTSupported) {
+ //
+ // Report nonsupport status code
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)
+ );
+ } else {
+ //
+ // Enable this feature
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)
+ );
+
+ Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
+ Status = AtaNonDataCommandIn (
+ IdeDev,
+ ATA_SMART_CMD,
+ Device,
+ ATA_SMART_ENABLE_OPERATION,
+ 0,
+ 0,
+ ATA_CONSTANT_4F,
+ ATA_CONSTANT_C2
+ );
+ //
+ // Detect if this feature is enabled
+ //
+ TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));
+
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
+ Status = AtaPioDataIn (
+ IdeDev,
+ (VOID *) TmpAtaIdentifyPointer,
+ sizeof (EFI_IDENTIFY_DATA),
+ IDENTIFY_DRIVE_CMD,
+ DeviceSelect,
+ 0,
+ 0,
+ 0,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (TmpAtaIdentifyPointer);
+ return ;
+ }
+
+ //
+ // Check if the feature is enabled
+ //
+ if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) {
+ //
+ // Read status data
+ //
+ AtaNonDataCommandIn (
+ IdeDev,
+ ATA_SMART_CMD,
+ Device,
+ ATA_SMART_RETURN_STATUS,
+ 0,
+ 0,
+ ATA_CONSTANT_4F,
+ ATA_CONSTANT_C2
+ );
+ LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb);
+ LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb);
+
+ if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {
+ //
+ // The threshold exceeded condition is not detected by the device
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)
+ );
+
+ } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {
+ //
+ // The threshold exceeded condition is detected by the device
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)
+ );
+ }
+
+ } else {
+ //
+ // Report disabled status code
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)
+ );
+ }
+
+ gBS->FreePool (TmpAtaIdentifyPointer);
+ }
+
+ return ;
+}
+
+/**
+ Send ATA Ext command into device with NON_DATA protocol
+
+ @param IdeDev Standard IDE device private data structure
+ @param AtaCommand The ATA command to be sent
+ @param Device The value in Device register
+ @param Feature The value in Feature register
+ @param SectorCount The value in SectorCount register
+ @param LbaAddress The LBA address in 48-bit mode
+
+ @retval EFI_SUCCESS Reading succeed
+ @retval EFI_DEVICE_ERROR Error executing commands on this device
+
+**/
+EFI_STATUS
+AtaCommandIssueExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+{
+ EFI_STATUS Status;
+ UINT8 SectorCount8;
+ UINT8 Feature8;
+ UINT8 LbaLow;
+ UINT8 LbaMid;
+ UINT8 LbaHigh;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0)
+ );
+
+ //
+ // ATA commands for ATA device must be issued when DRDY is set
+ //
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Pass parameter into device register block
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ //
+ // Fill the feature register, which is a two-byte FIFO. Need write twice.
+ //
+ Feature8 = (UINT8) (Feature >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
+
+ Feature8 = (UINT8) Feature;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
+
+ //
+ // Fill the sector count register, which is a two-byte FIFO. Need write twice.
+ //
+ SectorCount8 = (UINT8) (SectorCount >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ SectorCount8 = (UINT8) SectorCount;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ //
+ // Fill the start LBA registers, which are also two-byte FIFO
+ //
+ LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ LbaLow = (UINT8) LbaAddress;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+
+ LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+
+ LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+ LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ //
+ // Work around for Segate 160G disk writing
+ //
+ gBS->Stall (1800);
+
+ //
+ // Send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ //
+ // Stall at least 400ns
+ //
+ gBS->Stall (100);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Send ATA Ext command into device with NON_DATA protocol
+
+ @param IdeDev Standard IDE device private data structure
+ @param AtaCommand The ATA command to be sent
+ @param Device The value in Device register
+ @param Feature The value in Feature register
+ @param SectorCount The value in SectorCount register
+ @param LbaAddress The LBA address in 48-bit mode
+
+ @retval EFI_SUCCESS Reading succeed
+ @retval EFI_DEVICE_ERROR Error executing commands on this device
+
+**/
+EFI_STATUS
+AtaCommandIssue (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+{
+ EFI_STATUS Status;
+ UINT8 SectorCount8;
+ UINT8 Feature8;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0)
+ );
+
+ //
+ // ATA commands for ATA device must be issued when DRDY is set
+ //
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Lba0 = (UINT8) LbaAddress;
+ Lba1 = (UINT8) RShiftU64 (LbaAddress, 8);
+ Lba2 = (UINT8) RShiftU64 (LbaAddress, 16);
+ Lba3 = (UINT8) RShiftU64 (LbaAddress, 24);
+ Device = (UINT8) (Device | Lba3);
+
+ //
+ // Pass parameter into device register block
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ //
+ // Fill the feature register, which is a two-byte FIFO. Need write twice.
+ //
+ Feature8 = (UINT8) Feature;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
+
+ //
+ // Fill the sector count register, which is a two-byte FIFO. Need write twice.
+ //
+ SectorCount8 = (UINT8) SectorCount;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ //
+ // Fill the start LBA registers, which are also two-byte FIFO
+ //
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2);
+
+ //
+ // Send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ //
+ // Stall at least 400ns
+ //
+ gBS->Stall (100);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is called by the AtaBlkIoReadBlocks() to perform
+ reading from media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer A pointer to the destination buffer for the data.
+
+ @param[in] StartLba The starting logical block address to read from
+ on the device media.
+
+ @param[in] NumberOfBlocks The number of transfer data blocks.
+
+ @return The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+ TODO: EFI_UNSUPPORTED - add return value to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+**/
+EFI_STATUS
+AtaUdmaReadExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+{
+ return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadExtOp);
+}
+
+/**
+ This function is called by the AtaBlkIoReadBlocks() to perform
+ reading from media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer A pointer to the destination buffer for the data.
+ @param[in] StartLba The starting logical block address to read from
+ on the device media.
+ @param[in] NumberOfBlocks The number of transfer data blocks.
+
+ @return The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+ TODO: EFI_UNSUPPORTED - add return value to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+**/
+EFI_STATUS
+AtaUdmaRead (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+{
+ return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadOp);
+}
+
+/**
+ This function is called by the AtaBlkIoWriteBlocks() to perform
+ writing to media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer A pointer to the source buffer for the data.
+
+ @param[in] StartLba The starting logical block address to write to
+ on the device media.
+
+ @param[in] NumberOfBlocks The number of transfer data blocks.
+
+ @return The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+ TODO: EFI_UNSUPPORTED - add return value to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+**/
+EFI_STATUS
+AtaUdmaWriteExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+{
+ return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp);
+}
+
+/**
+ This function is called by the AtaBlkIoWriteBlocks() to perform
+ writing to media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer
+ A pointer to the source buffer for the data.
+
+ @param[in] StartLba
+ The starting logical block address to write to
+ on the device media.
+
+ @param[in] NumberOfBlocks
+ The number of transfer data blocks.
+
+ @return The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+ TODO: EFI_UNSUPPORTED - add return value to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+**/
+EFI_STATUS
+AtaUdmaWrite (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+{
+ return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteOp);
+}
+
+/**
+ Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer
+ A pointer to the source buffer for the data.
+
+ @param[in] StartLba
+ The starting logical block address to write to
+ on the device media.
+
+ @param[in] NumberOfBlocks
+ The number of transfer data blocks.
+
+ @param[in] UdmaOp
+ The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp,
+ AtaUdmaWriteOp, AtaUdmaWriteExOp
+
+ @return The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+**/
+EFI_STATUS
+DoAtaUdma (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks,
+ IN ATA_UDMA_OPERATION UdmaOp
+ )
+{
+ IDE_DMA_PRD *PrdAddr;
+ IDE_DMA_PRD *UsedPrdAddr;
+ IDE_DMA_PRD *TempPrdAddr;
+ UINT8 RegisterValue;
+ UINT8 Device;
+ UINT64 IoPortForBmic;
+ UINT64 IoPortForBmis;
+ UINT64 IoPortForBmid;
+ EFI_STATUS Status;
+ UINTN PrdTableNum;
+ UINTN ByteCount;
+ UINTN ByteAvailable;
+ UINT8 *PrdBuffer;
+ UINTN RemainBlockNum;
+ UINT8 DeviceControl;
+ UINT32 Count;
+ UINTN PageCount;
+ VOID *Map;
+ VOID *MemPage;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ UINTN MaxDmaCommandSectors;
+ EFI_PCI_IO_PROTOCOL_OPERATION PciIoProtocolOp;
+ UINT8 AtaCommand;
+
+ switch (UdmaOp) {
+ case AtaUdmaReadOp:
+ MaxDmaCommandSectors = MAX_DMA_COMMAND_SECTORS;
+ PciIoProtocolOp = EfiPciIoOperationBusMasterWrite;
+ AtaCommand = READ_DMA_CMD;
+ break;
+ case AtaUdmaReadExtOp:
+ MaxDmaCommandSectors = MAX_DMA_EXT_COMMAND_SECTORS;
+ PciIoProtocolOp = EfiPciIoOperationBusMasterWrite;
+ AtaCommand = READ_DMA_EXT_CMD;
+ break;
+ case AtaUdmaWriteOp:
+ MaxDmaCommandSectors = MAX_DMA_COMMAND_SECTORS;
+ PciIoProtocolOp = EfiPciIoOperationBusMasterRead;
+ AtaCommand = WRITE_DMA_CMD;
+ break;
+ case AtaUdmaWriteExtOp:
+ MaxDmaCommandSectors = MAX_DMA_EXT_COMMAND_SECTORS;
+ PciIoProtocolOp = EfiPciIoOperationBusMasterRead;
+ AtaCommand = WRITE_DMA_EXT_CMD;
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ break;
+ }
+
+ //
+ // Channel and device differential
+ //
+ Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
+
+ //
+ // Enable interrupt to support UDMA and Select device
+ //
+ DeviceControl = 0;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ if (IdePrimary == IdeDev->Channel) {
+ IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
+ IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;
+ } else {
+ if (IdeSecondary == IdeDev->Channel) {
+ IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
+ IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ RemainBlockNum = NumberOfBlocks;
+ while (RemainBlockNum > 0) {
+
+ if (RemainBlockNum >= MaxDmaCommandSectors) {
+ //
+ // SectorCount is used to record the number of sectors to be read
+ // Max 65536 sectors can be transfered at a time.
+ //
+ NumberOfBlocks = MaxDmaCommandSectors;
+ RemainBlockNum -= MaxDmaCommandSectors;
+ } else {
+ NumberOfBlocks = (UINT16) RemainBlockNum;
+ RemainBlockNum = 0;
+ }
+
+ //
+ // Calculate the number of PRD table to make sure the memory region
+ // not cross 64K boundary
+ //
+ ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
+ PrdTableNum = ((ByteCount >> 16) + 1) + 1;
+
+ //
+ // Build PRD table
+ //
+ PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));
+ Status = IdeDev->PciIo->AllocateBuffer (
+ IdeDev->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ PageCount,
+ &MemPage,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));
+
+ PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);
+ //
+ // To make sure PRD is allocated in one 64K page
+ //
+ if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {
+ UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);
+ } else {
+ if ((UINTN) PrdAddr & 0x03) {
+ UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);
+ } else {
+ UsedPrdAddr = PrdAddr;
+ }
+ }
+
+ //
+ // Build the PRD table
+ //
+ Status = IdeDev->PciIo->Map (
+ IdeDev->PciIo,
+ PciIoProtocolOp,
+ DataBuffer,
+ &ByteCount,
+ &DeviceAddress,
+ &Map
+ );
+ if (EFI_ERROR (Status)) {
+ IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ PrdBuffer = (VOID *) ((UINTN) DeviceAddress);
+ TempPrdAddr = UsedPrdAddr;
+ while (TRUE) {
+
+ ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);
+
+ if (ByteCount <= ByteAvailable) {
+ TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
+ TempPrdAddr->ByteCount = (UINT16) ByteCount;
+ TempPrdAddr->EndOfTable = 0x8000;
+ break;
+ }
+
+ TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
+ TempPrdAddr->ByteCount = (UINT16) ByteAvailable;
+
+ ByteCount -= ByteAvailable;
+ PrdBuffer += ByteAvailable;
+ TempPrdAddr++;
+ }
+
+ //
+ // Set the base address to BMID register
+ //
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint32,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmid,
+ 1,
+ &UsedPrdAddr
+ );
+
+ //
+ // Set BMIC register to identify the operation direction
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) {
+ RegisterValue |= BMIC_nREAD;
+ } else {
+ RegisterValue &= ~((UINT8) BMIC_nREAD);
+ }
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Read BMIS register and clear ERROR and INTR bit
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) {
+ Status = AtaCommandIssueExt (
+ IdeDev,
+ AtaCommand,
+ Device,
+ 0,
+ (UINT16) NumberOfBlocks,
+ StartLba
+ );
+ } else {
+ Status = AtaCommandIssue (
+ IdeDev,
+ AtaCommand,
+ Device,
+ 0,
+ (UINT16) NumberOfBlocks,
+ StartLba
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
+ IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Set START bit of BMIC register
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= BMIC_START;
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Check the INTERRUPT and ERROR bit of BMIS
+ // Max transfer number of sectors for one command is 65536(32Mbyte),
+ // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
+ // So set the variable Count to 2000, for about 2 second timeout time.
+ //
+ Count = 2000;
+ while (TRUE) {
+
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+ if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {
+ if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {
+ //
+ // Clear START bit of BMIC register before return EFI_DEVICE_ERROR
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue &= ~((UINT8)BMIC_START);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+ IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
+ IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+ }
+
+ gBS->Stall (1000);
+ Count --;
+ }
+
+ IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
+ IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
+ //
+ // Read Status Register of IDE device to clear interrupt
+ //
+ RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);
+ //
+ // Clear START bit of BMIC register
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue &= ~((UINT8) BMIC_START);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ if (RegisterValue & BMIS_ERROR) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
+ StartLba += NumberOfBlocks;
+ }
+
+ //
+ // Disable interrupt of Select device
+ //
+ IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);
+ DeviceControl |= IEN_L;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c new file mode 100644 index 0000000000..27f7f999fa --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c @@ -0,0 +1,2140 @@ +/** @file
+ Copyright (c) 2006 - 2007, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "idebus.h"
+
+/**
+ This function is used to get the current status of the media residing
+ in the LS-120 drive or ZIP drive. The media status is returned in the
+ Error Status.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @retval EFI_SUCCESS
+ The media status is achieved successfully and the media
+ can be read/written.
+
+ @retval EFI_DEVICE_ERROR
+ Get Media Status Command is failed.
+
+ @retval EFI_NO_MEDIA
+ There is no media in the drive.
+
+ @retval EFI_WRITE_PROTECTED
+ The media is writing protected.
+
+ @note
+ This function must be called after the LS120EnableMediaStatus()
+ with second parameter set to TRUE
+ (means enable media status notification) is called.
+
+**/
+STATIC
+EFI_STATUS
+LS120GetMediaStatus (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ UINT8 DeviceSelect;
+ UINT8 StatusValue;
+ EFI_STATUS EfiStatus;
+ //
+ // Poll Alternate Register for BSY clear within timeout.
+ //
+ EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (EfiStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device via Device/Head Register.
+ //
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect);
+
+ //
+ // Poll Alternate Register for DRDY set within timeout.
+ // After device is selected, DRDY set indicates the device is ready to
+ // accept command.
+ //
+ EfiStatus = DRDYReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (EfiStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get Media Status Command is sent
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xDA);
+
+ //
+ // BSY bit will clear after command is complete.
+ //
+ EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (EfiStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // the media status is returned by the command in the ERROR register
+ //
+ StatusValue = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+
+ if (StatusValue & bit1) {
+ return EFI_NO_MEDIA;
+ }
+
+ if (StatusValue & bit6) {
+ return EFI_WRITE_PROTECTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ This function is used to send Enable Media Status Notification Command
+ or Disable Media Status Notification Command.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] Enable
+ a flag that indicates whether enable or disable media
+ status notification.
+
+ @retval EFI_SUCCESS
+ If command completes successfully.
+
+ @retval EFI_DEVICE_ERROR
+ If command failed.
+
+**/
+STATIC
+EFI_STATUS
+LS120EnableMediaStatus (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN BOOLEAN Enable
+ )
+{
+ UINT8 DeviceSelect;
+ EFI_STATUS Status;
+
+ //
+ // Poll Alternate Register for BSY clear within timeout.
+ //
+ Status = WaitForBSYClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device via Device/Head Register.
+ //
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect);
+
+ //
+ // Poll Alternate Register for DRDY set within timeout.
+ // After device is selected, DRDY set indicates the device is ready to
+ // accept command.
+ //
+ Status = DRDYReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Enable) {
+ //
+ // 0x95: Enable media status notification
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x95);
+ } else {
+ //
+ // 0x31: Disable media status notification
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x31);
+ }
+ //
+ // Set Feature Command is sent
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xEF);
+
+ //
+ // BSY bit will clear after command is complete.
+ //
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is called by DiscoverIdeDevice() during its device
+ identification.
+
+ Its main purpose is to get enough information for the device media
+ to fill in the Media data structure of the Block I/O Protocol interface.
+
+ There are 5 steps to reach such objective:
+
+ 1. Sends out the ATAPI Identify Command to the specified device.
+ Only ATAPI device responses to this command. If the command succeeds,
+ it returns the Identify data structure which filled with information
+ about the device. Since the ATAPI device contains removable media,
+ the only meaningful information is the device module name.
+
+ 2. Sends out ATAPI Inquiry Packet Command to the specified device.
+ This command will return inquiry data of the device, which contains
+ the device type information.
+
+ 3. Allocate sense data space for future use. We don't detect the media
+ presence here to improvement boot performance, especially when CD
+ media is present. The media detection will be performed just before
+ each BLK_IO read/write
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @retval EFI_SUCCESS
+ Identify ATAPI device successfully.
+
+ @retval EFI_DEVICE_ERROR
+ ATAPI Identify Device Command failed or device type
+ is not supported by this IDE driver.
+
+ @note
+ Parameter "IdeDev" will be updated in this function.
+
+ TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+ TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+**/
+EFI_STATUS
+ATAPIIdentify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ EFI_IDENTIFY_DATA *AtapiIdentifyPointer;
+ UINT8 DeviceSelect;
+ EFI_STATUS Status;
+
+ //
+ // device select bit
+ //
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
+
+ AtapiIdentifyPointer = AllocatePool (sizeof (EFI_IDENTIFY_DATA));
+ if (AtapiIdentifyPointer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Send ATAPI Identify Command to get IDENTIFY data.
+ //
+ Status = AtaPioDataIn (
+ IdeDev,
+ (VOID *) AtapiIdentifyPointer,
+ sizeof (EFI_IDENTIFY_DATA),
+ ATAPI_IDENTIFY_DEVICE_CMD,
+ DeviceSelect,
+ 0,
+ 0,
+ 0,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (AtapiIdentifyPointer);
+ return EFI_DEVICE_ERROR;
+ }
+
+ IdeDev->pIdData = AtapiIdentifyPointer;
+ PrintAtaModuleName (IdeDev);
+
+ //
+ // Send ATAPI Inquiry Packet Command to get INQUIRY data.
+ //
+ Status = AtapiInquiry (IdeDev);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (IdeDev->pIdData);
+ //
+ // Make sure the pIdData will not be freed again.
+ //
+ IdeDev->pIdData = NULL;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Get media removable info from INQUIRY data.
+ //
+ IdeDev->BlkIo.Media->RemovableMedia = (UINT8) ((IdeDev->pInquiryData->RMB & 0x80) == 0x80);
+
+ //
+ // Identify device type via INQUIRY data.
+ //
+ switch (IdeDev->pInquiryData->peripheral_type & 0x1f) {
+
+ //
+ // Magnetic Disk
+ //
+ case 0x00:
+
+ //
+ // device is LS120 or ZIP drive.
+ //
+ IdeDev->Type = IdeMagnetic;
+
+ IdeDev->BlkIo.Media->MediaId = 0;
+ //
+ // Give initial value
+ //
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+
+ IdeDev->BlkIo.Media->LastBlock = 0;
+ IdeDev->BlkIo.Media->BlockSize = 0x200;
+ break;
+
+ //
+ // CD-ROM
+ //
+ case 0x05:
+
+ IdeDev->Type = IdeCdRom;
+ IdeDev->BlkIo.Media->MediaId = 0;
+ //
+ // Give initial value
+ //
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+
+ IdeDev->BlkIo.Media->LastBlock = 0;
+ IdeDev->BlkIo.Media->BlockSize = 0x800;
+ IdeDev->BlkIo.Media->ReadOnly = TRUE;
+ break;
+
+ //
+ // Tape
+ //
+ case 0x01:
+
+ //
+ // WORM
+ //
+ case 0x04:
+
+ //
+ // Optical
+ //
+ case 0x07:
+
+ default:
+ IdeDev->Type = IdeUnknown;
+ gBS->FreePool (IdeDev->pIdData);
+ gBS->FreePool (IdeDev->pInquiryData);
+ //
+ // Make sure the pIdData and pInquiryData will not be freed again.
+ //
+ IdeDev->pIdData = NULL;
+ IdeDev->pInquiryData = NULL;
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // original sense data numbers
+ //
+ IdeDev->SenseDataNumber = 20;
+
+ IdeDev->SenseData = AllocatePool (IdeDev->SenseDataNumber * sizeof (REQUEST_SENSE_DATA));
+ if (IdeDev->SenseData == NULL) {
+ gBS->FreePool (IdeDev->pIdData);
+ gBS->FreePool (IdeDev->pInquiryData);
+ //
+ // Make sure the pIdData and pInquiryData will not be freed again.
+ //
+ IdeDev->pIdData = NULL;
+ IdeDev->pInquiryData = NULL;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sends out ATAPI Inquiry Packet Command to the specified device.
+ This command will return INQUIRY data of the device.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @retval EFI_SUCCESS
+ Inquiry command completes successfully.
+
+ @retval EFI_DEVICE_ERROR
+ Inquiry command failed.
+
+ @note
+ Parameter "IdeDev" will be updated in this function.
+
+**/
+EFI_STATUS
+AtapiInquiry (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+ INQUIRY_DATA *InquiryData;
+
+ //
+ // prepare command packet for the ATAPI Inquiry Packet Command.
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Inquiry.opcode = INQUIRY;
+ Packet.Inquiry.page_code = 0;
+ Packet.Inquiry.allocation_length = sizeof (INQUIRY_DATA);
+
+ InquiryData = AllocatePool (sizeof (INQUIRY_DATA));
+ if (InquiryData == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Send command packet and get requested Inquiry data.
+ //
+ Status = AtapiPacketCommandIn (
+ IdeDev,
+ &Packet,
+ (UINT16 *) InquiryData,
+ sizeof (INQUIRY_DATA),
+ ATAPITIMEOUT
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (InquiryData);
+ return EFI_DEVICE_ERROR;
+ }
+
+ IdeDev->pInquiryData = InquiryData;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is used to send out ATAPI commands conforms to the
+ Packet Command with PIO Data In Protocol.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *Packet
+ pointer pointing to ATAPI_PACKET_COMMAND data structure
+ which contains the contents of the command.
+
+ @param[in] *Buffer
+ buffer contained data transferred from device to host.
+
+ @param[in] ByteCount
+ data size in byte unit of the buffer.
+
+ @param[in] TimeOut
+ this parameter is used to specify the timeout
+ value for the PioReadWriteData() function.
+
+ @retval EFI_SUCCESS
+ send out the ATAPI packet command successfully
+ and device sends data successfully.
+
+ @retval EFI_DEVICE_ERROR
+ the device failed to send data.
+
+**/
+EFI_STATUS
+AtapiPacketCommandIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATAPI_PACKET_COMMAND *Packet,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN UINTN TimeOut
+ )
+{
+ UINT16 *CommandIndex;
+ EFI_STATUS Status;
+ UINT32 Count;
+
+ //
+ // Set all the command parameters by fill related registers.
+ // Before write to all the following registers, BSY and DRQ must be 0.
+ //
+ Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select device via Device/Head Register.
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000)
+ );
+
+ //
+ // No OVL; No DMA
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00);
+
+ //
+ // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device
+ // determine how many data should be transferred.
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderLsb,
+ (UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff)
+ );
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderMsb,
+ (UINT8) (MAX_ATAPI_BYTE_COUNT >> 8)
+ );
+
+ //
+ // DEFAULT_CTL:0x0a (0000,1010)
+ // Disable interrupt
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DEFAULT_CTL);
+
+ //
+ // Send Packet command to inform device
+ // that the following data bytes are command packet.
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, PACKET_CMD);
+
+ Status = DRQReady (IdeDev, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Send out command packet
+ //
+ CommandIndex = Packet->Data16;
+ for (Count = 0; Count < 6; Count++, CommandIndex++) {
+
+ IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex);
+ gBS->Stall (10);
+ }
+
+ //
+ // call PioReadWriteData() function to get
+ // requested transfer data form device.
+ //
+ return PioReadWriteData (IdeDev, Buffer, ByteCount, 1, TimeOut);
+}
+
+/**
+ This function is used to send out ATAPI commands conforms to the
+ Packet Command with PIO Data Out Protocol.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *Packet
+ pointer pointing to ATAPI_PACKET_COMMAND data structure
+ which contains the contents of the command.
+
+ @param[in] *Buffer
+ buffer contained data transferred from host to device.
+
+ @param[in] ByteCount
+ data size in byte unit of the buffer.
+
+ @param[in] TimeOut
+ this parameter is used to specify the timeout
+ value for the PioReadWriteData() function.
+
+ @retval EFI_SUCCESS
+ send out the ATAPI packet command successfully
+ and device received data successfully.
+
+ @retval EFI_DEVICE_ERROR
+ the device failed to send data.
+
+**/
+EFI_STATUS
+AtapiPacketCommandOut (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATAPI_PACKET_COMMAND *Packet,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN UINTN TimeOut
+ )
+{
+ UINT16 *CommandIndex;
+ EFI_STATUS Status;
+ UINT32 Count;
+
+ //
+ // set all the command parameters
+ // Before write to all the following registers, BSY and DRQ must be 0.
+ //
+ Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select device via Device/Head Register.
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000)
+ );
+
+ //
+ // No OVL; No DMA
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00);
+
+ //
+ // set the transfersize to MAX_ATAPI_BYTE_COUNT to
+ // let the device determine how many data should be transferred.
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderLsb,
+ (UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff)
+ );
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderMsb,
+ (UINT8) (MAX_ATAPI_BYTE_COUNT >> 8)
+ );
+
+ //
+ // DEFAULT_CTL:0x0a (0000,1010)
+ // Disable interrupt
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DEFAULT_CTL);
+
+ //
+ // Send Packet command to inform device
+ // that the following data bytes are command packet.
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, PACKET_CMD);
+
+ Status = DRQReady2 (IdeDev, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Send out command packet
+ //
+ CommandIndex = Packet->Data16;
+ for (Count = 0; Count < 6; Count++, CommandIndex++) {
+ IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex);
+ gBS->Stall (10);
+ }
+
+ //
+ // call PioReadWriteData() function to send requested transfer data to device.
+ //
+ return PioReadWriteData (IdeDev, Buffer, ByteCount, 0, TimeOut);
+}
+
+/**
+ This function is called by either AtapiPacketCommandIn() or
+ AtapiPacketCommandOut(). It is used to transfer data between
+ host and device. The data direction is specified by the fourth
+ parameter.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *Buffer
+ buffer contained data transferred between host and device.
+
+ @param[in] ByteCount
+ data size in byte unit of the buffer.
+
+ @param[in] Read
+ flag used to determine the data transfer direction.
+ Read equals 1, means data transferred from device to host;
+ Read equals 0, means data transferred from host to device.
+
+ @param[in] TimeOut
+ timeout value for wait DRQ ready before each data
+ stream's transfer.
+
+ @retval EFI_SUCCESS
+ data is transferred successfully.
+
+ @retval EFI_DEVICE_ERROR
+ the device failed to transfer data.
+
+**/
+EFI_STATUS
+PioReadWriteData (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN BOOLEAN Read,
+ IN UINTN TimeOut
+ )
+{
+ //
+ // required transfer data in word unit.
+ //
+ UINT32 RequiredWordCount;
+
+ //
+ // actual transfer data in word unit.
+ //
+ UINT32 ActualWordCount;
+ UINT32 WordCount;
+ EFI_STATUS Status;
+ UINT16 *PtrBuffer;
+
+ //
+ // No data transfer is premitted.
+ //
+ if (ByteCount == 0) {
+ return EFI_SUCCESS;
+ }
+ //
+ // for performance, we assert the ByteCount is an even number
+ // which is actually a resonable assumption
+ ASSERT((ByteCount%2) == 0);
+
+ PtrBuffer = Buffer;
+ RequiredWordCount = ByteCount / 2;
+ //
+ // ActuralWordCount means the word count of data really transferred.
+ //
+ ActualWordCount = 0;
+
+ while (ActualWordCount < RequiredWordCount) {
+
+ //
+ // before each data transfer stream, the host should poll DRQ bit ready,
+ // to see whether indicates device is ready to transfer data.
+ //
+ Status = DRQReady2 (IdeDev, TimeOut);
+ if (EFI_ERROR (Status)) {
+ return CheckErrorStatus (IdeDev);
+ }
+
+ //
+ // read Status Register will clear interrupt
+ //
+ IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ //
+ // get current data transfer size from Cylinder Registers.
+ //
+ WordCount = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8;
+ WordCount = WordCount | IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb);
+ WordCount = WordCount & 0xffff;
+ WordCount /= 2;
+
+ WordCount = EFI_MIN (WordCount, (RequiredWordCount - ActualWordCount));
+
+ if (Read) {
+ IDEReadPortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ WordCount,
+ PtrBuffer
+ );
+ } else {
+ IDEWritePortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ WordCount,
+ PtrBuffer
+ );
+ }
+
+ PtrBuffer += WordCount;
+ ActualWordCount += WordCount;
+ }
+
+ if (Read) {
+ //
+ // In the case where the drive wants to send more data than we need to read,
+ // the DRQ bit will be set and cause delays from DRQClear2().
+ // We need to read data from the drive until it clears DRQ so we can move on.
+ //
+ AtapiReadPendingData (IdeDev);
+ }
+
+ //
+ // After data transfer is completed, normally, DRQ bit should clear.
+ //
+ Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // read status register to check whether error happens.
+ //
+ return CheckErrorStatus (IdeDev);
+}
+
+/**
+ Sends out ATAPI Test Unit Ready Packet Command to the specified device
+ to find out whether device is accessible.
+
+ @param[in] *IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+ @param[in] *SenseCount Sense count for this packet command
+
+ @retval EFI_SUCCESS Device is accessible.
+ @retval EFI_DEVICE_ERROR Device is not accessible.
+
+**/
+EFI_STATUS
+AtapiTestUnitReady (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT UINTN *SenseCount
+ )
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+
+ *SenseCount = 0;
+
+ //
+ // fill command packet
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.TestUnitReady.opcode = TEST_UNIT_READY;
+
+ //
+ // send command packet
+ //
+ Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = AtapiRequestSense (IdeDev, SenseCount);
+ if (EFI_ERROR (Status)) {
+ *SenseCount = 0;
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sends out ATAPI Request Sense Packet Command to the specified device.
+ This command will return all the current Sense data in the device.
+ This function will pack all the Sense data in one single buffer.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[out] **SenseBuffers
+ allocated in this function, and freed by the calling function.
+ This buffer is used to accommodate all the sense data returned
+ by the device.
+
+ @param[out] *BufUnit
+ record the unit size of the sense data block in the SenseBuffers,
+
+ @param[out] *BufNumbers
+ record the number of units in the SenseBuffers.
+
+ @retval EFI_SUCCESS
+ Request Sense command completes successfully.
+
+ @retval EFI_DEVICE_ERROR
+ Request Sense command failed.
+
+**/
+EFI_STATUS
+AtapiRequestSense (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT UINTN *SenseCounts
+ )
+{
+ EFI_STATUS Status;
+ REQUEST_SENSE_DATA *Sense;
+ UINT16 *Ptr;
+ BOOLEAN FetchSenseData;
+ ATAPI_PACKET_COMMAND Packet;
+
+ *SenseCounts = 0;
+
+ ZeroMem (IdeDev->SenseData, sizeof (REQUEST_SENSE_DATA) * (IdeDev->SenseDataNumber));
+ //
+ // fill command packet for Request Sense Packet Command
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.RequestSence.opcode = REQUEST_SENSE;
+ Packet.RequestSence.allocation_length = sizeof (REQUEST_SENSE_DATA);
+
+ //
+ // initialize pointer
+ //
+ Ptr = (UINT16 *) IdeDev->SenseData;
+ //
+ // request sense data from device continuously until no sense data
+ // exists in the device.
+ //
+ for (FetchSenseData = TRUE; FetchSenseData;) {
+
+ Sense = (REQUEST_SENSE_DATA *) Ptr;
+
+ //
+ // send out Request Sense Packet Command and get one Sense data form device
+ //
+ Status = AtapiPacketCommandIn (
+ IdeDev,
+ &Packet,
+ Ptr,
+ sizeof (REQUEST_SENSE_DATA),
+ ATAPITIMEOUT
+ );
+ //
+ // failed to get Sense data
+ //
+ if (EFI_ERROR (Status)) {
+ if (*SenseCounts == 0) {
+ return EFI_DEVICE_ERROR;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+
+ (*SenseCounts)++;
+ //
+ // We limit MAX sense data count to 20 in order to avoid dead loop. Some
+ // incompatible ATAPI devices don't retrive NO_SENSE when there is no media.
+ // In this case, dead loop occurs if we don't have a gatekeeper. 20 is
+ // supposed to be large enough for any ATAPI device.
+ //
+ if ((Sense->sense_key != SK_NO_SENSE) && ((*SenseCounts) < 20)) {
+ //
+ // Ptr is word-based pointer
+ //
+ Ptr += (sizeof (REQUEST_SENSE_DATA) + 1) >> 1;
+
+ } else {
+ //
+ // when no sense key, skip out the loop
+ //
+ FetchSenseData = FALSE;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sends out ATAPI Read Capacity Packet Command to the specified device.
+ This command will return the information regarding the capacity of the
+ media in the device.
+
+ Current device status will impact device's response to the Read Capacity
+ Command. For example, if the device once reset, the Read Capacity
+ Command will fail. The Sense data record the current device status, so
+ if the Read Capacity Command failed, the Sense data must be requested
+ and be analyzed to determine if the Read Capacity Command should retry.
+
+ @param[in] *IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+ @param[in] SenseCount Sense count for this packet command
+
+ @retval EFI_SUCCESS Read Capacity Command finally completes successfully.
+ @retval EFI_DEVICE_ERROR Read Capacity Command failed because of device error.
+
+ @note Parameter "IdeDev" will be updated in this function.
+
+ TODO: EFI_NOT_READY - add return value to function comment
+**/
+EFI_STATUS
+AtapiReadCapacity (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT UINTN *SenseCount
+ )
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ EFI_STATUS SenseStatus;
+ ATAPI_PACKET_COMMAND Packet;
+
+ //
+ // used for capacity data returned from ATAPI device
+ //
+ READ_CAPACITY_DATA Data;
+ READ_FORMAT_CAPACITY_DATA FormatData;
+
+ *SenseCount = 0;
+
+ ZeroMem (&Data, sizeof (Data));
+ ZeroMem (&FormatData, sizeof (FormatData));
+
+ if (IdeDev->Type == IdeCdRom) {
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Inquiry.opcode = READ_CAPACITY;
+ Status = AtapiPacketCommandIn (
+ IdeDev,
+ &Packet,
+ (UINT16 *) &Data,
+ sizeof (READ_CAPACITY_DATA),
+ ATAPITIMEOUT
+ );
+
+ } else {
+ //
+ // Type == IdeMagnetic
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY;
+ Packet.ReadFormatCapacity.allocation_length_lo = 12;
+ Status = AtapiPacketCommandIn (
+ IdeDev,
+ &Packet,
+ (UINT16 *) &FormatData,
+ sizeof (READ_FORMAT_CAPACITY_DATA),
+ ATAPITIMEOUT
+ );
+ }
+
+ if (Status == EFI_TIMEOUT) {
+ *SenseCount = 0;
+ return Status;
+ }
+
+ SenseStatus = AtapiRequestSense (IdeDev, SenseCount);
+
+ if (!EFI_ERROR (SenseStatus)) {
+
+ if (!EFI_ERROR (Status)) {
+
+ if (IdeDev->Type == IdeCdRom) {
+
+ IdeDev->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) |
+ (Data.LastLba2 << 16) |
+ (Data.LastLba1 << 8) |
+ Data.LastLba0;
+
+ if (IdeDev->BlkIo.Media->LastBlock != 0) {
+
+ IdeDev->BlkIo.Media->BlockSize = (Data.BlockSize3 << 24) |
+ (Data.BlockSize2 << 16) |
+ (Data.BlockSize1 << 8) |
+ Data.BlockSize0;
+
+ IdeDev->BlkIo.Media->MediaPresent = TRUE;
+ } else {
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+ return EFI_DEVICE_ERROR;
+ }
+
+ IdeDev->BlkIo.Media->ReadOnly = TRUE;
+
+ //
+ // Because the user data portion in the sector of the Data CD supported
+ // is always 0x800
+ //
+ IdeDev->BlkIo.Media->BlockSize = 0x800;
+ }
+
+ if (IdeDev->Type == IdeMagnetic) {
+
+ if (FormatData.DesCode == 3) {
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+ IdeDev->BlkIo.Media->LastBlock = 0;
+ } else {
+
+ IdeDev->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |
+ (FormatData.LastLba2 << 16) |
+ (FormatData.LastLba1 << 8) |
+ FormatData.LastLba0;
+ if (IdeDev->BlkIo.Media->LastBlock != 0) {
+ IdeDev->BlkIo.Media->LastBlock--;
+
+ IdeDev->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) |
+ (FormatData.BlockSize1 << 8) |
+ FormatData.BlockSize0;
+
+ IdeDev->BlkIo.Media->MediaPresent = TRUE;
+ } else {
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+ //
+ // Return EFI_NOT_READY operation succeeds but returned capacity is 0
+ //
+ return EFI_NOT_READY;
+ }
+
+ IdeDev->BlkIo.Media->BlockSize = 0x200;
+
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+
+ } else {
+ *SenseCount = 0;
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+/**
+ Used before read/write blocks from/to ATAPI device media.
+ Since ATAPI device media is removable, it is necessary to detect
+ whether media is present and get current present media's
+ information, and if media has been changed, Block I/O Protocol
+ need to be reinstalled.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[out] *MediaChange
+ return value that indicates if the media of the device has been
+ changed.
+
+ @retval EFI_SUCCESS
+ media found successfully.
+
+ @retval EFI_DEVICE_ERROR
+ any error encounters during media detection.
+
+ @retval EFI_NO_MEDIA
+ media not found.
+
+ @note
+ parameter IdeDev may be updated in this function.
+
+**/
+EFI_STATUS
+AtapiDetectMedia (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT BOOLEAN *MediaChange
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS CleanStateStatus;
+ EFI_BLOCK_IO_MEDIA OldMediaInfo;
+ UINTN RetryTimes;
+ UINTN RetryNotReady;
+ UINTN SenseCount;
+ SENSE_RESULT SResult;
+ BOOLEAN WriteProtected;
+
+ CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (EFI_BLOCK_IO_MEDIA));
+ *MediaChange = FALSE;
+ //
+ // Retry for SenseDeviceNotReadyNeedRetry.
+ // Each retry takes 1s and we limit the upper boundary to
+ // 120 times about 2 min.
+ //
+ RetryNotReady = 120;
+
+ //
+ // Do Test Unit Ready
+ //
+ DoTUR:
+ //
+ // Retry 5 times
+ //
+ RetryTimes = 5;
+ while (RetryTimes != 0) {
+
+ Status = AtapiTestUnitReady (IdeDev, &SenseCount);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Test Unit Ready error without sense data.
+ // For some devices, this means there's extra data
+ // that has not been read, so we read these extra
+ // data out before going on.
+ //
+ CleanStateStatus = AtapiReadPendingData (IdeDev);
+ if (EFI_ERROR (CleanStateStatus)) {
+ //
+ // Busy wait failed, try again
+ //
+ RetryTimes--;
+ }
+ //
+ // Try again without counting down RetryTimes
+ //
+ continue;
+ } else {
+
+ ParseSenseData (IdeDev, SenseCount, &SResult);
+
+ switch (SResult) {
+ case SenseNoSenseKey:
+ if (IdeDev->BlkIo.Media->MediaPresent) {
+ goto Done;
+ } else {
+ //
+ // Media present but the internal structure need refreshed.
+ // Try Read Capacity
+ //
+ goto DoRC;
+ }
+ break;
+
+ case SenseDeviceNotReadyNeedRetry:
+ if (--RetryNotReady == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ gBS->Stall (1000 * STALL_1_MILLI_SECOND);
+ continue;
+ break;
+
+ case SenseNoMedia:
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+ IdeDev->BlkIo.Media->LastBlock = 0;
+ goto Done;
+ break;
+
+ case SenseDeviceNotReadyNoRetry:
+ case SenseMediaError:
+ return EFI_DEVICE_ERROR;
+
+ case SenseMediaChange:
+ IdeDev->BlkIo.Media->MediaId++;
+ goto DoRC;
+ break;
+
+ default:
+ RetryTimes--;
+ break;
+ }
+ }
+ }
+
+ return EFI_DEVICE_ERROR;
+
+ //
+ // Do Read Capacity
+ //
+ DoRC:
+ RetryTimes = 5;
+
+ while (RetryTimes != 0) {
+
+ Status = AtapiReadCapacity (IdeDev, &SenseCount);
+
+ if (EFI_ERROR (Status)) {
+ RetryTimes--;
+ continue;
+ } else {
+
+ ParseSenseData (IdeDev, SenseCount, &SResult);
+
+ switch (SResult) {
+ case SenseNoSenseKey:
+ goto Done;
+ break;
+
+ case SenseDeviceNotReadyNeedRetry:
+ //
+ // We use Test Unit Ready to retry which
+ // is faster.
+ //
+ goto DoTUR;
+ break;
+
+ case SenseNoMedia:
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+ IdeDev->BlkIo.Media->LastBlock = 0;
+ goto Done;
+ break;
+
+ case SenseDeviceNotReadyNoRetry:
+ case SenseMediaError:
+ return EFI_DEVICE_ERROR;
+
+ case SenseMediaChange:
+ IdeDev->BlkIo.Media->MediaId++;
+ continue;
+ break;
+
+ default:
+ RetryTimes--;
+ break;
+ }
+ }
+ }
+
+ return EFI_DEVICE_ERROR;
+
+ Done:
+ //
+ // the following code is to check the write-protected for LS120 media
+ //
+ if ((IdeDev->BlkIo.Media->MediaPresent) && (IdeDev->Type == IdeMagnetic)) {
+
+ Status = IsLS120orZipWriteProtected (IdeDev, &WriteProtected);
+ if (!EFI_ERROR (Status)) {
+
+ if (WriteProtected) {
+
+ IdeDev->BlkIo.Media->ReadOnly = TRUE;
+ } else {
+
+ IdeDev->BlkIo.Media->ReadOnly = FALSE;
+ }
+
+ }
+ }
+
+ if (IdeDev->BlkIo.Media->MediaId != OldMediaInfo.MediaId) {
+ //
+ // Media change information got from the device
+ //
+ *MediaChange = TRUE;
+ }
+
+ if (IdeDev->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) {
+ *MediaChange = TRUE;
+ IdeDev->BlkIo.Media->MediaId += 1;
+ }
+
+ if (IdeDev->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) {
+ *MediaChange = TRUE;
+ IdeDev->BlkIo.Media->MediaId += 1;
+ }
+
+ if (IdeDev->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) {
+ *MediaChange = TRUE;
+ IdeDev->BlkIo.Media->MediaId += 1;
+ }
+
+ if (IdeDev->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) {
+ if (IdeDev->BlkIo.Media->MediaPresent) {
+ //
+ // when change from no media to media present, reset the MediaId to 1.
+ //
+ IdeDev->BlkIo.Media->MediaId = 1;
+ } else {
+ //
+ // when no media, reset the MediaId to zero.
+ //
+ IdeDev->BlkIo.Media->MediaId = 0;
+ }
+
+ *MediaChange = TRUE;
+ }
+
+ //
+ // if any change on current existing media,
+ // the Block I/O protocol need to be reinstalled.
+ //
+ if (*MediaChange) {
+ gBS->ReinstallProtocolInterface (
+ IdeDev->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &IdeDev->BlkIo,
+ &IdeDev->BlkIo
+ );
+ }
+
+ if (IdeDev->BlkIo.Media->MediaPresent) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NO_MEDIA;
+ }
+}
+
+/**
+ This function is called by the AtapiBlkIoReadBlocks() to perform
+ read from media in block unit.
+
+ The main command used to access media here is READ(10) Command.
+ READ(10) Command requests that the ATAPI device media transfer
+ specified data to the host. Data is transferred in block(sector)
+ unit. The maximum number of blocks that can be transferred once is
+ 65536. This is the main difference between READ(10) and READ(12)
+ Command. The maximum number of blocks in READ(12) is 2 power 32.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *Buffer
+ A pointer to the destination buffer for the data.
+
+ @param[in] Lba
+ The starting logical block address to read from
+ on the device media.
+
+ @param[in] NumberOfBlocks
+ The number of transfer data blocks.
+
+ @return status is fully dependent on the return status
+ of AtapiPacketCommandIn() function.
+
+**/
+EFI_STATUS
+AtapiReadSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+{
+
+ ATAPI_PACKET_COMMAND Packet;
+ READ10_CMD *Read10Packet;
+ EFI_STATUS Status;
+ UINTN BlocksRemaining;
+ UINT32 Lba32;
+ UINT32 BlockSize;
+ UINT32 ByteCount;
+ UINT16 SectorCount;
+ VOID *PtrBuffer;
+ UINT16 MaxBlock;
+ UINTN TimeOut;
+
+ //
+ // fill command packet for Read(10) command
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Read10Packet = &Packet.Read10;
+ Lba32 = (UINT32) Lba;
+ PtrBuffer = Buffer;
+
+ BlockSize = IdeDev->BlkIo.Media->BlockSize;
+
+ //
+ // limit the data bytes that can be transferred by one Read(10) Command
+ //
+ MaxBlock = 65535;
+
+ BlocksRemaining = NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ while (BlocksRemaining > 0) {
+
+ if (BlocksRemaining <= MaxBlock) {
+
+ SectorCount = (UINT16) BlocksRemaining;
+ } else {
+
+ SectorCount = MaxBlock;
+ }
+
+ //
+ // fill the Packet data structure
+ //
+
+ Read10Packet->opcode = READ_10;
+
+ //
+ // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
+ // Lba0 is MSB, Lba3 is LSB
+ //
+ Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
+ Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
+ Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
+ Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
+
+ //
+ // TranLen0 ~ TranLen1 specify the transfer length in block unit.
+ // TranLen0 is MSB, TranLen is LSB
+ //
+ Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
+ Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
+
+ ByteCount = SectorCount * BlockSize;
+
+ if (IdeDev->Type == IdeCdRom) {
+ TimeOut = CDROMLONGTIMEOUT;
+ } else {
+ TimeOut = ATAPILONGTIMEOUT;
+ }
+
+ Status = AtapiPacketCommandIn (
+ IdeDev,
+ &Packet,
+ (UINT16 *) PtrBuffer,
+ ByteCount,
+ TimeOut
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ PtrBuffer = (UINT8 *) PtrBuffer + SectorCount * BlockSize;
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+/**
+ This function is called by the AtapiBlkIoWriteBlocks() to perform
+ write onto media in block unit.
+ The main command used to access media here is Write(10) Command.
+ Write(10) Command requests that the ATAPI device media transfer
+ specified data to the host. Data is transferred in block (sector)
+ unit. The maximum number of blocks that can be transferred once is
+ 65536.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *Buffer
+ A pointer to the source buffer for the data.
+
+ @param[in] Lba
+ The starting logical block address to write onto
+ the device media.
+
+ @param[in] NumberOfBlocks
+ The number of transfer data blocks.
+
+ @return status is fully dependent on the return status
+ of AtapiPacketCommandOut() function.
+
+**/
+EFI_STATUS
+AtapiWriteSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+{
+
+ ATAPI_PACKET_COMMAND Packet;
+ READ10_CMD *Read10Packet;
+
+ EFI_STATUS Status;
+ UINTN BlocksRemaining;
+ UINT32 Lba32;
+ UINT32 BlockSize;
+ UINT32 ByteCount;
+ UINT16 SectorCount;
+ VOID *PtrBuffer;
+ UINT16 MaxBlock;
+
+ //
+ // fill command packet for Write(10) command
+ // Write(10) command packet has the same data structure as
+ // Read(10) command packet,
+ // so here use the Read10Packet data structure
+ // for the Write(10) command packet.
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Read10Packet = &Packet.Read10;
+
+ Lba32 = (UINT32) Lba;
+ PtrBuffer = Buffer;
+
+ BlockSize = IdeDev->BlkIo.Media->BlockSize;
+
+ //
+ // limit the data bytes that can be transferred by one Read(10) Command
+ //
+ MaxBlock = (UINT16) (65536 / BlockSize);
+
+ BlocksRemaining = NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ while (BlocksRemaining > 0) {
+
+ if (BlocksRemaining >= MaxBlock) {
+ SectorCount = MaxBlock;
+ } else {
+ SectorCount = (UINT16) BlocksRemaining;
+ }
+
+ //
+ // Command code is WRITE_10.
+ //
+ Read10Packet->opcode = WRITE_10;
+
+ //
+ // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
+ // Lba0 is MSB, Lba3 is LSB
+ //
+ Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
+ Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
+ Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
+ Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
+
+ //
+ // TranLen0 ~ TranLen1 specify the transfer length in block unit.
+ // TranLen0 is MSB, TranLen is LSB
+ //
+ Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
+ Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
+
+ ByteCount = SectorCount * BlockSize;
+
+ Status = AtapiPacketCommandOut (
+ IdeDev,
+ &Packet,
+ (UINT16 *) PtrBuffer,
+ ByteCount,
+ ATAPILONGTIMEOUT
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ PtrBuffer = ((UINT8 *) PtrBuffer + SectorCount * BlockSize);
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+/**
+ This function is used to implement the Soft Reset on the specified
+ ATAPI device. Different from the AtaSoftReset(), here reset is a ATA
+ Soft Reset Command special for ATAPI device, and it only take effects
+ on the specified ATAPI device, not on the whole IDE bus.
+ Since the ATAPI soft reset is needed when device is in exceptional
+ condition (such as BSY bit is always set ), I think the Soft Reset
+ command should be sent without waiting for the BSY clear and DRDY
+ set.
+ This function is called by IdeBlkIoReset(),
+ a interface function of Block I/O protocol.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @retval EFI_SUCCESS
+ Soft reset completes successfully.
+
+ @retval EFI_DEVICE_ERROR
+ Any step during the reset process is failed.
+
+**/
+EFI_STATUS
+AtapiSoftReset (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ UINT8 Command;
+ UINT8 DeviceSelect;
+ EFI_STATUS Status;
+
+ //
+ // for ATAPI device, no need to wait DRDY ready after device selecting.
+ // (bit7 and bit5 are both set to 1 for backward compatibility)
+ //
+ DeviceSelect = (UINT8) (((bit7 | bit5) | (IdeDev->Device << 4)));
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect);
+
+ Command = ATAPI_SOFT_RESET_CMD;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, Command);
+
+ //
+ // BSY cleared is the only status return to the host by the device
+ // when reset is completed.
+ // slave device needs at most 31s to clear BSY
+ //
+ Status = WaitForBSYClear (IdeDev, 31000);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // stall 5 seconds to make the device status stable
+ //
+ gBS->Stall (5000000);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is the ATAPI implementation for ReadBlocks in the
+ Block I/O Protocol interface.
+
+ @param[in] *IdeBlkIoDev
+ Indicates the calling context.
+
+ @param[in] MediaId
+ The media id that the read request is for.
+
+ @param[in] LBA
+ The starting logical block address to read from
+ on the device.
+
+ @param[in] BufferSize
+ The size of the Buffer in bytes. This must be a
+ multiple of the intrinsic block size of the device.
+
+ @param[out] *Buffer
+ A pointer to the destination buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the memory that data is read into.
+
+ @retval EFI_SUCCESS
+ Read Blocks successfully.
+
+ @retval EFI_DEVICE_ERROR
+ Read Blocks failed.
+
+ @retval EFI_NO_MEDIA
+ There is no media in the device.
+
+ @retval EFI_MEDIA_CHANGED
+ The MediaId is not for the current media.
+
+ @retval EFI_BAD_BUFFER_SIZE
+ The BufferSize parameter is not a multiple of the
+ intrinsic block size of the device.
+
+ @retval EFI_INVALID_PARAMETER
+ The read request contains LBAs that are not valid,
+ or the data buffer is not valid.
+
+**/
+EFI_STATUS
+AtapiBlkIoReadBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ EFI_STATUS Status;
+
+ BOOLEAN MediaChange;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // ATAPI device media is removable, so it is a must
+ // to detect media first before read operation
+ //
+ MediaChange = FALSE;
+ Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange);
+ if (EFI_ERROR (Status)) {
+
+ if (IdeBlkIoDevice->Cache != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+
+ return Status;
+ }
+ //
+ // Get the intrinsic block size
+ //
+ Media = IdeBlkIoDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (!(Media->MediaPresent)) {
+
+ if (IdeBlkIoDevice->Cache != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+ return EFI_NO_MEDIA;
+
+ }
+
+ if ((MediaId != Media->MediaId) || MediaChange) {
+
+ if (IdeBlkIoDevice->Cache != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (LBA > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if all the parameters are valid, then perform read sectors command
+ // to transfer data from device to host.
+ //
+ Status = AtapiReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Read blocks succeeded
+ //
+
+ //
+ // save the first block to the cache for performance
+ //
+ if (LBA == 0 && !IdeBlkIoDevice->Cache) {
+ IdeBlkIoDevice->Cache = AllocatePool (BlockSize);
+ if (IdeBlkIoDevice != NULL) {
+ CopyMem ((UINT8 *) IdeBlkIoDevice->Cache, (UINT8 *) Buffer, BlockSize);
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ This function is the ATAPI implementation for WriteBlocks in the
+ Block I/O Protocol interface.
+
+ @param[in] *This
+ Indicates the calling context.
+
+ @param[in] MediaId
+ The media id that the write request is for.
+
+ @param[in] LBA
+ The starting logical block address to write onto
+ the device.
+
+ @param[in] BufferSize
+ The size of the Buffer in bytes. This must be a
+ multiple of the intrinsic block size of the device.
+
+ @param[out] *Buffer
+ A pointer to the source buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the memory that data is
+ written from.
+
+ @retval EFI_SUCCESS
+ Write Blocks successfully.
+
+ @retval EFI_DEVICE_ERROR
+ Write Blocks failed.
+
+ @retval EFI_NO_MEDIA
+ There is no media in the device.
+
+ @retval EFI_MEDIA_CHANGE
+ The MediaId is not for the current media.
+
+ @retval EFI_BAD_BUFFER_SIZE
+ The BufferSize parameter is not a multiple of the
+ intrinsic block size of the device.
+
+ @retval EFI_INVALID_PARAMETER
+ The write request contains LBAs that are not valid,
+ or the data buffer is not valid.
+
+ TODO: EFI_MEDIA_CHANGED - add return value to function comment
+ TODO: EFI_WRITE_PROTECTED - add return value to function comment
+**/
+EFI_STATUS
+AtapiBlkIoWriteBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ EFI_STATUS Status;
+ BOOLEAN MediaChange;
+
+ if (LBA == 0 && IdeBlkIoDevice->Cache) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // ATAPI device media is removable,
+ // so it is a must to detect media first before write operation
+ //
+ MediaChange = FALSE;
+ Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange);
+ if (EFI_ERROR (Status)) {
+
+ if (LBA == 0 && IdeBlkIoDevice->Cache) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+ return Status;
+ }
+
+ //
+ // Get the intrinsic block size
+ //
+ Media = IdeBlkIoDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (!(Media->MediaPresent)) {
+
+ if (LBA == 0 && IdeBlkIoDevice->Cache) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+ return EFI_NO_MEDIA;
+ }
+
+ if ((MediaId != Media->MediaId) || MediaChange) {
+
+ if (LBA == 0 && IdeBlkIoDevice->Cache) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Media->ReadOnly) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (LBA > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if all the parameters are valid,
+ // then perform write sectors command to transfer data from host to device.
+ //
+ Status = AtapiWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ This function is used to parse sense data. Only the first
+ sense data is honoured.
+
+ @param[in] IdeDev Indicates the calling context.
+ @param[in] SenseCount Count of sense data.
+ @param[out] Result The parsed result.
+
+ @retval EFI_SUCCESS Successfully parsed.
+ @retval EFI_INVALID_PARAMETER Count of sense data is zero.
+
+**/
+EFI_STATUS
+ParseSenseData (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN SenseCount,
+ OUT SENSE_RESULT *Result
+ )
+{
+ REQUEST_SENSE_DATA *SenseData;
+
+ if (SenseCount == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Only use the first sense data
+ //
+ SenseData = IdeDev->SenseData;
+ *Result = SenseOtherSense;
+
+ switch (SenseData->sense_key) {
+ case SK_NO_SENSE:
+ *Result = SenseNoSenseKey;
+ break;
+ case SK_NOT_READY:
+ switch (SenseData->addnl_sense_code) {
+ case ASC_NO_MEDIA:
+ *Result = SenseNoMedia;
+ break;
+ case ASC_MEDIA_UPSIDE_DOWN:
+ *Result = SenseMediaError;
+ break;
+ case ASC_NOT_READY:
+ if (SenseData->addnl_sense_code_qualifier == ASCQ_IN_PROGRESS) {
+ *Result = SenseDeviceNotReadyNeedRetry;
+ } else {
+ *Result = SenseDeviceNotReadyNoRetry;
+ }
+ break;
+ }
+ break;
+ case SK_UNIT_ATTENTION:
+ if (SenseData->addnl_sense_code == ASC_MEDIA_CHANGE) {
+ *Result = SenseMediaChange;
+ }
+ break;
+ case SK_MEDIUM_ERROR:
+ switch (SenseData->addnl_sense_code) {
+ case ASC_MEDIA_ERR1:
+ case ASC_MEDIA_ERR2:
+ case ASC_MEDIA_ERR3:
+ case ASC_MEDIA_ERR4:
+ *Result = SenseMediaError;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function reads the pending data in the device.
+
+ @param[in] IdeDev Indicates the calling context.
+
+ @retval EFI_SUCCESS Successfully read.
+ @retval EFI_NOT_READY The BSY is set avoiding reading.
+
+**/
+EFI_STATUS
+AtapiReadPendingData (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ UINT8 AltRegister;
+ UINT16 TempWordBuffer;
+
+ AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
+ if ((AltRegister & BSY) == BSY) {
+ return EFI_NOT_READY;
+ }
+ if ((AltRegister & (BSY | DRQ)) == DRQ) {
+ TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus);
+ while ((TempWordBuffer & (BSY | DRQ)) == DRQ) {
+ IDEReadPortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ 1,
+ &TempWordBuffer
+ );
+ TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param WriteProtected TODO: add argument description
+
+ @retval EFI_DEVICE_ERROR TODO: Add description for return value
+ @retval EFI_DEVICE_ERROR TODO: Add description for return value
+ @retval EFI_SUCCESS TODO: Add description for return value
+
+**/
+EFI_STATUS
+IsLS120orZipWriteProtected (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT BOOLEAN *WriteProtected
+ )
+{
+ EFI_STATUS Status;
+
+ *WriteProtected = FALSE;
+
+ Status = LS120EnableMediaStatus (IdeDev, TRUE);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // the Get Media Status Command is only valid
+ // if a Set Features/Enable Media Status Command has been priviously issued.
+ //
+ if (LS120GetMediaStatus (IdeDev) == EFI_WRITE_PROTECTED) {
+
+ *WriteProtected = TRUE;
+ } else {
+
+ *WriteProtected = FALSE;
+ }
+
+ //
+ // After Get Media Status Command completes,
+ // Set Features/Disable Media Command should be sent.
+ //
+ Status = LS120EnableMediaStatus (IdeDev, FALSE);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c new file mode 100644 index 0000000000..4b4a8ef0a3 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c @@ -0,0 +1,1824 @@ +/** @file
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "idebus.h"
+
+BOOLEAN ChannelDeviceDetected = FALSE;
+BOOLEAN SlaveDeviceExist = FALSE;
+UINT8 SlaveDeviceType = INVALID_DEVICE_TYPE;
+BOOLEAN MasterDeviceExist = FALSE;
+UINT8 MasterDeviceType = INVALID_DEVICE_TYPE;
+
+/**
+ TODO: Add function description
+
+ @param PciIo TODO: add argument description
+ @param Port TODO: add argument description
+
+ TODO: add return values
+
+**/
+UINT8
+IDEReadPortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port
+ )
+{
+ UINT8 Data;
+
+ Data = 0;
+ //
+ // perform 1-byte data read from register
+ //
+ PciIo->Io.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+ return Data;
+}
+
+/**
+ Reads multiple words of data from the IDE data port.
+ Call the IO abstraction once to do the complete read,
+ not one word at a time
+
+ @param PciIo Pointer to the EFI_PCI_IO instance
+ @param Port IO port to read
+ @param Count No. of UINT16's to read
+ @param Buffer Pointer to the data buffer for read
+
+**/
+VOID
+IDEReadPortWMultiple (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ UINT16 *AlignedBuffer;
+ UINT16 *WorkingBuffer;
+ UINTN Size;
+
+ //
+ // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
+ // not perform actual I/O operations if buffer pointer passed in is not at
+ // natural boundary. The "Buffer" argument is passed in by user and may not
+ // at 16-bit natural boundary.
+ //
+ Size = sizeof (UINT16) * Count;
+
+ gBS->AllocatePool (
+ EfiBootServicesData,
+ Size + 1,
+ (VOID**)&WorkingBuffer
+ );
+
+ AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
+
+ //
+ // Perform UINT16 data read from FIFO
+ //
+ PciIo->Io.Read (
+ PciIo,
+ EfiPciIoWidthFifoUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ Count,
+ (UINT16*)AlignedBuffer
+ );
+
+ //
+ // Copy data to user buffer
+ //
+ CopyMem (Buffer, (UINT16*)AlignedBuffer, Size);
+ gBS->FreePool (WorkingBuffer);
+}
+
+/**
+ TODO: Add function description
+
+ @param PciIo TODO: add argument description
+ @param Port TODO: add argument description
+ @param Data TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+IDEWritePortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT8 Data
+ )
+{
+ //
+ // perform 1-byte data write to register
+ //
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+
+}
+
+/**
+ TODO: Add function description
+
+ @param PciIo TODO: add argument description
+ @param Port TODO: add argument description
+ @param Data TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+IDEWritePortW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT16 Data
+ )
+{
+ //
+ // perform 1-word data write to register
+ //
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+}
+
+/**
+ Write multiple words of data to the IDE data port.
+ Call the IO abstraction once to do the complete read,
+ not one word at a time
+
+ @param PciIo Pointer to the EFI_PCI_IO instance
+ @param Port IO port to read
+ @param Count No. of UINT16's to read
+ @param Buffer Pointer to the data buffer for read
+
+**/
+VOID
+IDEWritePortWMultiple (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ UINT16 *AlignedBuffer;
+ UINT32 *WorkingBuffer;
+ UINTN Size;
+
+ //
+ // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
+ // not perform actual I/O operations if buffer pointer passed in is not at
+ // natural boundary. The "Buffer" argument is passed in by user and may not
+ // at 16-bit natural boundary.
+ //
+ Size = sizeof (UINT16) * Count;
+
+ gBS->AllocatePool (
+ EfiBootServicesData,
+ Size + 1,
+ (VOID **) &WorkingBuffer
+ );
+
+ AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
+
+ //
+ // Copy data from user buffer to working buffer
+ //
+ CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size);
+
+ //
+ // perform UINT16 data write to the FIFO
+ //
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthFifoUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ Count,
+ (UINT16 *) AlignedBuffer
+ );
+
+ gBS->FreePool (WorkingBuffer);
+}
+
+//
+// GetIdeRegistersBaseAddr
+//
+/**
+ Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,
+ use fixed addresses. In Native-PCI mode, get base addresses from BARs in
+ the PCI IDE controller's Configuration Space.
+
+ The steps to get IDE IO port registers' base addresses for each channel
+ as follows:
+
+ 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE
+ controller's Configuration Space to determine the operating mode.
+
+ 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.
+ <pre>
+ ___________________________________________
+ | | Command Block | Control Block |
+ | Channel | Registers | Registers |
+ |___________|_______________|_______________|
+ | Primary | 1F0h - 1F7h | 3F6h - 3F7h |
+ |___________|_______________|_______________|
+ | Secondary | 170h - 177h | 376h - 377h |
+ |___________|_______________|_______________|
+
+ Table 1. Compatibility resource mappings
+ </pre>
+
+ b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs
+ in IDE controller's PCI Configuration Space, shown in the Table 2 below.
+ <pre>
+ ___________________________________________________
+ | | Command Block | Control Block |
+ | Channel | Registers | Registers |
+ |___________|___________________|___________________|
+ | Primary | BAR at offset 0x10| BAR at offset 0x14|
+ |___________|___________________|___________________|
+ | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
+ |___________|___________________|___________________|
+
+ Table 2. BARs for Register Mapping
+ </pre>
+ @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for
+ primary, 0374h for secondary. So 2 bytes extra offset should be
+ added to the base addresses read from BARs.
+
+ For more details, please refer to PCI IDE Controller Specification and Intel
+ ICH4 Datasheet.
+
+ @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance
+ @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to
+ receive IDE IO port registers' base addresses
+
+**/
+EFI_STATUS
+GetIdeRegistersBaseAddr (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr
+ )
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 PciData;
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PciData),
+ &PciData
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {
+ IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 0x1f0;
+ IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 0x3f6;
+ IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr =
+ (UINT16)((PciData.Device.Bar[4] & 0x0000fff0));
+ } else {
+ //
+ // The BARs should be of IO type
+ //
+ if ((PciData.Device.Bar[0] & bit0) == 0 ||
+ (PciData.Device.Bar[1] & bit0) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr =
+ (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);
+ IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr =
+ (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);
+ IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr =
+ (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
+ }
+
+ if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {
+ IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 0x170;
+ IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 0x376;
+ IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr =
+ (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
+ } else {
+ //
+ // The BARs should be of IO type
+ //
+ if ((PciData.Device.Bar[2] & bit0) == 0 ||
+ (PciData.Device.Bar[3] & bit0) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr =
+ (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);
+ IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr =
+ (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);
+ IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr =
+ (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is used to requery IDE resources. The IDE controller will
+ probably switch between native and legacy modes during the EFI->CSM->OS
+ transfer. We do this everytime before an BlkIo operation to ensure its
+ succeess.
+
+ @param IdeDev The BLK_IO private data which specifies the IDE device
+
+**/
+EFI_STATUS
+ReassignIdeResources (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
+ UINT16 CommandBlockBaseAddr;
+ UINT16 ControlBlockBaseAddr;
+
+ //
+ // Requery IDE IO port registers' base addresses in case of the switch of
+ // native and legacy modes
+ //
+ Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS));
+ CommandBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr;
+ ControlBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr;
+
+ IdeDev->IoPort->Data = CommandBlockBaseAddr;
+ (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
+ IdeDev->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
+ IdeDev->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
+ IdeDev->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
+ IdeDev->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
+ IdeDev->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
+
+ (*(UINT16 *) &IdeDev->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
+ (*(UINT16 *) &IdeDev->IoPort->Alt) = ControlBlockBaseAddr;
+ IdeDev->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
+ IdeDev->IoPort->MasterSlave = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0);
+
+ IdeDev->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr;
+ return EFI_SUCCESS;
+}
+
+//
+// DiscoverIdeDevice
+//
+/**
+ Detect if there is disk connected to this port
+
+ @param IdeDev The BLK_IO private data which specifies the IDE device
+
+**/
+EFI_STATUS
+DiscoverIdeDevice (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+
+ //
+ // If a channel has not been checked, check it now. Then set it to "checked" state
+ // After this step, all devices in this channel have been checked.
+ //
+ if (ChannelDeviceDetected == FALSE) {
+ Status = DetectIDEController (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ Status = EFI_NOT_FOUND;
+
+ //
+ // Device exists. test if it is an ATA device.
+ // Prefer the result from DetectIDEController,
+ // if failed, try another device type to handle
+ // devices that not follow the spec.
+ //
+ if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) {
+ if (MasterDeviceType == ATA_DEVICE_TYPE) {
+ Status = ATAIdentify (IdeDev);
+ if (EFI_ERROR (Status)) {
+ Status = ATAPIIdentify (IdeDev);
+ if (!EFI_ERROR (Status)) {
+ MasterDeviceType = ATAPI_DEVICE_TYPE;
+ }
+ }
+ } else {
+ Status = ATAPIIdentify (IdeDev);
+ if (EFI_ERROR (Status)) {
+ Status = ATAIdentify (IdeDev);
+ if (!EFI_ERROR (Status)) {
+ MasterDeviceType = ATA_DEVICE_TYPE;
+ }
+ }
+ }
+ }
+ if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) {
+ if (SlaveDeviceType == ATA_DEVICE_TYPE) {
+ Status = ATAIdentify (IdeDev);
+ if (EFI_ERROR (Status)) {
+ Status = ATAPIIdentify (IdeDev);
+ if (!EFI_ERROR (Status)) {
+ SlaveDeviceType = ATAPI_DEVICE_TYPE;
+ }
+ }
+ } else {
+ Status = ATAPIIdentify (IdeDev);
+ if (EFI_ERROR (Status)) {
+ Status = ATAIdentify (IdeDev);
+ if (!EFI_ERROR (Status)) {
+ SlaveDeviceType = ATA_DEVICE_TYPE;
+ }
+ }
+ }
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Init Block I/O interface
+ //
+ IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
+ IdeDev->BlkIo.Reset = IDEBlkIoReset;
+ IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks;
+ IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks;
+ IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks;
+
+ IdeDev->BlkMedia.LogicalPartition = FALSE;
+ IdeDev->BlkMedia.WriteCaching = FALSE;
+
+ //
+ // Init Disk Info interface
+ //
+ gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID));
+ IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry;
+ IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify;
+ IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData;
+ IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This interface is used to initialize all state data related to the detection of one
+ channel.
+
+ @retval EFI_SUCCESS Completed Successfully.
+
+**/
+EFI_STATUS
+InitializeIDEChannelData (
+ VOID
+ )
+{
+ ChannelDeviceDetected = FALSE;
+ MasterDeviceExist = FALSE;
+ MasterDeviceType = 0xff;
+ SlaveDeviceExist = FALSE;
+ SlaveDeviceType = 0xff;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is called by DiscoverIdeDevice(). It is used for detect
+ whether the IDE device exists in the specified Channel as the specified
+ Device Number.
+
+ There is two IDE channels: one is Primary Channel, the other is
+ Secondary Channel.(Channel is the logical name for the physical "Cable".)
+ Different channel has different register group.
+
+ On each IDE channel, at most two IDE devices attach,
+ one is called Device 0 (Master device), the other is called Device 1
+ (Slave device). The devices on the same channel co-use the same register
+ group, so before sending out a command for a specified device via command
+ register, it is a must to select the current device to accept the command
+ by set the device number in the Head/Device Register.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @retval TRUE
+ successfully detects device.
+
+ @retval FALSE
+ any failure during detection process will return this
+ value.
+
+ @note
+ TODO: EFI_SUCCESS - add return value to function comment
+ TODO: EFI_NOT_FOUND - add return value to function comment
+
+**/
+EFI_STATUS
+DetectIDEController (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ EFI_STATUS Status;
+ UINT8 SectorCountReg;
+ UINT8 LBALowReg;
+ UINT8 LBAMidReg;
+ UINT8 LBAHighReg;
+ UINT8 InitStatusReg;
+ UINT8 StatusReg;
+
+ //
+ // Select slave device
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((1 << 4) | 0xe0)
+ );
+ gBS->Stall (100);
+
+ //
+ // Save the init slave status register
+ //
+ InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ //
+ // Select Master back
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((0 << 4) | 0xe0)
+ );
+ gBS->Stall (100);
+
+ //
+ // Send ATA Device Execut Diagnostic command.
+ // This command should work no matter DRDY is ready or not
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90);
+
+ Status = WaitForBSYClear (IdeDev, 3500);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status));
+ return Status;
+ }
+ //
+ // Read device signature
+ //
+ //
+ // Select Master
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((0 << 4) | 0xe0)
+ );
+ gBS->Stall (100);
+ SectorCountReg = IDEReadPortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->SectorCount
+ );
+ LBALowReg = IDEReadPortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->SectorNumber
+ );
+ LBAMidReg = IDEReadPortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderLsb
+ );
+ LBAHighReg = IDEReadPortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderMsb
+ );
+ if ((SectorCountReg == 0x1) &&
+ (LBALowReg == 0x1) &&
+ (LBAMidReg == 0x0) &&
+ (LBAHighReg == 0x0)) {
+ MasterDeviceExist = TRUE;
+ MasterDeviceType = ATA_DEVICE_TYPE;
+ } else {
+ if ((LBAMidReg == 0x14) &&
+ (LBAHighReg == 0xeb)) {
+ MasterDeviceExist = TRUE;
+ MasterDeviceType = ATAPI_DEVICE_TYPE;
+ }
+ }
+
+ //
+ // For some Hard Drive, it takes some time to get
+ // the right signature when operating in single slave mode.
+ // We stall 20ms to work around this.
+ //
+ if (!MasterDeviceExist) {
+ gBS->Stall (20000);
+ }
+
+ //
+ // Select Slave
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((1 << 4) | 0xe0)
+ );
+ gBS->Stall (100);
+ SectorCountReg = IDEReadPortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->SectorCount
+ );
+ LBALowReg = IDEReadPortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->SectorNumber
+ );
+ LBAMidReg = IDEReadPortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderLsb
+ );
+ LBAHighReg = IDEReadPortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderMsb
+ );
+ StatusReg = IDEReadPortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Reg.Status
+ );
+ if ((SectorCountReg == 0x1) &&
+ (LBALowReg == 0x1) &&
+ (LBAMidReg == 0x0) &&
+ (LBAHighReg == 0x0)) {
+ SlaveDeviceExist = TRUE;
+ SlaveDeviceType = ATA_DEVICE_TYPE;
+ } else {
+ if ((LBAMidReg == 0x14) &&
+ (LBAHighReg == 0xeb)) {
+ SlaveDeviceExist = TRUE;
+ SlaveDeviceType = ATAPI_DEVICE_TYPE;
+ }
+ }
+
+ //
+ // When single master is plugged, slave device
+ // will be wrongly detected. Here's the workaround
+ // for ATA devices by detecting DRY bit in status
+ // register.
+ // NOTE: This workaround doesn't apply to ATAPI.
+ //
+ if (MasterDeviceExist && SlaveDeviceExist &&
+ (StatusReg & DRDY) == 0 &&
+ (InitStatusReg & DRDY) == 0 &&
+ MasterDeviceType == SlaveDeviceType &&
+ SlaveDeviceType != ATAPI_DEVICE_TYPE) {
+ SlaveDeviceExist = FALSE;
+ }
+
+ //
+ // Indicate this channel has been detected
+ //
+ ChannelDeviceDetected = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is used to poll for the DRQ bit clear in the Status
+ Register. DRQ is cleared when the device is finished transferring data.
+ So this function is called after data transfer is finished.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ clear.
+
+ @retval EFI_SUCCESS
+ DRQ bit clear within the time out.
+
+ @retval EFI_TIMEOUT
+ DRQ bit not clear within the time out.
+
+ @note
+ Read Status Register will clear interrupt status.
+
+**/
+EFI_STATUS
+DRQClear (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ UINT32 Delay;
+ UINT8 StatusRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ //
+ // wait for BSY == 0 and DRQ == 0
+ //
+ if ((StatusRegister & (DRQ | BSY)) == 0) {
+ break;
+ }
+
+ if ((StatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is used to poll for the DRQ bit clear in the Alternate
+ Status Register. DRQ is cleared when the device is finished
+ transferring data. So this function is called after data transfer
+ is finished.
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ clear.
+
+ @retval EFI_SUCCESS
+ DRQ bit clear within the time out.
+
+ @retval EFI_TIMEOUT
+ DRQ bit not clear within the time out.
+
+ @note
+ Read Alternate Status Register will not clear interrupt status.
+
+**/
+EFI_STATUS
+DRQClear2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ UINT32 Delay;
+ UINT8 AltRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+
+ AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
+
+ //
+ // wait for BSY == 0 and DRQ == 0
+ //
+ if ((AltRegister & (DRQ | BSY)) == 0) {
+ break;
+ }
+
+ if ((AltRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is used to poll for the DRQ bit set in the
+ Status Register.
+ DRQ is set when the device is ready to transfer data. So this function
+ is called after the command is sent to the device and before required
+ data is transferred.
+
+ @param[in] IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure,used
+ to record all the information of the IDE device.
+
+ @param[in] UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ @retval EFI_SUCCESS
+ DRQ bit set within the time out.
+
+ @retval EFI_TIMEOUT
+ DRQ bit not set within the time out.
+
+ @retval EFI_ABORTED
+ DRQ bit not set caused by the command abort.
+
+ @note
+ Read Status Register will clear interrupt status.
+
+**/
+EFI_STATUS
+DRQReady (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+{
+ UINT32 Delay;
+ UINT8 StatusRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+ //
+ // read Status Register will clear interrupt
+ //
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ //
+ // BSY==0,DRQ==1
+ //
+ if ((StatusRegister & (BSY | DRQ)) == DRQ) {
+ break;
+ }
+
+ if ((StatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is used to poll for the DRQ bit set in the
+ Alternate Status Register. DRQ is set when the device is ready to
+ transfer data. So this function is called after the command
+ is sent to the device and before required data is transferred.
+
+ @param[in] IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ @retval EFI_SUCCESS
+ DRQ bit set within the time out.
+
+ @retval EFI_TIMEOUT
+ DRQ bit not set within the time out.
+
+ @retval EFI_ABORTED
+ DRQ bit not set caused by the command abort.
+
+ @note
+ Read Alternate Status Register will not clear interrupt status.
+
+**/
+EFI_STATUS
+DRQReady2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+{
+ UINT32 Delay;
+ UINT8 AltRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+
+ do {
+ //
+ // Read Alternate Status Register will not clear interrupt status
+ //
+ AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
+ //
+ // BSY == 0 , DRQ == 1
+ //
+ if ((AltRegister & (BSY | DRQ)) == DRQ) {
+ break;
+ }
+
+ if ((AltRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is used to poll for the BSY bit clear in the
+ Status Register. BSY is clear when the device is not busy.
+ Every command must be sent after device is not busy.
+
+ @param[in] IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ @retval EFI_SUCCESS
+ BSY bit clear within the time out.
+
+ @retval EFI_TIMEOUT
+ BSY bit not clear within the time out.
+
+ @note
+ Read Status Register will clear interrupt status.
+
+**/
+EFI_STATUS
+WaitForBSYClear (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+{
+ UINT32 Delay;
+ UINT8 StatusRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+ if ((StatusRegister & BSY) == 0x00) {
+ break;
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+//
+// WaitForBSYClear2
+//
+/**
+ This function is used to poll for the BSY bit clear in the
+ Alternate Status Register. BSY is clear when the device is not busy.
+ Every command must be sent after device is not busy.
+
+ @param[in] IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ @retval EFI_SUCCESS
+ BSY bit clear within the time out.
+
+ @retval EFI_TIMEOUT
+ BSY bit not clear within the time out.
+
+ @note
+ Read Alternate Status Register will not clear interrupt status.
+
+**/
+EFI_STATUS
+WaitForBSYClear2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+{
+ UINT32 Delay;
+ UINT8 AltRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+ AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
+ if ((AltRegister & BSY) == 0x00) {
+ break;
+ }
+
+ gBS->Stall (30);
+
+ Delay--;
+
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// DRDYReady
+//
+/**
+ This function is used to poll for the DRDY bit set in the
+ Status Register. DRDY bit is set when the device is ready
+ to accept command. Most ATA commands must be sent after
+ DRDY set except the ATAPI Packet Command.
+
+ @param[in] IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ @retval EFI_SUCCESS
+ DRDY bit set within the time out.
+
+ @retval EFI_TIMEOUT
+ DRDY bit not set within the time out.
+
+ @note
+ Read Status Register will clear interrupt status.
+
+**/
+EFI_STATUS
+DRDYReady (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN DelayInMilliSeconds
+ )
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DelayInMilliSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ UINT32 Delay;
+ UINT8 StatusRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+ //
+ // BSY == 0 , DRDY == 1
+ //
+ if ((StatusRegister & (DRDY | BSY)) == DRDY) {
+ break;
+ }
+
+ if ((StatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ gBS->Stall (30);
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// DRDYReady2
+//
+/**
+ This function is used to poll for the DRDY bit set in the
+ Alternate Status Register. DRDY bit is set when the device is ready
+ to accept command. Most ATA commands must be sent after
+ DRDY set except the ATAPI Packet Command.
+
+ @param[in] IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ @retval EFI_SUCCESS
+ DRDY bit set within the time out.
+
+ @retval EFI_TIMEOUT
+ DRDY bit not set within the time out.
+
+ @note
+ Read Alternate Status Register will clear interrupt status.
+
+**/
+EFI_STATUS
+DRDYReady2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN DelayInMilliSeconds
+ )
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DelayInMilliSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ UINT32 Delay;
+ UINT8 AltRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+ AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
+ //
+ // BSY == 0 , DRDY == 1
+ //
+ if ((AltRegister & (DRDY | BSY)) == DRDY) {
+ break;
+ }
+
+ if ((AltRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ gBS->Stall (30);
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// SwapStringChars
+//
+/**
+ This function is a helper function used to change the char order in a
+ string. It is designed specially for the PrintAtaModuleName() function.
+ After the IDE device is detected, the IDE driver gets the device module
+ name by sending ATA command called ATA Identify Command or ATAPI
+ Identify Command to the specified IDE device. The module name returned
+ is a string of ASCII characters: the first character is bit8--bit15
+ of the first word, the second character is bit0--bit7 of the first word
+ and so on. Thus the string can not be print directly before it is
+ preprocessed by this func to change the order of characters in
+ each word in the string.
+
+ @param[in] CHAR8 IN *Destination
+ Indicates the destination string.
+
+ @param[in] CHAR8 IN *Source
+ Indicates the source string.
+
+ @param[in] UINT8 IN Size
+ the length of the string
+
+**/
+VOID
+SwapStringChars (
+ IN CHAR8 *Destination,
+ IN CHAR8 *Source,
+ IN UINT32 Size
+ )
+{
+ UINT32 Index;
+ CHAR8 Temp;
+
+ for (Index = 0; Index < Size; Index += 2) {
+
+ Temp = Source[Index + 1];
+ Destination[Index + 1] = Source[Index];
+ Destination[Index] = Temp;
+ }
+}
+
+//
+// ReleaseIdeResources
+//
+/**
+ Release resources of an IDE device before stopping it.
+
+ @param[in] *IdeBlkIoDevice Standard IDE device private data structure
+
+**/
+VOID
+ReleaseIdeResources (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice
+ )
+{
+ if (IdeBlkIoDevice == NULL) {
+ return ;
+ }
+
+ //
+ // Release all the resourses occupied by the IDE_BLK_IO_DEV
+ //
+
+ if (IdeBlkIoDevice->SenseData != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->SenseData);
+ IdeBlkIoDevice->SenseData = NULL;
+ }
+
+ if (IdeBlkIoDevice->Cache != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+
+ if (IdeBlkIoDevice->pIdData != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->pIdData);
+ IdeBlkIoDevice->pIdData = NULL;
+ }
+
+ if (IdeBlkIoDevice->pInquiryData != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->pInquiryData);
+ IdeBlkIoDevice->pInquiryData = NULL;
+ }
+
+ if (IdeBlkIoDevice->ControllerNameTable != NULL) {
+ FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable);
+ IdeBlkIoDevice->ControllerNameTable = NULL;
+ }
+
+ if (IdeBlkIoDevice->IoPort != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->IoPort);
+ }
+
+ if (IdeBlkIoDevice->DevicePath != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->DevicePath);
+ }
+
+ if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) {
+ gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent);
+ IdeBlkIoDevice->ExitBootServiceEvent = NULL;
+ }
+
+ gBS->FreePool (IdeBlkIoDevice);
+ IdeBlkIoDevice = NULL;
+
+ return ;
+}
+
+//
+// SetDeviceTransferMode
+//
+/**
+ Set the calculated Best transfer mode to a detected device
+
+ @param[in] *IdeDev Standard IDE device private data structure
+ @param[in] *TransferMode The device transfer mode to be set
+
+ @return Set transfer mode Command execute status
+
+**/
+EFI_STATUS
+SetDeviceTransferMode (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATA_TRANSFER_MODE *TransferMode
+ )
+// TODO: function comment is missing 'Routine Description:'
+{
+ EFI_STATUS Status;
+ UINT8 DeviceSelect;
+ UINT8 SectorCount;
+
+ DeviceSelect = 0;
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
+ SectorCount = *((UINT8 *) TransferMode);
+
+ //
+ // Send SET FEATURE command (sub command 0x03) to set pio mode.
+ //
+ Status = AtaNonDataCommandIn (
+ IdeDev,
+ SET_FEATURES_CMD,
+ DeviceSelect,
+ 0x03,
+ SectorCount,
+ 0,
+ 0,
+ 0
+ );
+
+ return Status;
+}
+
+/**
+ Send ATA command into device with NON_DATA protocol
+
+ @param IdeDev Standard IDE device private data structure
+ @param AtaCommand The ATA command to be sent
+ @param Device The value in Device register
+ @param Feature The value in Feature register
+ @param SectorCount The value in SectorCount register
+ @param LbaLow The value in LBA_LOW register
+ @param LbaMiddle The value in LBA_MIDDLE register
+ @param LbaHigh The value in LBA_HIGH register
+
+ @retval EFI_SUCCESS Reading succeed
+ @retval EFI_ABORTED Command failed
+ @retval EFI_DEVICE_ERROR Device status error
+
+**/
+EFI_STATUS
+AtaNonDataCommandIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT8 Feature,
+ IN UINT8 SectorCount,
+ IN UINT8 LbaLow,
+ IN UINT8 LbaMiddle,
+ IN UINT8 LbaHigh
+ )
+{
+ EFI_STATUS Status;
+ UINT8 StatusRegister;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0)
+ );
+
+ //
+ // ATA commands for ATA device must be issued when DRDY is set
+ //
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Pass parameter into device register block
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ //
+ // Send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ //
+ // Wait for command completion
+ // For ATA_SMART_CMD, we may need more timeout to let device
+ // adjust internal states.
+ //
+ if (AtaCommand == ATA_SMART_CMD) {
+ Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT);
+ } else {
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+ if ((StatusRegister & ERR) == ERR) {
+ //
+ // Failed to execute command, abort operation
+ //
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Send ATA Ext command into device with NON_DATA protocol
+
+ @param IdeDev Standard IDE device private data structure
+ @param AtaCommand The ATA command to be sent
+ @param Device The value in Device register
+ @param Feature The value in Feature register
+ @param SectorCount The value in SectorCount register
+ @param LbaAddress The LBA address in 48-bit mode
+
+ @retval EFI_SUCCESS Reading succeed
+ @retval EFI_ABORTED Command failed
+ @retval EFI_DEVICE_ERROR Device status error
+
+**/
+EFI_STATUS
+AtaNonDataCommandInExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+{
+ EFI_STATUS Status;
+ UINT8 StatusRegister;
+ UINT8 SectorCount8;
+ UINT8 Feature8;
+ UINT8 LbaLow;
+ UINT8 LbaMid;
+ UINT8 LbaHigh;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0)
+ );
+
+ //
+ // ATA commands for ATA device must be issued when DRDY is set
+ //
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Pass parameter into device register block
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ //
+ // Fill the feature register, which is a two-byte FIFO. Need write twice.
+ //
+ Feature8 = (UINT8) (Feature >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
+
+ Feature8 = (UINT8) Feature;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
+
+ //
+ // Fill the sector count register, which is a two-byte FIFO. Need write twice.
+ //
+ SectorCount8 = (UINT8) (SectorCount >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ SectorCount8 = (UINT8) SectorCount;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ //
+ // Fill the start LBA registers, which are also two-byte FIFO
+ //
+ LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);
+ LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);
+ LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ LbaLow = (UINT8) LbaAddress;
+ LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);
+ LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ //
+ // Send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ //
+ // Wait for command completion
+ //
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+ if ((StatusRegister & ERR) == ERR) {
+ //
+ // Failed to execute command, abort operation
+ //
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// SetDriveParameters
+//
+/**
+ Set drive parameters for devices not support PACKETS command
+
+ @param[in] IdeDev Standard IDE device private data structure
+ @param[in] DriveParameters The device parameters to be set into the disk
+
+ @return SetParameters Command execute status
+
+**/
+EFI_STATUS
+SetDriveParameters (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATA_DRIVE_PARMS *DriveParameters
+ )
+{
+ EFI_STATUS Status;
+ UINT8 DeviceSelect;
+
+ DeviceSelect = 0;
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
+
+ //
+ // Send Init drive parameters
+ //
+ Status = AtaNonDataCommandIn (
+ IdeDev,
+ INIT_DRIVE_PARAM_CMD,
+ (UINT8) (DeviceSelect + DriveParameters->Heads),
+ 0,
+ DriveParameters->Sector,
+ 0,
+ 0,
+ 0
+ );
+
+ //
+ // Send Set Multiple parameters
+ //
+ Status = AtaNonDataCommandIn (
+ IdeDev,
+ SET_MULTIPLE_MODE_CMD,
+ DeviceSelect,
+ 0,
+ DriveParameters->MultipleSector,
+ 0,
+ 0,
+ 0
+ );
+ return Status;
+}
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ @retval EFI_SUCCESS TODO: Add description for return value
+
+**/
+EFI_STATUS
+EnableInterrupt (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+{
+ UINT8 DeviceControl;
+
+ //
+ // Enable interrupt for DMA operation
+ //
+ DeviceControl = 0;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
+
+ @param[in] Event Pointer to this event
+ @param[in] Context Event hanlder private data
+
+**/
+VOID
+EFIAPI
+ClearInterrupt (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINT64 IoPortForBmis;
+ UINT8 RegisterValue;
+ IDE_BLK_IO_DEV *IdeDev;
+
+ //
+ // Get our context
+ //
+ IdeDev = (IDE_BLK_IO_DEV *) Context;
+
+ //
+ // Obtain IDE IO port registers' base addresses
+ //
+ Status = ReassignIdeResources (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Check whether interrupt is pending
+ //
+
+ //
+ // Reset IDE device to force it de-assert interrupt pin
+ // Note: this will reset all devices on this IDE channel
+ //
+ AtaSoftReset (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Get base address of IDE Bus Master Status Regsiter
+ //
+ if (IdePrimary == IdeDev->Channel) {
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
+ } else {
+ if (IdeSecondary == IdeDev->Channel) {
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
+ } else {
+ return;
+ }
+ }
+ //
+ // Read BMIS register and clear ERROR and INTR bit
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Select the other device on this channel to ensure this device to release the interrupt pin
+ //
+ if (IdeDev->Device == 0) {
+ RegisterValue = (1 << 4) | 0xe0;
+ } else {
+ RegisterValue = (0 << 4) | 0xe0;
+ }
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ RegisterValue
+ );
+
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h new file mode 100644 index 0000000000..ec1f9e07a0 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h @@ -0,0 +1,1328 @@ +/** @file
+ Header file for IDE Bus Driver, containing the helper functions'
+ entire prototype.
+
+ Copyright (c) 2006 - 2007 Intel Corporation. <BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including
+ Add - IDEBlkIoReadBlocksExt() func definition
+ Add - IDEBlkIoWriteBlocksExt() func definition
+
+**/
+
+#ifndef _IDE_H
+#define _IDE_H
+
+//
+// Helper functions Prototype
+//
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param Controller TODO: add argument description
+ @param Handle TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+DeRegisterIdeDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param Controller TODO: add argument description
+ @param PciIo TODO: add argument description
+ @param ParentDevicePath TODO: add argument description
+ @param RemainingDevicePath TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EnableIdeDevice (
+ IN EFI_HANDLE Controller,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param PciIo TODO: add argument description
+ @param Port TODO: add argument description
+
+ TODO: add return values
+
+**/
+UINT8
+IDEReadPortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param PciIo TODO: add argument description
+ @param Port TODO: add argument description
+ @param Count TODO: add argument description
+ @param Buffer TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+IDEReadPortWMultiple (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param PciIo TODO: add argument description
+ @param Port TODO: add argument description
+ @param Data TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+IDEWritePortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT8 Data
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param PciIo TODO: add argument description
+ @param Port TODO: add argument description
+ @param Data TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+IDEWritePortW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT16 Data
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param PciIo TODO: add argument description
+ @param Port TODO: add argument description
+ @param Count TODO: add argument description
+ @param Buffer TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+IDEWritePortWMultiple (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param PciIo TODO: add argument description
+ @param IdeRegsBaseAddr TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+GetIdeRegistersBaseAddr (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+ReassignIdeResources (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+DiscoverIdeDevice (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ This interface is used to initialize all state data related to the
+ detection of one channel.
+
+ @retval EFI_SUCCESS Completed successfully.
+
+**/
+EFI_STATUS
+InitializeIDEChannelData (
+ VOID
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+DetectIDEController (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param TimeoutInMilliSeconds TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+DRQClear (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param TimeoutInMilliSeconds TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+DRQClear2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param TimeoutInMilliSeconds TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+DRQReady (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param TimeoutInMilliSeconds TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+DRQReady2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param TimeoutInMilliSeconds TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+WaitForBSYClear (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param TimeoutInMilliSeconds TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+WaitForBSYClear2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param DelayInMilliSeconds TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+DRDYReady (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN DelayInMilliSeconds
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param DelayInMilliSeconds TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+DRDYReady2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN DelayInMilliSeconds
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param Destination TODO: add argument description
+ @param Source TODO: add argument description
+ @param Size TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+SwapStringChars (
+ IN CHAR8 *Destination,
+ IN CHAR8 *Source,
+ IN UINT32 Size
+ )
+;
+
+//
+// ATA device functions' prototype
+//
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+ATAIdentify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+PrintAtaModuleName (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param Buffer TODO: add argument description
+ @param ByteCount TODO: add argument description
+ @param AtaCommand TODO: add argument description
+ @param Head TODO: add argument description
+ @param SectorCount TODO: add argument description
+ @param SectorNumber TODO: add argument description
+ @param CylinderLsb TODO: add argument description
+ @param CylinderMsb TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaPioDataIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN UINT8 Head,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorNumber,
+ IN UINT8 CylinderLsb,
+ IN UINT8 CylinderMsb
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param Buffer TODO: add argument description
+ @param ByteCount TODO: add argument description
+ @param AtaCommand TODO: add argument description
+ @param Head TODO: add argument description
+ @param SectorCount TODO: add argument description
+ @param SectorNumber TODO: add argument description
+ @param CylinderLsb TODO: add argument description
+ @param CylinderMsb TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaPioDataOut (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN UINT8 Head,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorNumber,
+ IN UINT8 CylinderLsb,
+ IN UINT8 CylinderMsb
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+CheckErrorStatus (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param DataBuffer TODO: add argument description
+ @param Lba TODO: add argument description
+ @param NumberOfBlocks TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaReadSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param BufferData TODO: add argument description
+ @param Lba TODO: add argument description
+ @param NumberOfBlocks TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaWriteSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *BufferData,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaSoftReset (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeBlkIoDevice TODO: add argument description
+ @param MediaId TODO: add argument description
+ @param LBA TODO: add argument description
+ @param BufferSize TODO: add argument description
+ @param Buffer TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaBlkIoReadBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeBlkIoDevice TODO: add argument description
+ @param MediaId TODO: add argument description
+ @param LBA TODO: add argument description
+ @param BufferSize TODO: add argument description
+ @param Buffer TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaBlkIoWriteBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+;
+
+//
+// ATAPI device functions' prototype
+//
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+ATAPIIdentify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiInquiry (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param Packet TODO: add argument description
+ @param Buffer TODO: add argument description
+ @param ByteCount TODO: add argument description
+ @param TimeOut TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiPacketCommandIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATAPI_PACKET_COMMAND *Packet,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN UINTN TimeOut
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param Packet TODO: add argument description
+ @param Buffer TODO: add argument description
+ @param ByteCount TODO: add argument description
+ @param TimeOut TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiPacketCommandOut (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATAPI_PACKET_COMMAND *Packet,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN UINTN TimeOut
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param Buffer TODO: add argument description
+ @param ByteCount TODO: add argument description
+ @param Read TODO: add argument description
+ @param TimeOut TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+PioReadWriteData (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN BOOLEAN Read,
+ IN UINTN TimeOut
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiTestUnitReady (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT UINTN *SenseCount
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param SenseCounts TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiRequestSense (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT UINTN *SenseCounts
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiReadCapacity (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT UINTN *SenseCount
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param MediaChange TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiDetectMedia (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT BOOLEAN *MediaChange
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param Buffer TODO: add argument description
+ @param Lba TODO: add argument description
+ @param NumberOfBlocks TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiReadSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param Buffer TODO: add argument description
+ @param Lba TODO: add argument description
+ @param NumberOfBlocks TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiWriteSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiSoftReset (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeBlkIoDevice TODO: add argument description
+ @param MediaId TODO: add argument description
+ @param LBA TODO: add argument description
+ @param BufferSize TODO: add argument description
+ @param Buffer TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiBlkIoReadBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeBlkIoDevice TODO: add argument description
+ @param MediaId TODO: add argument description
+ @param LBA TODO: add argument description
+ @param BufferSize TODO: add argument description
+ @param Buffer TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiBlkIoWriteBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param SenseCount TODO: add argument description
+ @param Result TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+ParseSenseData (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN SenseCount,
+ OUT SENSE_RESULT *Result
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtapiReadPendingData (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param WriteProtected TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+IsLS120orZipWriteProtected (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT BOOLEAN *WriteProtected
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeBlkIoDevice TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+ReleaseIdeResources (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param TransferMode TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+SetDeviceTransferMode (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATA_TRANSFER_MODE *TransferMode
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param NativeMaxAddress TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+ReadNativeMaxAddress (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT EFI_LBA *NativeMaxAddress
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param MaxAddress TODO: add argument description
+ @param bVolatile TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+SetMaxAddress (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN EFI_LBA MaxAddress,
+ IN BOOLEAN bVolatile
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param AtaCommand TODO: add argument description
+ @param Device TODO: add argument description
+ @param Feature TODO: add argument description
+ @param SectorCount TODO: add argument description
+ @param LbaLow TODO: add argument description
+ @param LbaMiddle TODO: add argument description
+ @param LbaHigh TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaNonDataCommandIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT8 Feature,
+ IN UINT8 SectorCount,
+ IN UINT8 LbaLow,
+ IN UINT8 LbaMiddle,
+ IN UINT8 LbaHigh
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param AtaCommand TODO: add argument description
+ @param Device TODO: add argument description
+ @param Feature TODO: add argument description
+ @param SectorCount TODO: add argument description
+ @param LbaAddress TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaNonDataCommandInExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param DataBuffer TODO: add argument description
+ @param StartLba TODO: add argument description
+ @param NumberOfBlocks TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaReadSectorsExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param DataBuffer TODO: add argument description
+ @param StartLba TODO: add argument description
+ @param NumberOfBlocks TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaWriteSectorsExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param DataBuffer TODO: add argument description
+ @param StartLba TODO: add argument description
+ @param NumberOfBlocks TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaUdmaReadExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param DataBuffer TODO: add argument description
+ @param StartLba TODO: add argument description
+ @param NumberOfBlocks TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaUdmaRead (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param DataBuffer TODO: add argument description
+ @param StartLba TODO: add argument description
+ @param NumberOfBlocks TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaUdmaWriteExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+;
+
+/**
+ Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer
+ A pointer to the source buffer for the data.
+
+ @param[in] StartLba
+ The starting logical block address to write to
+ on the device media.
+
+ @param[in] NumberOfBlocks
+ The number of transfer data blocks.
+
+ @param[in] UdmaOp
+ The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp,
+ AtaUdmaWriteOp, AtaUdmaWriteExOp
+
+ @return The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+**/
+EFI_STATUS
+DoAtaUdma (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks,
+ IN ATA_UDMA_OPERATION UdmaOp
+ )
+;
+
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param DataBuffer TODO: add argument description
+ @param StartLba TODO: add argument description
+ @param NumberOfBlocks TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaUdmaWrite (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param AtaCommand TODO: add argument description
+ @param Device TODO: add argument description
+ @param Feature TODO: add argument description
+ @param SectorCount TODO: add argument description
+ @param LbaAddress TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaCommandIssueExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param AtaCommand TODO: add argument description
+ @param Device TODO: add argument description
+ @param Feature TODO: add argument description
+ @param SectorCount TODO: add argument description
+ @param LbaAddress TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaCommandIssue (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaAtapi6Identify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+AtaSMARTSupport (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param Buffer TODO: add argument description
+ @param ByteCount TODO: add argument description
+ @param AtaCommand TODO: add argument description
+ @param StartLba TODO: add argument description
+ @param SectorCount TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaPioDataInExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN OUT VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN EFI_LBA StartLba,
+ IN UINT16 SectorCount
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param Buffer TODO: add argument description
+ @param ByteCount TODO: add argument description
+ @param AtaCommand TODO: add argument description
+ @param StartLba TODO: add argument description
+ @param SectorCount TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+AtaPioDataOutExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN EFI_LBA StartLba,
+ IN UINT16 SectorCount
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+ @param DriveParameters TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+SetDriveParameters (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATA_DRIVE_PARMS *DriveParameters
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param IdeDev TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EnableInterrupt (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+;
+
+/**
+ Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
+
+ @param[in] Event Pointer to this event
+ @param[in] Context Event hanlder private data
+
+ @retval EFI_SUCCESS - Interrupt cleared
+
+**/
+VOID
+EFIAPI
+ClearInterrupt (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.c new file mode 100644 index 0000000000..6a43d9cd80 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.c @@ -0,0 +1,1413 @@ +/** @file
+ Copyright (c) 2006 - 2007 Intel Corporation. <BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ This module is modified from DXE\IDE module for Ide Contriller Init support
+
+**/
+
+#include "idebus.h"
+
+#define PCI_CLASS_MASS_STORAGE 0x01
+#define PCI_SUB_CLASS_IDE 0x01
+
+
+//
+// IDE Bus Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = {
+ IDEBusDriverBindingSupported,
+ IDEBusDriverBindingStart,
+ IDEBusDriverBindingStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+//
+// ***********************************************************************************
+// IDEBusDriverBindingSupported
+// ***********************************************************************************
+//
+/**
+ Register Driver Binding protocol for this driver.
+
+ @param[in] This -- A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle -- The handle of the controller to test.
+ @param[in] RemainingDevicePath -- A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS Driver loaded.
+ @retval other Driver not loaded.
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+// TODO: Controller - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_DEV_PATH *Node;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
+
+ if (RemainingDevicePath != NULL) {
+ Node = (EFI_DEV_PATH *) RemainingDevicePath;
+ if (Node->DevPath.Type != MESSAGING_DEVICE_PATH ||
+ Node->DevPath.SubType != MSG_ATAPI_DP ||
+ DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Close protocol, don't use device path protocol in the .Support() function
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Verify the Ide Controller Init Protocol, which installed by the
+ // IdeController module.
+ // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't
+ // open BY_DRIVER here) That's why we don't check pciio protocol
+ // Note 2: ide_init driver check ide controller's pci config space, so we dont
+ // check here any more to save code size
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **) &IdeInit,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If protocols were opened normally, closed it
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+//
+// ***********************************************************************************
+// IDEBusDriverBindingStart
+// ***********************************************************************************
+//
+/**
+ Start this driver on Controller by detecting all disks and installing
+ BlockIo protocol on them.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath Not used, always produce all possible children.
+
+ @retval EFI_SUCCESS This driver is added to ControllerHandle.
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS SavedStatus;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_DEV_PATH *Node;
+ UINT8 IdeChannel;
+ UINT8 BeginningIdeChannel;
+ UINT8 EndIdeChannel;
+ UINT8 IdeDevice;
+ UINT8 BeginningIdeDevice;
+ UINT8 EndIdeDevice;
+ IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice];
+ IDE_BLK_IO_DEV *IdeBlkIoDevicePtr;
+ IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
+ ATA_TRANSFER_MODE TransferMode;
+ ATA_DRIVE_PARMS DriveParameters;
+ EFI_DEV_PATH NewNode;
+ UINT8 ConfigurationOptions;
+ UINT16 CommandBlockBaseAddr;
+ UINT16 ControlBlockBaseAddr;
+ UINTN DataSize;
+ IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
+
+ //
+ // Local variables declaration for IdeControllerInit support
+ //
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
+ BOOLEAN EnumAll;
+ BOOLEAN ChannelEnabled;
+ UINT8 MaxDevices;
+ EFI_IDENTIFY_DATA IdentifyData;
+ EFI_ATA_COLLECTIVE_MODE *SupportedModes;
+
+ IdeBusDriverPrivateData = NULL;
+ SupportedModes = NULL;
+
+ //
+ // Perform IdeBus initialization
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+ return Status;
+ }
+
+ //
+ // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **) &IdeInit,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ //
+ // The following OpenProtocol function with _GET_PROTOCOL attribute and
+ // will not return EFI_ALREADY_STARTED, so save it for now
+ //
+ SavedStatus = Status;
+
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+ DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status));
+ //
+ // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
+ //
+ goto ErrorExit;
+ }
+
+ //
+ // Save Enumall. Step7.2
+ //
+ EnumAll = IdeInit->EnumAll;
+
+ //
+ // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
+ // attribute will not return EFI_ALREADY_STARTED
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status));
+ goto ErrorExit;
+ }
+
+ //
+ // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
+ //
+ if (SavedStatus != EFI_ALREADY_STARTED) {
+ IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
+ if (IdeBusDriverPrivateData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiCallerIdGuid,
+ IdeBusDriverPrivateData,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ } else {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &IdeBusDriverPrivateData,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData = NULL;
+ goto ErrorExit;
+ }
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // Read the environment variable that contains the IDEBus Driver's
+ // Config options that were set by the Driver Configuration Protocol
+ //
+ DataSize = sizeof (ConfigurationOptions);
+ Status = gRT->GetVariable (
+ (CHAR16 *) L"Configuration",
+ &gEfiCallerIdGuid,
+ NULL,
+ &DataSize,
+ &ConfigurationOptions
+ );
+ if (EFI_ERROR (Status)) {
+ ConfigurationOptions = 0x0f;
+ }
+
+ if (EnumAll) {
+ //
+ // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway
+ //
+ BeginningIdeChannel = IdePrimary;
+ EndIdeChannel = IdeSecondary;
+ BeginningIdeDevice = IdeMaster;
+ EndIdeDevice = IdeSlave;
+ } else if (RemainingDevicePath == NULL) {
+ //
+ // RemainingDevicePath is NULL, scan IDE bus for each device;
+ //
+ BeginningIdeChannel = IdePrimary;
+ EndIdeChannel = IdeSecondary;
+ BeginningIdeDevice = IdeMaster;
+ //
+ // default, may be redefined by IdeInit
+ //
+ EndIdeDevice = IdeSlave;
+ } else {
+ //
+ // RemainingDevicePath is not NULL, only scan the specified device.
+ //
+ Node = (EFI_DEV_PATH *) RemainingDevicePath;
+ BeginningIdeChannel = Node->Atapi.PrimarySecondary;
+ EndIdeChannel = BeginningIdeChannel;
+ BeginningIdeDevice = Node->Atapi.SlaveMaster;
+ EndIdeDevice = BeginningIdeDevice;
+ }
+
+ //
+ // Obtain IDE IO port registers' base addresses
+ //
+ Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // Report status code: begin IdeBus initialization
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
+ ParentDevicePath
+ );
+
+ //
+ // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
+ //
+ for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
+
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);
+
+ //
+ // now obtain channel information fron IdeControllerInit protocol. Step9
+ //
+ Status = IdeInit->GetChannelInfo (
+ IdeInit,
+ IdeChannel,
+ &ChannelEnabled,
+ &MaxDevices
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));
+ continue;
+ }
+
+ if (!ChannelEnabled) {
+ continue;
+ }
+
+ EndIdeDevice = (UINT8) EFI_MIN ((MaxDevices - 1), EndIdeDevice);
+
+ //
+ // Now inform the IDE Controller Init Module. Sept10
+ //
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);
+
+ //
+ // No reset channel function implemented. Sept11
+ //
+ IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);
+
+ //
+ // Step13
+ //
+ IdeInit->NotifyPhase (
+ IdeInit,
+ EfiIdeBusBeforeDevicePresenceDetection,
+ IdeChannel
+ );
+
+ //
+ // Prepare to detect IDE device of this channel
+ //
+ InitializeIDEChannelData ();
+
+ //
+ // -- 1st inner loop --- Master/Slave ------------ Step14
+ //
+ for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
+ //
+ // Check whether the configuration options allow this device
+ //
+ if (!(ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice)))) {
+ continue;
+ }
+
+ //
+ // The device has been scanned in another Start(), No need to scan it again
+ // for perf optimization.
+ //
+ if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) {
+ continue;
+ }
+
+ //
+ // create child handle for the detected device.
+ //
+ IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV));
+ if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) {
+ continue;
+ }
+
+ IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
+
+ ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV));
+
+ IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE;
+ IdeBlkIoDevicePtr->Channel = (EFI_IDE_CHANNEL) IdeChannel;
+ IdeBlkIoDevicePtr->Device = (EFI_IDE_DEVICE) IdeDevice;
+
+ //
+ // initialize Block IO interface's Media pointer
+ //
+ IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia;
+
+ //
+ // Initialize IDE IO port addresses, including Command Block registers
+ // and Control Block registers
+ //
+ IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS));
+ if (IdeBlkIoDevicePtr->IoPort == NULL) {
+ continue;
+ }
+
+ ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS));
+ CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;
+ ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;
+
+ IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr;
+ (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
+ IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
+ IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
+ IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
+ IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
+ IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
+ (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
+
+ (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr;
+ IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
+
+ IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0);
+
+ IdeBlkIoDevicePtr->PciIo = PciIo;
+ IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;
+ IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;
+
+ //
+ // Report Status code: is about to detect IDE drive
+ //
+ REPORT_STATUS_CODE_EX (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),
+ 0,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL,
+ 0
+ );
+
+ //
+ // Discover device, now!
+ //
+ PERF_START (0, "DiscoverIdeDevice", "IDE", 0);
+ Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);
+ PERF_END (0, "DiscoverIdeDevice", "IDE", 0);
+
+ IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE;
+ IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE;
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set Device Path
+ //
+ ZeroMem (&NewNode, sizeof (NewNode));
+ NewNode.DevPath.Type = MESSAGING_DEVICE_PATH;
+ NewNode.DevPath.SubType = MSG_ATAPI_DP;
+ SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH));
+
+ NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel;
+ NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device;
+ NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun;
+ IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode (
+ ParentDevicePath,
+ &NewNode.DevPath
+ );
+ if (IdeBlkIoDevicePtr->DevicePath == NULL) {
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ continue;
+ }
+
+ //
+ // Submit identify data to IDE controller init driver
+ //
+ CopyMem (&IdentifyData, IdeBlkIoDevicePtr->pIdData, sizeof (IdentifyData));
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;
+ IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);
+ } else {
+ //
+ // Device detection failed
+ //
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL);
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ }
+ //
+ // end of 1st inner loop ---
+ //
+ }
+ //
+ // end of 1st outer loop =========
+ //
+ }
+
+ //
+ // = 2nd outer loop == Primary/Secondary =================
+ //
+ for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
+
+ //
+ // -- 2nd inner loop --- Master/Slave --------
+ //
+ for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
+
+ if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) {
+ continue;
+ }
+
+ if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) {
+ continue;
+ }
+
+ Status = IdeInit->CalculateMode (
+ IdeInit,
+ IdeChannel,
+ IdeDevice,
+ &SupportedModes
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status));
+ continue;
+ }
+
+ IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
+
+ //
+ // Set best supported PIO mode on this IDE device
+ //
+ if (SupportedModes->PioMode.Mode <= ATA_PIO_MODE_2) {
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO;
+ } else {
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO;
+ }
+
+ TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
+
+ if (SupportedModes->ExtModeCount == 0){
+ Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ continue;
+ }
+ }
+
+ //
+ // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
+ // be set together. Only one DMA mode can be set to a device. If setting
+ // DMA mode operation fails, we can continue moving on because we only use
+ // PIO mode at boot time. DMA modes are used by certain kind of OS booting
+ //
+ if (SupportedModes->UdmaMode.Valid) {
+
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA;
+ TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
+ Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ continue;
+ }
+ //
+ // Record Udma Mode
+ //
+ IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE;
+ IdeBlkIoDevicePtr->UdmaMode.Mode = SupportedModes->UdmaMode.Mode;
+ EnableInterrupt (IdeBlkIoDevicePtr);
+ } else if (SupportedModes->MultiWordDmaMode.Valid) {
+
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA;
+ TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
+ Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ continue;
+ }
+
+ EnableInterrupt (IdeBlkIoDevicePtr);
+ }
+ //
+ // Init driver parameters
+ //
+ DriveParameters.Sector = (UINT8) IdeBlkIoDevicePtr->pIdData->AtaData.sectors_per_track;
+ DriveParameters.Heads = (UINT8) (IdeBlkIoDevicePtr->pIdData->AtaData.heads - 1);
+ DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->pIdData->AtaData.multi_sector_cmd_max_sct_cnt;
+ //
+ // Set Parameters for the device:
+ // 1) Init
+ // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
+ //
+ if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) {
+ Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters);
+ }
+
+ //
+ // Record PIO mode used in private data
+ //
+ IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode;
+
+ //
+ // Set IDE controller Timing Blocks in the PCI Configuration Space
+ //
+ IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);
+
+ //
+ // Add Component Name for the IDE/ATAPI device that was discovered.
+ //
+ IdeBlkIoDevicePtr->ControllerNameTable = NULL;
+ ADD_NAME (IdeBlkIoDevicePtr);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &IdeBlkIoDevicePtr->Handle,
+ &gEfiDevicePathProtocolGuid,
+ IdeBlkIoDevicePtr->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &IdeBlkIoDevicePtr->BlkIo,
+ &gEfiDiskInfoProtocolGuid,
+ &IdeBlkIoDevicePtr->DiskInfo,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ }
+
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ IdeBlkIoDevicePtr->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE;
+
+ //
+ // Report status code: device eanbled!
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE),
+ IdeBlkIoDevicePtr->DevicePath
+ );
+
+ //
+ // Create event to clear pending IDE interrupt
+ //
+ Status = gBS->CreateEvent (
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_NOTIFY,
+ ClearInterrupt,
+ IdeBlkIoDevicePtr,
+ &IdeBlkIoDevicePtr->ExitBootServiceEvent
+ );
+
+ //
+ // end of 2nd inner loop ----
+ //
+ }
+ //
+ // end of 2nd outer loop ==========
+ //
+ }
+
+ //
+ // All configurations done! Notify IdeController to do post initialization
+ // work such as saving IDE controller PCI settings for S3 resume
+ //
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);
+
+ if (SupportedModes != NULL) {
+ gBS->FreePool (SupportedModes);
+ }
+
+ PERF_START (0, "Finish IDE detection", "IDE", 1);
+ PERF_END (0, "Finish IDE detection", "IDE", 0);
+
+ return EFI_SUCCESS;
+
+ErrorExit:
+
+ //
+ // Report error code: controller error
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR),
+ ParentDevicePath
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ IdeBusDriverPrivateData,
+ NULL
+ );
+
+ if (IdeBusDriverPrivateData != NULL) {
+ gBS->FreePool (IdeBusDriverPrivateData);
+ }
+
+ if (SupportedModes != NULL) {
+ gBS->FreePool (SupportedModes);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+
+}
+
+//
+// ***********************************************************************************
+// IDEBusDriverBindingStop
+// ***********************************************************************************
+//
+/**
+ Stop this driver on Controller Handle.
+
+ @param This Protocol instance pointer.
+ @param DeviceHandle Handle of device to stop driver on
+ @param NumberOfChildren Not used
+ @param ChildHandleBuffer Not used
+
+ @retval EFI_SUCCESS This driver is removed DeviceHandle
+ @retval other This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+// TODO: Controller - add argument and description to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+ IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
+
+ IdeBusDriverPrivateData = NULL;
+
+ if (NumberOfChildren == 0) {
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ }
+
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &IdeBusDriverPrivateData,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ IdeBusDriverPrivateData,
+ NULL
+ );
+
+ if (IdeBusDriverPrivateData != NULL) {
+ gBS->FreePool (IdeBusDriverPrivateData);
+ }
+ //
+ // Close the bus driver
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]);
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// ***********************************************************************************
+// DeRegisterIdeDevice
+// ***********************************************************************************
+//
+/**
+ Deregister an IDE device and free resources
+
+ @param This Protocol instance pointer.
+ @param Controller Ide device handle
+ @param Handle Handle of device to deregister driver on
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+DeRegisterIdeDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ )
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Index;
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
+
+ //
+ // Report Status code: Device disabled
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE),
+ IdeBlkIoDevice->DevicePath
+ );
+
+ //
+ // Close the child handle
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Handle
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ IdeBlkIoDevice->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &IdeBlkIoDevice->BlkIo,
+ &gEfiDiskInfoProtocolGuid,
+ &IdeBlkIoDevice->DiskInfo,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+
+ //
+ // Release allocated resources
+ //
+ Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device;
+ IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE;
+
+ ReleaseIdeResources (IdeBlkIoDevice);
+
+ return EFI_SUCCESS;
+}
+
+//
+// ***********************************************************************************
+// IDEBlkIoReset
+// ***********************************************************************************
+//
+/**
+ TODO: This - add argument and description to function comment
+ TODO: ExtendedVerification - add argument and description to function comment
+ TODO: EFI_DEVICE_ERROR - add return value to function comment
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+ //
+ // Requery IDE IO resources in case of the switch of native and legacy modes
+ //
+ ReassignIdeResources (IdeBlkIoDevice);
+
+ //
+ // for ATA device, using ATA reset method
+ //
+ if (IdeBlkIoDevice->Type == IdeHardDisk ||
+ IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+ Status = AtaSoftReset (IdeBlkIoDevice);
+ goto Done;
+ }
+
+ if (IdeBlkIoDevice->Type == IdeUnknown) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // for ATAPI device, using ATAPI reset method
+ //
+ Status = AtapiSoftReset (IdeBlkIoDevice);
+ if (ExtendedVerification) {
+ Status = AtaSoftReset (IdeBlkIoDevice);
+ }
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Read data from block io device
+
+ @param This Protocol instance pointer.
+ @param MediaId The media ID of the device
+ @param LBA Starting LBA address to read data
+ @param BufferSize The size of data to be read
+ @param Buffer Caller supplied buffer to save data
+
+ @return read data status
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+
+ //
+ // Requery IDE IO resources in case of the switch of native and legacy modes
+ //
+ ReassignIdeResources (IdeBlkIoDevice);
+
+ //
+ // For ATA compatible device, use ATA read block's mechanism
+ //
+ if (IdeBlkIoDevice->Type == IdeHardDisk ||
+ IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+ Status = AtaBlkIoReadBlocks (
+ IdeBlkIoDevice,
+ MediaId,
+ LBA,
+ BufferSize,
+ Buffer
+ );
+ goto Done;
+ }
+
+ if (IdeBlkIoDevice->Type == IdeUnknown) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // for ATAPI device, using ATAPI read block's mechanism
+ //
+ Status = AtapiBlkIoReadBlocks (
+ IdeBlkIoDevice,
+ MediaId,
+ LBA,
+ BufferSize,
+ Buffer
+ );
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+ Write data to block io device
+
+ @param This Protocol instance pointer.
+ @param MediaId The media ID of the device
+ @param LBA Starting LBA address to write data
+ @param BufferSize The size of data to be written
+ @param Buffer Caller supplied buffer to save data
+
+ @return write data status
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+ //
+ // Requery IDE IO resources in case of the switch of native and legacy modes
+ //
+ ReassignIdeResources (IdeBlkIoDevice);
+
+ //
+ // for ATA device, using ATA write block's mechanism
+ //
+ if (IdeBlkIoDevice->Type == IdeHardDisk ||
+ IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+
+ Status = AtaBlkIoWriteBlocks (
+ IdeBlkIoDevice,
+ MediaId,
+ LBA,
+ BufferSize,
+ Buffer
+ );
+ goto Done;
+ }
+
+ if (IdeBlkIoDevice->Type == IdeUnknown) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // for ATAPI device, using ATAPI write block's mechanism
+ //
+ Status = AtapiBlkIoWriteBlocks (
+ IdeBlkIoDevice,
+ MediaId,
+ LBA,
+ BufferSize,
+ Buffer
+ );
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+//
+// ***********************************************************************************
+// IDEBlkIoFlushBlocks
+// ***********************************************************************************
+//
+/**
+ TODO: This - add argument and description to function comment
+ TODO: EFI_SUCCESS - add return value to function comment
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ //
+ // return directly
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the results of the Inquiry command to a drive in InquiryData.
+ Data format of Inquiry data is defined by the Interface GUID.
+
+ @param This Protocol instance pointer.
+ @param InquiryData Results of Inquiry command to device
+ @param InquiryDataSize Size of InquiryData in bytes.
+
+ @retval EFI_SUCCESS InquiryData valid
+ @retval EFI_NOT_FOUND Device does not support this data class
+ @retval EFI_DEVICE_ERROR Error reading InquiryData from device
+ @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *InquiryDataSize
+ )
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+
+ if (*InquiryDataSize < sizeof (INQUIRY_DATA)) {
+ *InquiryDataSize = sizeof (INQUIRY_DATA);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (IdeBlkIoDevice->pInquiryData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ gBS->CopyMem (InquiryData, IdeBlkIoDevice->pInquiryData, sizeof (INQUIRY_DATA));
+ *InquiryDataSize = sizeof (INQUIRY_DATA);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the results of the Identify command to a drive in IdentifyData.
+ Data format of Identify data is defined by the Interface GUID.
+
+ @param This Protocol instance pointer.
+ @param IdentifyData Results of Identify command to device
+ @param IdentifyDataSize Size of IdentifyData in bytes.
+
+ @retval EFI_SUCCESS IdentifyData valid
+ @retval EFI_NOT_FOUND Device does not support this data class
+ @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
+ @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoIdentify (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+ )
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+
+ if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) {
+ *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (IdeBlkIoDevice->pIdData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ gBS->CopyMem (IdentifyData, IdeBlkIoDevice->pIdData, sizeof (EFI_IDENTIFY_DATA));
+ *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the results of the Request Sense command to a drive in SenseData.
+ Data format of Sense data is defined by the Interface GUID.
+
+ @param This Protocol instance pointer.
+ @param SenseData Results of Request Sense command to device
+ @param SenseDataSize Size of SenseData in bytes.
+ @param SenseDataNumber Type of SenseData
+
+ @retval EFI_SUCCESS InquiryData valid
+ @retval EFI_NOT_FOUND Device does not support this data class
+ @retval EFI_DEVICE_ERROR Error reading InquiryData from device
+ @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoSenseData (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *SenseData,
+ IN OUT UINT32 *SenseDataSize,
+ OUT UINT8 *SenseDataNumber
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Return the results of the Request Sense command to a drive in SenseData.
+ Data format of Sense data is defined by the Interface GUID.
+
+ @param This Protocol instance pointer.
+ @param IdeChannel Primary or Secondary
+ @param IdeDevice Master or Slave
+
+ @retval EFI_SUCCESS IdeChannel and IdeDevice are valid
+ @retval EFI_UNSUPPORTED This is not an IDE device
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoWhichIde (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+ )
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+ *IdeChannel = IdeBlkIoDevice->Channel;
+ *IdeDevice = IdeBlkIoDevice->Device;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The user Entry Point for module IdeBus. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeIdeBus(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallAllDriverProtocols (
+ ImageHandle,
+ SystemTable,
+ &gIDEBusDriverBinding,
+ ImageHandle,
+ &gIDEBusComponentName,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h new file mode 100644 index 0000000000..a0c90fd3a7 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h @@ -0,0 +1,420 @@ +/** @file
+ Header file for IDE Bus Driver.
+
+ Copyright (c) 2006 - 2007 Intel Corporation. <BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _IDE_BUS_H
+#define _IDE_BUS_H
+
+
+//
+// The package level header files this module uses
+//
+#include <PiDxe.h>
+#include <Common/FrameworkStatusCode.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/IdeControllerInit.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/DiskInfo.h>
+#include <Protocol/DevicePath.h>
+//
+// The Library classes this module consumes
+//
+#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/PerformanceLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <IndustryStandard/pci22.h>
+#include "idedata.h"
+
+//
+// Extra Definition to porting
+//
+#define EFI_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+#define MAX_IDE_DEVICE 4
+#define MAX_IDE_CHANNELS 2
+#define MAX_IDE_DRIVES 2
+
+#define INVALID_DEVICE_TYPE 0xff
+#define ATA_DEVICE_TYPE 0x00
+#define ATAPI_DEVICE_TYPE 0x01
+
+typedef struct {
+ BOOLEAN HaveScannedDevice[MAX_IDE_DEVICE];
+ BOOLEAN DeviceFound[MAX_IDE_DEVICE];
+ BOOLEAN DeviceProcessed[MAX_IDE_DEVICE];
+} IDE_BUS_DRIVER_PRIVATE_DATA;
+
+#define IDE_BLK_IO_DEV_SIGNATURE EFI_SIGNATURE_32 ('i', 'b', 'i', 'd')
+
+typedef struct {
+ UINT32 Signature;
+
+ EFI_HANDLE Handle;
+ EFI_BLOCK_IO_PROTOCOL BlkIo;
+ EFI_BLOCK_IO_MEDIA BlkMedia;
+ EFI_DISK_INFO_PROTOCOL DiskInfo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
+
+ //
+ // Local Data for IDE interface goes here
+ //
+ EFI_IDE_CHANNEL Channel;
+ EFI_IDE_DEVICE Device;
+ UINT16 Lun;
+ IDE_DEVICE_TYPE Type;
+
+ IDE_BASE_REGISTERS *IoPort;
+ UINT16 AtapiError;
+
+ INQUIRY_DATA *pInquiryData;
+ EFI_IDENTIFY_DATA *pIdData;
+ ATA_PIO_MODE PioMode;
+ EFI_ATA_MODE UdmaMode;
+ CHAR8 ModelName[41];
+ REQUEST_SENSE_DATA *SenseData;
+ UINT8 SenseDataNumber;
+ UINT8 *Cache;
+
+ //
+ // ExitBootService Event, it is used to clear pending IDE interrupt
+ //
+ EFI_EVENT ExitBootServiceEvent;
+
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+} IDE_BLK_IO_DEV;
+
+#include "ComponentName.h"
+
+#define IDE_BLOCK_IO_DEV_FROM_THIS(a) CR (a, IDE_BLK_IO_DEV, BlkIo, IDE_BLK_IO_DEV_SIGNATURE)
+#define IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS(a) CR (a, IDE_BLK_IO_DEV, DiskInfo, IDE_BLK_IO_DEV_SIGNATURE)
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding;
+
+#include "ide.h"
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+/**
+ TODO: Add function description
+
+ @param ImageHandle TODO: add argument description
+ @param SystemTable TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusControllerDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param Controller TODO: add argument description
+ @param RemainingDevicePath TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param Controller TODO: add argument description
+ @param RemainingDevicePath TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param Controller TODO: add argument description
+ @param NumberOfChildren TODO: add argument description
+ @param ChildHandleBuffer TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+;
+
+//
+// EFI Driver Configuration Functions
+//
+EFI_STATUS
+IDEBusDriverConfigurationSetOptions (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired
+ );
+
+EFI_STATUS
+IDEBusDriverConfigurationOptionsValid (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL
+ );
+
+EFI_STATUS
+IDEBusDriverConfigurationForceDefaults (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN UINT32 DefaultType,
+ OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired
+ );
+
+//
+// EFI Driver Diagnostics Functions
+//
+EFI_STATUS
+IDEBusDriverDiagnosticsRunDiagnostics (
+ IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,
+ IN CHAR8 *Language,
+ OUT EFI_GUID **ErrorType,
+ OUT UINTN *BufferSize,
+ OUT CHAR16 **Buffer
+ );
+
+//
+// Block I/O Protocol Interface
+//
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param ExtendedVerification TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param MediaId TODO: add argument description
+ @param LBA TODO: add argument description
+ @param BufferSize TODO: add argument description
+ @param Buffer TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param MediaId TODO: add argument description
+ @param LBA TODO: add argument description
+ @param BufferSize TODO: add argument description
+ @param Buffer TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param PciIo TODO: add argument description
+ @param Enable TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+IDERegisterDecodeEnableorDisable (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN BOOLEAN Enable
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param InquiryData TODO: add argument description
+ @param IntquiryDataSize TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *IntquiryDataSize
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param IdentifyData TODO: add argument description
+ @param IdentifyDataSize TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoIdentify (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param SenseData TODO: add argument description
+ @param SenseDataSize TODO: add argument description
+ @param SenseDataNumber TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoSenseData (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *SenseData,
+ IN OUT UINT32 *SenseDataSize,
+ OUT UINT8 *SenseDataNumber
+ )
+;
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param IdeChannel TODO: add argument description
+ @param IdeDevice TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoWhichIde (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+ )
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.inf b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.inf new file mode 100644 index 0000000000..ecbb1623fd --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.inf @@ -0,0 +1,135 @@ +#/** @file
+# Component description file for PS2 keyboard module.
+#
+# IDE bus driver. This driver will enumerate IDE device and export the blockIo
+# protocol for every device.
+# Copyright (c) 2006 - 2007, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IdeBus
+ FILE_GUID = 69FD8E47-A161-4550-B01A-5594CEB2B2B2
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeIdeBus
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gIDEBusDriverBinding
+# COMPONENT_NAME = gIDEBusComponentName
+# Variable Guid C Name: gConfigurationGuid Variable Name: L"Configuration"
+#
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ DriverDiagnostics.c
+ DriverConfiguration.c
+ ComponentName.h
+ ComponentName.c
+ atapi.c
+ ata.c
+ ide.c
+ idebus.c
+ idedata.h
+ ide.h
+ idebus.h
+
+
+################################################################################
+#
+# Includes Section - list of Include locations that are required for
+# this module.
+#
+################################################################################
+
+[Includes]
+ $(WORKSPACE)/MdePkg/Include
+ $(WORKSPACE)/MdeModulePkg/Include
+ $(WORKSPACE)/IntelFrameworkPkg/Include
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ DevicePathLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PerformanceLib
+ MemoryAllocationLib
+ ReportStatusCodeLib
+ BaseMemoryLib
+ UefiLib
+ BaseLib
+ UefiDriverEntryPoint
+ DebugLib
+
+
+################################################################################
+#
+# Guid C Name Section - list of Guids that this module uses or produces.
+#
+################################################################################
+
+[Guids]
+ gEfiDiskInfoIdeInterfaceGuid # SOMETIMES_CONSUMED
+
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+
+[Protocols]
+ gEfiDiskInfoProtocolGuid # PROTOCOL BY_START
+ gEfiBlockIoProtocolGuid # PROTOCOL BY_START
+ gEfiIdeControllerInitProtocolGuid # PROTOCOL TO_START
+ gEfiPciIoProtocolGuid # PROTOCOL TO_START
+ gEfiDevicePathProtocolGuid # PROTOCOL TO_START
+
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa new file mode 100644 index 0000000000..7d8e9ad259 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>IdeBus</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>69FD8E47-A161-4550-B01A-5594CEB2B2B2</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for PS2 keyboard module.</Abstract>
+ <Description>IDE bus driver. This driver will enumerate IDE device and export the blockIo
+ protocol for every device.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>IdeBus</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>ReportStatusCodeLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PerformanceLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DevicePathLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>idebus.h</Filename>
+ <Filename>ide.h</Filename>
+ <Filename>idedata.h</Filename>
+ <Filename>idebus.c</Filename>
+ <Filename>ide.c</Filename>
+ <Filename>ata.c</Filename>
+ <Filename>atapi.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ <Filename>ComponentName.h</Filename>
+ <Filename>DriverConfiguration.c</Filename>
+ <Filename>DriverDiagnostics.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="1E73767F-8F52-4603-AEB4-F29B510B6766"/>
+ <Package PackageGuid="2759ded5-bb57-4b06-af4f-c398fa552719"/>
+ <Package PackageGuid="BA0D78D6-2CAF-414b-BD4D-B6762A894288"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiPciIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiIdeControllerInitProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="BY_START">
+ <ProtocolCName>gEfiBlockIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="BY_START">
+ <ProtocolCName>gEfiDiskInfoProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Variables>
+ <Variable Usage="ALWAYS_CONSUMED">
+ <VariableName>0x0043 0x006F 0x006E 0x0066 0x0069 0x0067 0x0075 0x0072 0x0061 0x0074 0x0069 0x006F 0x006E</VariableName>
+ <GuidC_Name>gConfigurationGuid</GuidC_Name>
+ </Variable>
+ </Variables>
+ <Guids>
+ <GuidCNames Usage="SOMETIMES_CONSUMED">
+ <GuidCName>gEfiDiskInfoIdeInterfaceGuid</GuidCName>
+ </GuidCNames>
+ </Guids>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <DriverBinding>gIDEBusDriverBinding</DriverBinding>
+ <ComponentName>gIDEBusComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h new file mode 100644 index 0000000000..277e74fcc0 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h @@ -0,0 +1,893 @@ +/** @file
+ Header file for IDE Bus Driver's Data Structures
+
+ Copyright (c) 2006 - 2007 Intel Corporation. <BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _IDE_DATA_H
+#define _IDE_DATA_H
+
+//
+// bit definition
+//
+#define bit0 (1 << 0)
+#define bit1 (1 << 1)
+#define bit2 (1 << 2)
+#define bit3 (1 << 3)
+#define bit4 (1 << 4)
+#define bit5 (1 << 5)
+#define bit6 (1 << 6)
+#define bit7 (1 << 7)
+#define bit8 (1 << 8)
+#define bit9 (1 << 9)
+#define bit10 (1 << 10)
+#define bit11 (1 << 11)
+#define bit12 (1 << 12)
+#define bit13 (1 << 13)
+#define bit14 (1 << 14)
+#define bit15 (1 << 15)
+#define bit16 (1 << 16)
+#define bit17 (1 << 17)
+#define bit18 (1 << 18)
+#define bit19 (1 << 19)
+#define bit20 (1 << 20)
+#define bit21 (1 << 21)
+#define bit22 (1 << 22)
+#define bit23 (1 << 23)
+#define bit24 (1 << 24)
+#define bit25 (1 << 25)
+#define bit26 (1 << 26)
+#define bit27 (1 << 27)
+#define bit28 (1 << 28)
+#define bit29 (1 << 29)
+#define bit30 (1 << 30)
+#define bit31 (1 << 31)
+
+//
+// common constants
+//
+#define STALL_1_MILLI_SECOND 1000 // stall 1 ms
+#define STALL_1_SECOND 1000000 // stall 1 second
+typedef enum {
+ IdePrimary = 0,
+ IdeSecondary = 1,
+ IdeMaxChannel = 2
+} EFI_IDE_CHANNEL;
+
+typedef enum {
+ IdeMaster = 0,
+ IdeSlave = 1,
+ IdeMaxDevice = 2
+} EFI_IDE_DEVICE;
+
+typedef enum {
+ IdeMagnetic, /* ZIP Drive or LS120 Floppy Drive */
+ IdeCdRom, /* ATAPI CDROM */
+ IdeHardDisk, /* Hard Disk */
+ Ide48bitAddressingHardDisk, /* Hard Disk larger than 120GB */
+ IdeUnknown
+} IDE_DEVICE_TYPE;
+
+typedef enum {
+ SenseNoSenseKey,
+ SenseDeviceNotReadyNoRetry,
+ SenseDeviceNotReadyNeedRetry,
+ SenseNoMedia,
+ SenseMediaChange,
+ SenseMediaError,
+ SenseOtherSense
+} SENSE_RESULT;
+
+typedef enum {
+ AtaUdmaReadOp,
+ AtaUdmaReadExtOp,
+ AtaUdmaWriteOp,
+ AtaUdmaWriteExtOp
+} ATA_UDMA_OPERATION;
+
+//
+// IDE Registers
+//
+typedef union {
+ UINT16 Command; /* when write */
+ UINT16 Status; /* when read */
+} IDE_CMD_OR_STATUS;
+
+typedef union {
+ UINT16 Error; /* when read */
+ UINT16 Feature; /* when write */
+} IDE_ERROR_OR_FEATURE;
+
+typedef union {
+ UINT16 AltStatus; /* when read */
+ UINT16 DeviceControl; /* when write */
+} IDE_AltStatus_OR_DeviceControl;
+
+//
+// IDE registers set
+//
+typedef struct {
+ UINT16 Data;
+ IDE_ERROR_OR_FEATURE Reg1;
+ UINT16 SectorCount;
+ UINT16 SectorNumber;
+ UINT16 CylinderLsb;
+ UINT16 CylinderMsb;
+ UINT16 Head;
+ IDE_CMD_OR_STATUS Reg;
+
+ IDE_AltStatus_OR_DeviceControl Alt;
+ UINT16 DriveAddress;
+
+ UINT16 MasterSlave;
+ UINT16 BusMasterBaseAddr;
+} IDE_BASE_REGISTERS;
+
+//
+// IDE registers' base addresses
+//
+typedef struct {
+ UINT16 CommandBlockBaseAddr;
+ UINT16 ControlBlockBaseAddr;
+ UINT16 BusMasterBaseAddr;
+} IDE_REGISTERS_BASE_ADDR;
+
+//
+// Bit definitions in Programming Interface byte of the Class Code field
+// in PCI IDE controller's Configuration Space
+//
+#define IDE_PRIMARY_OPERATING_MODE bit0
+#define IDE_PRIMARY_PROGRAMMABLE_INDICATOR bit1
+#define IDE_SECONDARY_OPERATING_MODE bit2
+#define IDE_SECONDARY_PROGRAMMABLE_INDICATOR bit3
+
+//
+// IDE registers bit definitions
+//
+
+//
+// Err Reg
+//
+#define BBK_ERR bit7 /* Bad block detected */
+#define UNC_ERR bit6 /* Uncorrectable Data */
+#define MC_ERR bit5 /* Media Change */
+#define IDNF_ERR bit4 /* ID Not Found */
+#define MCR_ERR bit3 /* Media Change Requested */
+#define ABRT_ERR bit2 /* Aborted Command */
+#define TK0NF_ERR bit1 /* Track 0 Not Found */
+#define AMNF_ERR bit0 /* Address Mark Not Found */
+
+//
+// Device/Head Reg
+//
+#define LBA_MODE bit6
+#define DEV bit4
+#define HS3 bit3
+#define HS2 bit2
+#define HS1 bit1
+#define HS0 bit0
+#define CHS_MODE (0)
+#define DRV0 (0)
+#define DRV1 (1)
+#define MST_DRV DRV0
+#define SLV_DRV DRV1
+
+//
+// Status Reg
+//
+#define BSY bit7 /* Controller Busy */
+#define DRDY bit6 /* Drive Ready */
+#define DWF bit5 /* Drive Write Fault */
+#define DSC bit4 /* Disk Seek Complete */
+#define DRQ bit3 /* Data Request */
+#define CORR bit2 /* Corrected Data */
+#define IDX bit1 /* Index */
+#define ERR bit0 /* Error */
+
+//
+// Device Control Reg
+//
+#define SRST bit2 /* Software Reset */
+#define IEN_L bit1 /* Interrupt Enable #*/
+
+//
+// Bus Master Reg
+//
+#define BMIC_nREAD bit3
+#define BMIC_START bit0
+#define BMIS_INTERRUPT bit2
+#define BMIS_ERROR bit1
+
+#define BMICP_OFFSET 0x00
+#define BMISP_OFFSET 0x02
+#define BMIDP_OFFSET 0x04
+#define BMICS_OFFSET 0x08
+#define BMISS_OFFSET 0x0A
+#define BMIDS_OFFSET 0x0C
+
+//
+// Time Out Value For IDE Device Polling
+//
+
+//
+// ATATIMEOUT is used for waiting time out for ATA device
+//
+
+//
+// 1 second
+//
+#define ATATIMEOUT 1000
+
+//
+// ATAPITIMEOUT is used for waiting operation
+// except read and write time out for ATAPI device
+//
+
+//
+// 1 second
+//
+#define ATAPITIMEOUT 1000
+
+//
+// ATAPILONGTIMEOUT is used for waiting read and
+// write operation timeout for ATAPI device
+//
+
+//
+// 2 seconds
+//
+#define CDROMLONGTIMEOUT 2000
+
+//
+// 5 seconds
+//
+#define ATAPILONGTIMEOUT 5000
+
+//
+// 10 seconds
+//
+#define ATASMARTTIMEOUT 10000
+
+//
+// ATA Commands Code
+//
+#define ATA_INITIALIZE_DEVICE 0x91
+
+//
+// Class 1
+//
+#define IDENTIFY_DRIVE_CMD 0xec
+#define READ_BUFFER_CMD 0xe4
+#define READ_SECTORS_CMD 0x20
+#define READ_SECTORS_WITH_RETRY_CMD 0x21
+#define READ_LONG_CMD 0x22
+#define READ_LONG_WITH_RETRY_CMD 0x23
+//
+// Class 1 - Atapi6 enhanced commands
+//
+#define READ_SECTORS_EXT_CMD 0x24
+
+//
+// Class 2
+//
+#define FORMAT_TRACK_CMD 0x50
+#define WRITE_BUFFER_CMD 0xe8
+#define WRITE_SECTORS_CMD 0x30
+#define WRITE_SECTORS_WITH_RETRY_CMD 0x31
+#define WRITE_LONG_CMD 0x32
+#define WRITE_LONG_WITH_RETRY_CMD 0x33
+#define WRITE_VERIFY_CMD 0x3c
+//
+// Class 2 - Atapi6 enhanced commands
+//
+#define WRITE_SECTORS_EXT_CMD 0x34
+
+//
+// Class 3
+//
+#define ACK_MEDIA_CHANGE_CMD 0xdb
+#define BOOT_POST_BOOT_CMD 0xdc
+#define BOOT_PRE_BOOT_CMD 0xdd
+#define CHECK_POWER_MODE_CMD 0x98
+#define CHECK_POWER_MODE_CMD_ALIAS 0xe5
+#define DOOR_LOCK_CMD 0xde
+#define DOOR_UNLOCK_CMD 0xdf
+#define EXEC_DRIVE_DIAG_CMD 0x90
+#define IDLE_CMD_ALIAS 0x97
+#define IDLE_CMD 0xe3
+#define IDLE_IMMEDIATE_CMD 0x95
+#define IDLE_IMMEDIATE_CMD_ALIAS 0xe1
+#define INIT_DRIVE_PARAM_CMD 0x91
+#define RECALIBRATE_CMD 0x10 /* aliased to 1x */
+#define READ_DRIVE_STATE_CMD 0xe9
+#define SET_MULTIPLE_MODE_CMD 0xC6
+#define READ_DRIVE_STATE_CMD 0xe9
+#define READ_VERIFY_CMD 0x40
+#define READ_VERIFY_WITH_RETRY_CMD 0x41
+#define SEEK_CMD 0x70 /* aliased to 7x */
+#define SET_FEATURES_CMD 0xef
+#define STANDBY_CMD 0x96
+#define STANDBY_CMD_ALIAS 0xe2
+#define STANDBY_IMMEDIATE_CMD 0x94
+#define STANDBY_IMMEDIATE_CMD_ALIAS 0xe0
+
+//
+// Class 4
+//
+#define READ_DMA_CMD 0xc8
+#define READ_DMA_WITH_RETRY_CMD 0xc9
+#define READ_DMA_EXT_CMD 0x25
+#define WRITE_DMA_CMD 0xca
+#define WRITE_DMA_WITH_RETRY_CMD 0xcb
+#define WRITE_DMA_EXT_CMD 0x35
+
+//
+// Class 5
+//
+#define READ_MULTIPLE_CMD 0xc4
+#define REST_CMD 0xe7
+#define RESTORE_DRIVE_STATE_CMD 0xea
+#define SET_SLEEP_MODE_CMD 0x99
+#define SET_SLEEP_MODE_CMD_ALIAS 0xe6
+#define WRITE_MULTIPLE_CMD 0xc5
+#define WRITE_SAME_CMD 0xe9
+
+//
+// Class 6 - Host protected area access feature set
+//
+#define READ_NATIVE_MAX_ADDRESS_CMD 0xf8
+#define SET_MAX_ADDRESS_CMD 0xf9
+
+//
+// Class 6 - ATA/ATAPI-6 enhanced commands
+//
+#define READ_NATIVE_MAX_ADDRESS_EXT_CMD 0x27
+#define SET_MAX_ADDRESS_CMD_EXT 0x37
+
+//
+// Class 6 - SET_MAX related sub command (in feature register)
+//
+#define PARTIES_SET_MAX_ADDRESS_SUB_CMD 0x00
+#define PARTIES_SET_PASSWORD_SUB_CMD 0x01
+#define PARTIES_LOCK_SUB_CMD 0x02
+#define PARTIES_UNLOCK_SUB_CMD 0x03
+#define PARTIES_FREEZE_SUB_CMD 0x04
+
+//
+// S.M.A.R.T
+//
+#define ATA_SMART_CMD 0xb0
+#define ATA_CONSTANT_C2 0xc2
+#define ATA_CONSTANT_4F 0x4f
+#define ATA_SMART_ENABLE_OPERATION 0xd8
+#define ATA_SMART_RETURN_STATUS 0xda
+
+//
+// Error codes for Exec Drive Diag
+//
+#define DRIV_DIAG_NO_ERROR (0x01)
+#define DRIV_DIAG_FORMATTER_ERROR (0x02)
+#define DRIV_DIAG_DATA_BUFFER_ERROR (0x03)
+#define DRIV_DIAG_ECC_CKT_ERRROR (0x04)
+#define DRIV_DIAG_UP_ERROR (0x05)
+#define DRIV_DIAG_SLAVE_DRV_ERROR (0x80) /* aliased to 0x8x */
+
+//
+// Codes for Format Track
+//
+#define FORMAT_GOOD_SECTOR (0x00)
+#define FORMAT_SUSPEND_ALLOC (0x01)
+#define FORMAT_REALLOC_SECTOR (0x02)
+#define FORMAT_MARK_SECTOR_DEFECTIVE (0x03)
+
+//
+// IDE_IDENTIFY bits
+// config bits :
+//
+#define ID_CONFIG_RESERVED0 bit0
+#define ID_CONFIG_HARD_SECTORED_DRIVE bit1
+#define ID_CONFIG_SOFT_SECTORED_DRIVE bit2
+#define ID_CONFIG_NON_MFM bit3
+#define ID_CONFIG_15uS_HEAD_SWITCHING bit4
+#define ID_CONFIG_SPINDLE_MOTOR_CONTROL bit5
+#define ID_CONFIG_HARD_DRIVE bit6
+#define ID_CONFIG_CHANGEABLE_MEDIUM bit7
+#define ID_CONFIG_DATA_RATE_TO_5MHZ bit8
+#define ID_CONFIG_DATA_RATE_5_TO_10MHZ bit9
+#define ID_CONFIG_DATA_RATE_ABOVE_10MHZ bit10
+#define ID_CONFIG_MOTOR_SPEED_TOLERANCE_ABOVE_0_5_PERC bit11
+#define ID_CONFIG_DATA_CLK_OFFSET_AVAIL bit12
+#define ID_CONFIG_TRACK_OFFSET_AVAIL bit13
+#define ID_CONFIG_SPEED_TOLERANCE_GAP_NECESSARY bit14
+#define ID_CONFIG_RESERVED1 bit15
+
+#define ID_DOUBLE_WORD_IO_POSSIBLE bit01
+#define ID_LBA_SUPPORTED bit9
+#define ID_DMA_SUPPORTED bit8
+
+#define SET_FEATURE_ENABLE_8BIT_TRANSFER (0x01)
+#define SET_FEATURE_ENABLE_WRITE_CACHE (0x02)
+#define SET_FEATURE_TRANSFER_MODE (0x03)
+#define SET_FEATURE_WRITE_SAME_WRITE_SPECIFIC_AREA (0x22)
+#define SET_FEATURE_DISABLE_RETRIES (0x33)
+//
+// for Read & Write Longs
+//
+#define SET_FEATURE_VENDOR_SPEC_ECC_LENGTH (0x44)
+#define SET_FEATURE_PLACE_NO_OF_CACHE_SEGMENTS_IN_SECTOR_NO_REG (0x54)
+#define SET_FEATURE_DISABLE_READ_AHEAD (0x55)
+#define SET_FEATURE_MAINTAIN_PARAM_AFTER_RESET (0x66)
+#define SET_FEATURE_DISABLE_ECC (0x77)
+#define SET_FEATURE_DISABLE_8BIT_TRANSFER (0x81)
+#define SET_FEATURE_DISABLE_WRITE_CACHE (0x82)
+#define SET_FEATURE_ENABLE_ECC (0x88)
+#define SET_FEATURE_ENABLE_RETRIES (0x99)
+#define SET_FEATURE_ENABLE_READ_AHEAD (0xaa)
+#define SET_FEATURE_SET_SECTOR_CNT_REG_AS_NO_OF_READ_AHEAD_SECTORS (0xab)
+#define SET_FEATURE_ALLOW_REST_MODE (0xac)
+//
+// for Read & Write Longs
+//
+#define SET_FEATURE_4BYTE_ECC (0xbb)
+#define SET_FEATURE_DEFALUT_FEATURES_ON_SOFTWARE_RESET (0xcc)
+#define SET_FEATURE_WRITE_SAME_TO_WRITE_ENTIRE_MEDIUM (0xdd)
+
+#define BLOCK_TRANSFER_MODE (0x00)
+#define SINGLE_WORD_DMA_TRANSFER_MODE (0x10)
+#define MULTI_WORD_DMA_TRANSFER_MODE (0x20)
+#define TRANSFER_MODE_MASK (0x07) // 3 LSBs
+
+//
+// Drive 0 - Head 0
+//
+#define DEFAULT_DRIVE (0x00)
+#define DEFAULT_CMD (0xa0)
+//
+// default content of device control register, disable INT
+//
+#define DEFAULT_CTL (0x0a)
+#define DEFAULT_IDE_BM_IO_BASE_ADR (0xffa0)
+
+//
+// ATAPI6 related data structure definition
+//
+
+//
+// The maximum sectors count in 28 bit addressing mode
+//
+#define MAX_28BIT_ADDRESSING_CAPACITY 0xfffffff
+
+//
+// Move the IDENTIFY section to DXE\Protocol\IdeControllerInit
+//
+
+//
+// ATAPI Command
+//
+#define ATAPI_SOFT_RESET_CMD 0x08
+#define ATAPI_PACKET_CMD 0xA0
+#define PACKET_CMD 0xA0
+#define ATAPI_IDENTIFY_DEVICE_CMD 0xA1
+#define ATAPI_SERVICE_CMD 0xA2
+
+//
+// ATAPI Packet Command
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} TEST_UNIT_READY_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 page_code;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} INQUIRY_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} REQUEST_SENSE_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 page_code : 4;
+ UINT8 page_control : 4;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 parameter_list_length_hi;
+ UINT8 parameter_list_length_lo;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} MODE_SENSE_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 5;
+ UINT8 lun : 3;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+ UINT8 reserved_6;
+ UINT8 TranLen0;
+ UINT8 TranLen1;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} READ10_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 allocation_length_hi;
+ UINT8 allocation_length_lo;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} READ_FORMAT_CAP_CMD;
+
+typedef union {
+ UINT16 Data16[6];
+ TEST_UNIT_READY_CMD TestUnitReady;
+ READ10_CMD Read10;
+ REQUEST_SENSE_CMD RequestSence;
+ INQUIRY_CMD Inquiry;
+ MODE_SENSE_CMD ModeSense;
+ READ_FORMAT_CAP_CMD ReadFormatCapacity;
+} ATAPI_PACKET_COMMAND;
+
+typedef struct {
+ UINT32 RegionBaseAddr;
+ UINT16 ByteCount;
+ UINT16 EndOfTable;
+} IDE_DMA_PRD;
+
+#define MAX_DMA_EXT_COMMAND_SECTORS 0x10000
+#define MAX_DMA_COMMAND_SECTORS 0x100
+
+#pragma pack()
+
+//
+// Packet Command Code
+//
+#define TEST_UNIT_READY 0x00
+#define REZERO 0x01
+#define REQUEST_SENSE 0x03
+#define FORMAT_UNIT 0x04
+#define REASSIGN_BLOCKS 0x07
+#define INQUIRY 0x12
+#define START_STOP_UNIT 0x1B
+#define PREVENT_ALLOW_MEDIA_REMOVAL 0x1E
+#define READ_FORMAT_CAPACITY 0x23
+#define OLD_FORMAT_UNIT 0x24
+#define READ_CAPACITY 0x25
+#define READ_10 0x28
+#define WRITE_10 0x2A
+#define SEEK 0x2B
+#define SEND_DIAGNOSTICS 0x3D
+#define WRITE_VERIFY 0x2E
+#define VERIFY 0x2F
+#define READ_DEFECT_DATA 0x37
+#define WRITE_BUFFER 0x38
+#define READ_BUFFER 0x3C
+#define READ_LONG 0x3E
+#define WRITE_LONG 0x3F
+#define MODE_SELECT 0x55
+#define MODE_SENSE 0x5A
+#define READ_12 0xA8
+#define WRITE_12 0xAA
+#define MAX_ATAPI_BYTE_COUNT (0xfffe)
+
+//
+// Sense Key
+//
+#define REQUEST_SENSE_ERROR (0x70)
+#define SK_NO_SENSE (0x0)
+#define SK_RECOVERY_ERROR (0x1)
+#define SK_NOT_READY (0x2)
+#define SK_MEDIUM_ERROR (0x3)
+#define SK_HARDWARE_ERROR (0x4)
+#define SK_ILLEGAL_REQUEST (0x5)
+#define SK_UNIT_ATTENTION (0x6)
+#define SK_DATA_PROTECT (0x7)
+#define SK_BLANK_CHECK (0x8)
+#define SK_VENDOR_SPECIFIC (0x9)
+#define SK_RESERVED_A (0xA)
+#define SK_ABORT (0xB)
+#define SK_RESERVED_C (0xC)
+#define SK_OVERFLOW (0xD)
+#define SK_MISCOMPARE (0xE)
+#define SK_RESERVED_F (0xF)
+
+//
+// Additional Sense Codes
+//
+#define ASC_NOT_READY (0x04)
+#define ASC_MEDIA_ERR1 (0x10)
+#define ASC_MEDIA_ERR2 (0x11)
+#define ASC_MEDIA_ERR3 (0x14)
+#define ASC_MEDIA_ERR4 (0x30)
+#define ASC_MEDIA_UPSIDE_DOWN (0x06)
+#define ASC_INVALID_CMD (0x20)
+#define ASC_LBA_OUT_OF_RANGE (0x21)
+#define ASC_INVALID_FIELD (0x24)
+#define ASC_WRITE_PROTECTED (0x27)
+#define ASC_MEDIA_CHANGE (0x28)
+#define ASC_RESET (0x29) /* Power On Reset or Bus Reset occurred */
+#define ASC_ILLEGAL_FIELD (0x26)
+#define ASC_NO_MEDIA (0x3A)
+#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK (0x64)
+
+//
+// Additional Sense Code Qualifier
+//
+#define ASCQ_IN_PROGRESS (0x01)
+
+#define SETFEATURE TRUE
+#define CLEARFEATURE FALSE
+
+//
+// ATAPI Data structure
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 peripheral_type;
+ UINT8 RMB;
+ UINT8 version;
+ UINT8 response_data_format;
+ UINT8 addnl_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 vendor_info[8];
+ UINT8 product_id[12];
+ UINT8 eeprom_product_code[4];
+ UINT8 firmware_rev_level[4];
+ UINT8 firmware_sub_rev_level[1];
+ UINT8 reserved_37;
+ UINT8 reserved_38;
+ UINT8 reserved_39;
+ UINT8 max_capacity_hi;
+ UINT8 max_capacity_mid;
+ UINT8 max_capacity_lo;
+ UINT8 reserved_43_95[95 - 43 + 1];
+} INQUIRY_DATA;
+
+typedef struct {
+ UINT8 peripheral_type;
+ UINT8 RMB;
+ UINT8 version;
+ UINT8 response_data_format;
+ UINT8 addnl_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 vendor_info[8];
+ UINT8 product_id[16];
+ UINT8 product_revision_level[4];
+ UINT8 vendor_specific[20];
+ UINT8 reserved_56_95[40];
+} CDROM_INQUIRY_DATA;
+
+typedef struct {
+ UINT8 error_code : 7;
+ UINT8 valid : 1;
+ UINT8 reserved_1;
+ UINT8 sense_key : 4;
+ UINT8 reserved_21 : 1;
+ UINT8 ILI : 1;
+ UINT8 reserved_22 : 2;
+ UINT8 vendor_specific_3;
+ UINT8 vendor_specific_4;
+ UINT8 vendor_specific_5;
+ UINT8 vendor_specific_6;
+ UINT8 addnl_sense_length; // n - 7
+ UINT8 vendor_specific_8;
+ UINT8 vendor_specific_9;
+ UINT8 vendor_specific_10;
+ UINT8 vendor_specific_11;
+ UINT8 addnl_sense_code; // mandatory
+ UINT8 addnl_sense_code_qualifier; // mandatory
+ UINT8 field_replaceable_unit_code; // optional
+ UINT8 reserved_15;
+ UINT8 reserved_16;
+ UINT8 reserved_17;
+ //
+ // Followed by additional sense bytes : FIXME
+ //
+} REQUEST_SENSE_DATA;
+
+typedef struct {
+ UINT8 LastLba3;
+ UINT8 LastLba2;
+ UINT8 LastLba1;
+ UINT8 LastLba0;
+ UINT8 BlockSize3;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_CAPACITY_DATA;
+
+typedef struct {
+ UINT8 reserved_0;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 Capacity_Length;
+ UINT8 LastLba3;
+ UINT8 LastLba2;
+ UINT8 LastLba1;
+ UINT8 LastLba0;
+ UINT8 DesCode : 2;
+ UINT8 reserved_9 : 6;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_FORMAT_CAPACITY_DATA;
+
+#pragma pack()
+
+//
+// PIO mode definition
+//
+typedef enum {
+ ATA_PIO_MODE_BELOW_2,
+ ATA_PIO_MODE_2,
+ ATA_PIO_MODE_3,
+ ATA_PIO_MODE_4
+} ATA_PIO_MODE;
+
+//
+// Multi word DMA definition
+//
+typedef enum {
+ ATA_MDMA_MODE_0,
+ ATA_MDMA_MODE_1,
+ ATA_MDMA_MODE_2
+} ATA_MDMA_MODE;
+
+//
+// UDMA mode definition
+//
+typedef enum {
+ ATA_UDMA_MODE_0,
+ ATA_UDMA_MODE_1,
+ ATA_UDMA_MODE_2,
+ ATA_UDMA_MODE_3,
+ ATA_UDMA_MODE_4,
+ ATA_UDMA_MODE_5
+} ATA_UDMA_MODE;
+
+#define ATA_MODE_CATEGORY_DEFAULT_PIO 0x00
+#define ATA_MODE_CATEGORY_FLOW_PIO 0x01
+#define ATA_MODE_CATEGORY_MDMA 0x04
+#define ATA_MODE_CATEGORY_UDMA 0x08
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 ModeNumber : 3;
+ UINT8 ModeCategory : 5;
+} ATA_TRANSFER_MODE;
+
+typedef struct {
+ UINT8 Sector;
+ UINT8 Heads;
+ UINT8 MultipleSector;
+} ATA_DRIVE_PARMS;
+
+#pragma pack()
+//
+// IORDY Sample Point field value
+//
+#define ISP_5_CLK 0
+#define ISP_4_CLK 1
+#define ISP_3_CLK 2
+#define ISP_2_CLK 3
+
+//
+// Recovery Time field value
+//
+#define RECVY_4_CLK 0
+#define RECVY_3_CLK 1
+#define RECVY_2_CLK 2
+#define RECVY_1_CLK 3
+
+//
+// Slave IDE Timing Register Enable
+//
+#define SITRE bit14
+
+//
+// DMA Timing Enable Only Select 1
+//
+#define DTE1 bit7
+
+//
+// Pre-fetch and Posting Enable Select 1
+//
+#define PPE1 bit6
+
+//
+// IORDY Sample Point Enable Select 1
+//
+#define IE1 bit5
+
+//
+// Fast Timing Bank Drive Select 1
+//
+#define TIME1 bit4
+
+//
+// DMA Timing Enable Only Select 0
+//
+#define DTE0 bit3
+
+//
+// Pre-fetch and Posting Enable Select 0
+//
+#define PPE0 bit2
+
+//
+// IOREY Sample Point Enable Select 0
+//
+#define IE0 bit1
+
+//
+// Fast Timing Bank Drive Select 0
+//
+#define TIME0 bit0
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.c new file mode 100644 index 0000000000..b10ee93591 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.c @@ -0,0 +1,133 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "pcibus.h"
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName = {
+ PciBusComponentNameGetDriverName,
+ PciBusComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = {
+ { "eng", (CHAR16 *) 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 LookupUnicodeString (
+ Language,
+ gPciBusComponentName.SupportedLanguages,
+ mPciBusDriverNameTable,
+ 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
+ )
+/*++
+
+ 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;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.h new file mode 100644 index 0000000000..0e5dbdeff8 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.h @@ -0,0 +1,87 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.h
+
+Abstract:
+
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_BUS_COMPONENT_NAME_H
+#define _EFI_PCI_BUS_COMPONENT_NAME_H
+
+extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName;
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Language - TODO: add argument description
+ DriverName - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+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:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ ControllerHandle - TODO: add argument description
+ ChildHandle - TODO: add argument description
+ Language - TODO: add argument description
+ ControllerName - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.inf b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.inf new file mode 100644 index 0000000000..db1ea24356 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.inf @@ -0,0 +1,172 @@ +#/** @file
+# Component description file for PciBus module.
+#
+# PCI bus driver. This module will probe all PCI devices and allocate MMIO and IO
+# space for these devices. Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable
+# support hot plug.
+# Copyright (c) 2006 - 2007, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PciBus
+ FILE_GUID = 93B80004-9FB3-11d4-9A3A-0090273FC14D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = PciBusEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gPciBusDriverBinding
+# COMPONENT_NAME = gPciBusComponentName
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ PciLib.c
+ PciIo.c
+ pcibus.c
+ PciDeviceSupport.c
+ ComponentName.c
+ ComponentName.h
+ PciCommand.c
+ PciResourceSupport.c
+ PciEnumeratorSupport.c
+ PciEnumerator.c
+ PciOptionRomSupport.c
+ PciDriverOverride.c
+ PciPowerManagement.c
+ PciPowerManagement.h
+ PciDriverOverride.h
+ PciRomTable.c
+ PciHotPlugSupport.c
+ PciLib.h
+ PciHotPlugSupport.h
+ PciRomTable.h
+ PciOptionRomSupport.h
+ PciEnumeratorSupport.h
+ PciEnumerator.h
+ PciResourceSupport.h
+ PciDeviceSupport.h
+ PciCommand.h
+ PciIo.h
+ pcibus.h
+
+[Includes]
+ IntelFrameworkModulePkg/Include
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ PciIncompatibleDeviceSupportLib
+ PcdLib
+ DevicePathLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ ReportStatusCodeLib
+ BaseMemoryLib
+ UefiLib
+ BaseLib
+ UefiDriverEntryPoint
+ DebugLib
+
+
+################################################################################
+#
+# Guid C Name Section - list of Guids that this module uses or produces.
+#
+################################################################################
+
+[Guids]
+ gEfiPciOptionRomTableGuid # SOMETIMES_CONSUMED System Table
+ gEfiUgaIoProtocolGuid # ALWAYS_CONSUMED System Table
+ gEfiPciHotplugDeviceGuid # PRIVATE
+ gEfiPciOptionRomTableGuid # SOMETIMES_CONSUMED
+
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+
+[Protocols]
+ gEfiPciHotPlugRequestProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiBusSpecificDriverOverrideProtocolGuid # PROTOCOL BY_START
+ gEfiPciIoProtocolGuid # PROTOCOL BY_START
+ gEfiLoadedImageProtocolGuid # PROTOCOL TO_START
+ gEfiDecompressProtocolGuid # PROTOCOL TO_START
+ gEfiPciHotPlugInitProtocolGuid # PROTOCOL TO_START
+ gEfiPciHostBridgeResourceAllocationProtocolGuid # PROTOCOL TO_START
+ gEfiPciPlatformProtocolGuid # PROTOCOL TO_START
+ gEfiPciRootBridgeIoProtocolGuid # PROTOCOL TO_START
+ gEfiDevicePathProtocolGuid # PROTOCOL TO_START
+
+
+################################################################################
+#
+# Pcd FEATURE_FLAG - list of PCDs that this module is coded for.
+#
+################################################################################
+
+[PcdsFeatureFlag.common]
+ PcdPciVgaEnable|gEfiIntelFrameworkModulePkgTokenSpaceGuid
+ PcdPciBusHotplugDeviceSupport|gEfiIntelFrameworkModulePkgTokenSpaceGuid
+ PcdPciIsaEnable|gEfiIntelFrameworkModulePkgTokenSpaceGuid
+
+
+################################################################################
+#
+# Pcd FIXED_AT_BUILD - list of PCDs that this module is coded for.
+#
+################################################################################
+
+[PcdsFixedAtBuild.common]
+ PcdPciIncompatibleDeviceSupportMask|gEfiIntelFrameworkModulePkgTokenSpaceGuid
+
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa new file mode 100644 index 0000000000..655fb4f1b1 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa @@ -0,0 +1,178 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>PciBus</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>93B80004-9FB3-11d4-9A3A-0090273FC14D</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for PciBus module.</Abstract>
+ <Description>PCI bus driver. This module will probe all PCI devices and allocate MMIO and IO
+ space for these devices. Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable
+ support hot plug.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>PciBus</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>ReportStatusCodeLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DevicePathLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PcdLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PciIncompatibleDeviceSupportLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>pcibus.h</Filename>
+ <Filename>PciIo.h</Filename>
+ <Filename>PciCommand.h</Filename>
+ <Filename>PciDeviceSupport.h</Filename>
+ <Filename>PciResourceSupport.h</Filename>
+ <Filename>PciEnumerator.h</Filename>
+ <Filename>PciEnumeratorSupport.h</Filename>
+ <Filename>PciOptionRomSupport.h</Filename>
+ <Filename>PciRomTable.h</Filename>
+ <Filename>PciHotPlugSupport.h</Filename>
+ <Filename>PciLib.h</Filename>
+ <Filename>PciHotPlugSupport.c</Filename>
+ <Filename>PciRomTable.c</Filename>
+ <Filename>PciDriverOverride.h</Filename>
+ <Filename>PciPowerManagement.h</Filename>
+ <Filename>PciPowerManagement.c</Filename>
+ <Filename>PciDriverOverride.c</Filename>
+ <Filename>PciOptionRomSupport.c</Filename>
+ <Filename>PciEnumerator.c</Filename>
+ <Filename>PciEnumeratorSupport.c</Filename>
+ <Filename>PciResourceSupport.c</Filename>
+ <Filename>PciCommand.c</Filename>
+ <Filename>ComponentName.h</Filename>
+ <Filename>ComponentName.c</Filename>
+ <Filename>PciDeviceSupport.c</Filename>
+ <Filename>pcibus.c</Filename>
+ <Filename>PciIo.c</Filename>
+ <Filename>PciLib.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="1E73767F-8F52-4603-AEB4-F29B510B6766"/>
+ <Package PackageGuid="2759ded5-bb57-4b06-af4f-c398fa552719"/>
+ <Package PackageGuid="BA0D78D6-2CAF-414b-BD4D-B6762A894288"/>
+ <Package PackageGuid="88894582-7553-4822-B484-624E24B6DECF"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiPciRootBridgeIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiPciPlatformProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiPciHostBridgeResourceAllocationProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiPciHotPlugInitProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiDecompressProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiLoadedImageProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="BY_START">
+ <ProtocolCName>gEfiPciIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="BY_START">
+ <ProtocolCName>gEfiBusSpecificDriverOverrideProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_PRODUCED">
+ <ProtocolCName>gEfiPciHotPlugRequestProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <SystemTables>
+ <SystemTableCNames Usage="ALWAYS_CONSUMED">
+ <SystemTableCName>gEfiUgaIoProtocolGuid</SystemTableCName>
+ </SystemTableCNames>
+ <SystemTableCNames Usage="SOMETIMES_CONSUMED">
+ <SystemTableCName>gEfiPciOptionRomTableGuid</SystemTableCName>
+ </SystemTableCNames>
+ </SystemTables>
+ <Guids>
+ <GuidCNames Usage="SOMETIMES_CONSUMED">
+ <GuidCName>gEfiPciOptionRomTableGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="PRIVATE">
+ <GuidCName>gEfiPciHotplugDeviceGuid</GuidCName>
+ </GuidCNames>
+ </Guids>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>PciBusEntryPoint</ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gPciBusDriverBinding</DriverBinding>
+ <ComponentName>gPciBusComponentName</ComponentName>
+ </Extern>
+ </Externs>
+ <PcdCoded>
+ <PcdEntry PcdItemType="FEATURE_FLAG">
+ <C_Name>PcdPciIsaEnable</C_Name>
+ <TokenSpaceGuidCName>gEfiIntelFrameworkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>This is a switch to enable ISA</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FIXED_AT_BUILD">
+ <C_Name>PcdPciIncompatibleDeviceSupportMask</C_Name>
+ <TokenSpaceGuidCName>gEfiIntelFrameworkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>The PCD masks for PCI incompatible devices support.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG">
+ <C_Name>PcdPciBusHotplugDeviceSupport</C_Name>
+ <TokenSpaceGuidCName>gEfiIntelFrameworkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>If TRUE, the PCI bus driver will support hot plug device. If not hot plug device is supported, this feature flag can be set to FALSE to save size.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="FEATURE_FLAG">
+ <C_Name>PcdPciVgaEnable</C_Name>
+ <TokenSpaceGuidCName>gEfiIntelFrameworkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>Whether VGA decoding is enabled on this platform so we should avoid those aliased resources</HelpText>
+ </PcdEntry>
+ </PcdCoded>
+</ModuleSurfaceArea>
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.c new file mode 100644 index 0000000000..dd4b650612 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.c @@ -0,0 +1,207 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciCommand.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+
+EFI_STATUS
+PciOperateRegister (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 Command,
+ IN UINT8 Offset,
+ IN UINT8 Operation,
+ OUT UINT16 *PtrCommand
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Command - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: PtrCommand - add argument and description to function comment
+{
+ UINT16 OldCommand;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ OldCommand = 0;
+ PciIo = &PciIoDevice->PciIo;
+
+ if (Operation != EFI_SET_REGISTER) {
+ Status = PciIoRead (
+ PciIo,
+ EfiPciIoWidthUint16,
+ Offset,
+ 1,
+ &OldCommand
+ );
+
+ if (Operation == EFI_GET_REGISTER) {
+ *PtrCommand = OldCommand;
+ return Status;
+ }
+ }
+
+ if (Operation == EFI_ENABLE_REGISTER) {
+ OldCommand = (UINT16) (OldCommand | Command);
+ } else if (Operation == EFI_DISABLE_REGISTER) {
+ OldCommand = (UINT16) (OldCommand & ~(Command));
+ } else {
+ OldCommand = Command;
+ }
+
+ return PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ Offset,
+ 1,
+ &OldCommand
+ );
+}
+
+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 cap reg.
+
+Arguments:
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+ CapId - The cap ID.
+ Offset - A pointer to the offset.
+ NextRegBlock - A pointer to the next block.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ UINT8 CapabilityPtr;
+ UINT16 CapabilityEntry;
+ UINT8 CapabilityID;
+
+ //
+ // To check the cpability of this device supports
+ //
+ if (!PciCapabilitySupport (PciIoDevice)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (*Offset != 0) {
+ CapabilityPtr = *Offset;
+ } else {
+
+ CapabilityPtr = 0;
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+
+ PciIoRead (
+ &PciIoDevice->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,
+ 1,
+ &CapabilityPtr
+ );
+ } else {
+
+ PciIoRead (
+ &PciIoDevice->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_CAPABILITY_PTR,
+ 1,
+ &CapabilityPtr
+ );
+ }
+ }
+
+ while (CapabilityPtr > 0x3F) {
+ //
+ // Mask it to DWORD alignment per PCI spec
+ //
+ CapabilityPtr &= 0xFC;
+ PciIoRead (
+ &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;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.h new file mode 100644 index 0000000000..e63d0d1525 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.h @@ -0,0 +1,175 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciCommand.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_COMMAND_H
+#define _EFI_PCI_COMMAND_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 \
+ )
+
+
+#define EFI_GET_REGISTER 1
+#define EFI_SET_REGISTER 2
+#define EFI_ENABLE_REGISTER 3
+#define EFI_DISABLE_REGISTER 4
+
+EFI_STATUS
+PciOperateRegister (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 Command,
+ IN UINT8 Offset,
+ IN UINT8 Operation,
+ OUT UINT16 *PtrCommand
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Command - TODO: add argument description
+ Offset - TODO: add argument description
+ Operation - TODO: add argument description
+ PtrCommand - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+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:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ CapId - TODO: add argument description
+ Offset - TODO: add argument description
+ NextRegBlock - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+
+#define PciReadCommandRegister(a,b) \
+ PciOperateRegister (a,0, PCI_COMMAND_OFFSET, EFI_GET_REGISTER, b)
+
+#define PciSetCommandRegister(a,b) \
+ PciOperateRegister (a,b, PCI_COMMAND_OFFSET, EFI_SET_REGISTER, NULL)
+
+#define PciEnableCommandRegister(a,b) \
+ PciOperateRegister (a,b, PCI_COMMAND_OFFSET, EFI_ENABLE_REGISTER, NULL)
+
+#define PciDisableCommandRegister(a,b) \
+ PciOperateRegister (a,b, PCI_COMMAND_OFFSET, EFI_DISABLE_REGISTER, NULL)
+
+#define PciReadBridgeControlRegister(a,b) \
+ PciOperateRegister (a,0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_GET_REGISTER, b)
+
+#define PciSetBridgeControlRegister(a,b) \
+ PciOperateRegister (a,b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_SET_REGISTER, NULL)
+
+#define PciEnableBridgeControlRegister(a,b) \
+ PciOperateRegister (a,b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_ENABLE_REGISTER, NULL)
+
+#define PciDisableBridgeControlRegister(a,b) \
+ PciOperateRegister (a,b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_DISABLE_REGISTER, NULL)
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.c new file mode 100644 index 0000000000..0e95dc1865 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.c @@ -0,0 +1,1351 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciDeviceSupport.c
+
+Abstract:
+
+ This file provides routine to support Pci device node manipulation
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+#include "PciDeviceSupport.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
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ InitializeListHead (&gPciDevicePool);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InsertRootBridge (
+ 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
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ 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
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ 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
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ DestroyPciDeviceTree (RootBridge);
+
+ FreePciDevice (RootBridge);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FreePciDevice (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Destroy a pci device node.
+ Also all direct or indirect allocated resource for this node will be freed.
+
+Arguments:
+
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ //
+ // Assume all children have been removed underneath this device
+ //
+ if (PciIoDevice->ResourcePaddingDescriptors != NULL) {
+ gBS->FreePool (PciIoDevice->ResourcePaddingDescriptors);
+ }
+
+ if (PciIoDevice->DevicePath != NULL) {
+ gBS->FreePool (PciIoDevice->DevicePath);
+ }
+
+ gBS->FreePool (PciIoDevice);
+
+ 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
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ 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 (!IsListEmpty (&Temp->ChildList)) {
+ DestroyPciDeviceTree (Temp);
+ }
+
+ FreePciDevice (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
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+
+ 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);
+
+ FreePciDevice (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;
+ VOID *PlatformOpRomBuffer;
+ UINTN PlatformOpRomSize;
+ UINT8 PciExpressCapRegOffset;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Data8;
+
+ //
+ // Install the pciio protocol, device path protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PciIoDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PciIoDevice->DevicePath,
+ &gEfiPciIoProtocolGuid,
+ &PciIoDevice->PciIo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Detect if PCI Express Device
+ //
+ PciExpressCapRegOffset = 0;
+ Status = LocateCapabilityRegBlock (
+ PciIoDevice,
+ EFI_PCI_CAPABILITY_ID_PCIEXP,
+ &PciExpressCapRegOffset,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ PciIoDevice->IsPciExp = TRUE;
+ }
+
+ //
+ // Force Interrupt line to "Unknown" or "No Connection"
+ //
+ PciIo = &(PciIoDevice->PciIo);
+ Data8 = PCI_INT_LINE_UNKNOWN;
+ PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &Data8);
+
+ //
+ // Process Platform OpRom
+ //
+ if (gPciPlatformProtocol != NULL && !PciIoDevice->AllOpRomProcessed) {
+ PciIoDevice->AllOpRomProcessed = TRUE;
+
+ Status = gPciPlatformProtocol->GetPciRom (
+ gPciPlatformProtocol,
+ PciIoDevice->Handle,
+ &PlatformOpRomBuffer,
+ &PlatformOpRomSize
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Have Platform OpRom
+ //
+ PciIoDevice->RomSize = PlatformOpRomSize;
+ PciIoDevice->PciIo.RomSize = PlatformOpRomSize;
+ PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
+
+ //
+ // Process Image
+ //
+ ProcessOpRomImage (PciIoDevice);
+ }
+ }
+
+ if (PciIoDevice->BusOverride) {
+ //
+ // Install BusSpecificDriverOverride Protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PciIoDevice->Handle,
+ &gEfiBusSpecificDriverOverrideProtocolGuid,
+ &PciIoDevice->PciDriverOverride,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ &PciIoDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PciIoDevice->DevicePath,
+ &gEfiPciIoProtocolGuid,
+ &PciIoDevice->PciIo,
+ NULL
+ );
+
+ return Status;
+ }
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &(PciIoDevice->PciRootBridgeIo),
+ gPciBusDriverBinding.DriverBindingHandle,
+ PciIoDevice->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Pccard Hotplug GUID for Pccard device so that
+ // to notify CardBus driver to stop the device when de-register happens
+ //
+ InstallPciHotplugGuid (PciIoDevice);
+
+ if (Handle != NULL) {
+ *Handle = PciIoDevice->Handle;
+ }
+
+ //
+ // Indicate the pci device is registered
+ //
+ PciIoDevice->Registered = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RemoveAllPciDeviceOnBridge (
+ EFI_HANDLE RootBridgeHandle,
+ PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ This function is used to remove the whole PCI devices from the bridge.
+
+Arguments:
+
+ RootBridgeHandle - An efi handle.
+ Bridge - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+
+ while (!IsListEmpty (&Bridge->ChildList)) {
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ //
+ // Check if the current node has been deregistered before
+ // If it is not, then deregister it
+ //
+ if (Temp->Registered) {
+ DeRegisterPciDevice (RootBridgeHandle, Temp->Handle);
+ }
+
+ //
+ // Remove this node from the linked list
+ //
+ RemoveEntryList (CurrentLink);
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
+ }
+
+ FreePciDevice (Temp);
+ }
+
+ 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
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ 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 (!IsListEmpty (&PciIoDevice->ChildList)) {
+
+ 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;
+ }
+ }
+ //
+ // Uninstall Pccard Hotplug GUID for Pccard device
+ //
+ UninstallPciHotplugGuid (PciIoDevice);
+
+ //
+ // 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
+StartPciDevicesOnBridge (
+ IN EFI_HANDLE Controller,
+ IN PCI_IO_DEVICE *RootBridge,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ IN OUT UINT8 *NumberOfChildren,
+ IN OUT EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+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
+
+--*/
+// TODO: EFI_NOT_READY - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ PCI_IO_DEVICE *Temp;
+ PCI_IO_DEVICE *PciIoDevice;
+ EFI_DEV_PATH_PTR Node;
+ EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
+ EFI_STATUS Status;
+ LIST_ENTRY *CurrentLink;
+ UINT64 Supports;
+
+ 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
+ );
+
+ }
+
+ if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && Temp->Registered) {
+ ChildHandleBuffer[*NumberOfChildren] = Temp->Handle;
+ (*NumberOfChildren)++;
+ }
+
+ //
+ // Get the next device path
+ //
+ CurrentDevicePath = EfiNextDevicePathNode (RemainingDevicePath);
+ if (EfiIsDevicePathEnd (CurrentDevicePath)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If it is a PPB
+ //
+ if (!IsListEmpty (&Temp->ChildList)) {
+ Status = StartPciDevicesOnBridge (
+ Controller,
+ Temp,
+ CurrentDevicePath,
+ NumberOfChildren,
+ ChildHandleBuffer
+ );
+
+ Temp->PciIo.Attributes (
+ &(Temp->PciIo),
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Temp->PciIo.Attributes (
+ &(Temp->PciIo),
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+
+ 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 (NumberOfChildren != NULL && ChildHandleBuffer != NULL && Temp->Registered) {
+ ChildHandleBuffer[*NumberOfChildren] = Temp->Handle;
+ (*NumberOfChildren)++;
+ }
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ Status = StartPciDevicesOnBridge (
+ Controller,
+ Temp,
+ RemainingDevicePath,
+ NumberOfChildren,
+ ChildHandleBuffer
+ );
+
+ Temp->PciIo.Attributes (
+ &(Temp->PciIo),
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Temp->PciIo.Attributes (
+ &(Temp->PciIo),
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+
+ }
+
+ 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
+
+--*/
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ 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,
+ NULL,
+ NULL
+ );
+ }
+
+ 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;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ 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);
+
+ Status = gBS->OpenProtocol (
+ RootBridgeHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ gPciBusDriverBinding.DriverBindingHandle,
+ RootBridgeHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (Dev);
+ return NULL;
+ }
+
+ //
+ // Record the root bridge parent device path
+ //
+ Dev->DevicePath = DuplicateDevicePath (ParentDevicePath);
+
+ //
+ // Get the pci root bridge io protocol
+ //
+ Status = gBS->OpenProtocol (
+ RootBridgeHandle,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ RootBridgeHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePciDevice (Dev);
+ return NULL;
+ }
+
+ Dev->PciRootBridgeIo = PciRootBridgeIo;
+
+ //
+ // Initialize the PCI I/O instance structure
+ //
+ Status = InitializePciIoInstance (Dev);
+ Status = InitializePciDriverOverrideInstance (Dev);
+
+ //
+ // Initialize reserved resource list and
+ // option rom driver list
+ //
+ InitializeListHead (&Dev->ReservedResourceList);
+ InitializeListHead (&Dev->OptionRomDriverList);
+
+ 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;
+}
+
+EFI_STATUS
+GetHpcPciAddress (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ OUT UINT64 *PciAddress
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL.
+ PciAddress - A pointer to the pci address.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
+ EFI_DEV_PATH_PTR Node;
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *RootBridge;
+ EFI_STATUS Status;
+
+ CurrentDevicePath = HpcDevicePath;
+
+ //
+ // Get the remaining device path for this PCI device, if it is a PCI device
+ //
+ while (!EfiIsDevicePathEnd (CurrentDevicePath)) {
+
+ Node.DevPath = CurrentDevicePath;
+
+ //
+ // Check if it is PCI device Path?
+ //
+ if ((Node.DevPath->Type != HARDWARE_DEVICE_PATH) ||
+ ((Node.DevPath->SubType != HW_PCI_DP) &&
+ (DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)))) {
+ CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath);
+ continue;
+ }
+
+ break;
+ }
+
+ //
+ // Check if it is not PCI device path
+ //
+ if (EfiIsDevicePathEnd (CurrentDevicePath)) {
+ return EFI_NOT_FOUND;
+ }
+
+ CurrentLink = gPciDevicePool.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &gPciDevicePool) {
+
+ RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ //
+ // Locate the right root bridge to start
+ //
+ if (RootBridge->PciRootBridgeIo == PciRootBridgeIo) {
+ Status = GetHpcPciAddressFromRootBridge (
+ RootBridge,
+ CurrentDevicePath,
+ PciAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+GetHpcPciAddressFromRootBridge (
+ IN PCI_IO_DEVICE *RootBridge,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ OUT UINT64 *PciAddress
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL.
+ PciAddress - A pointer to the pci address.
+
+Returns:
+
+ None
+
+--*/
+// TODO: RootBridge - add argument and description to function comment
+// TODO: RemainingDevicePath - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_DEV_PATH_PTR Node;
+ PCI_IO_DEVICE *Temp;
+ EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
+ LIST_ENTRY *CurrentLink;
+ BOOLEAN MisMatch;
+
+ MisMatch = FALSE;
+
+ CurrentDevicePath = RemainingDevicePath;
+ Node.DevPath = CurrentDevicePath;
+ Temp = NULL;
+
+ while (!EfiIsDevicePathEnd (CurrentDevicePath)) {
+
+ CurrentLink = RootBridge->ChildList.ForwardLink;
+ Node.DevPath = CurrentDevicePath;
+
+ while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (Node.Pci->Device == Temp->DeviceNumber &&
+ Node.Pci->Function == Temp->FunctionNumber) {
+ RootBridge = Temp;
+ break;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // Check if we find the bridge
+ //
+ if (CurrentLink == &RootBridge->ChildList) {
+
+ MisMatch = TRUE;
+ break;
+
+ }
+
+ CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath);
+ }
+
+ if (MisMatch) {
+
+ CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath);
+
+ if (EfiIsDevicePathEnd (CurrentDevicePath)) {
+ *PciAddress = EFI_PCI_ADDRESS (RootBridge->BusNumber, Node.Pci->Device, Node.Pci->Function, 0);
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+ }
+
+ *PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
+
+ return EFI_SUCCESS;
+
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.h new file mode 100644 index 0000000000..374f4dfad3 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.h @@ -0,0 +1,477 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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
+InsertRootBridge (
+ PCI_IO_DEVICE *RootBridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridge - TODO: add argument description
+
+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
+DestroyRootBridge (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridge - 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:
+
+ TODO: Add function description
+
+Arguments:
+
+ Controller - TODO: add argument description
+ PciIoDevice - TODO: add argument description
+ Handle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RemoveAllPciDeviceOnBridge (
+ EFI_HANDLE RootBridgeHandle,
+ PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeHandle - TODO: add argument description
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+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
+StartPciDevicesOnBridge (
+ IN EFI_HANDLE Controller,
+ IN PCI_IO_DEVICE *RootBridge,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ IN OUT UINT8 *NumberOfChildren,
+ IN OUT EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Controller - TODO: add argument description
+ RootBridge - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+ NumberOfChildren - TODO: add argument description
+ ChildHandleBuffer - 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
+
+--*/
+;
+
+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
+
+--*/
+;
+
+EFI_STATUS
+GetHpcPciAddress (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ OUT UINT64 *PciAddress
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciRootBridgeIo - TODO: add argument description
+ HpcDevicePath - TODO: add argument description
+ PciAddress - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetHpcPciAddressFromRootBridge (
+ IN PCI_IO_DEVICE *RootBridge,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ OUT UINT64 *PciAddress
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridge - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+ PciAddress - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+FreePciDevice (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c new file mode 100644 index 0000000000..7643fc87e2 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c @@ -0,0 +1,175 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciDriverOverride.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+
+EFI_STATUS
+InitializePciDriverOverrideInstance (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Initializes a PCI Driver Override Instance
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ 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
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: DriverImageHandle - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+{
+ 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
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: DriverImageHandle - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_NT_HEADERS *PeHdr;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ 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;
+
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) LoadedImage->ImageBase;
+ if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ return EFI_SUCCESS;
+ }
+
+ PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) LoadedImage->ImageBase + DosHdr->e_lfanew);
+
+ if (PeHdr->FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {
+ return EFI_SUCCESS;
+ }
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.h new file mode 100644 index 0000000000..5992df9eb7 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.h @@ -0,0 +1,108 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciDriverOverride.h
+
+Abstract:
+
+
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H
+#define _EFI_PCI_DRIVER_OVERRRIDE_H
+
+#define DRIVER_OVERRIDE_SIGNATURE EFI_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
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c new file mode 100644 index 0000000000..e7a05a2ec9 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c @@ -0,0 +1,2168 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciEnumerator.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+#include "PciEnumerator.h"
+#include "PciResourceSupport.h"
+#include "PciOptionRomSupport.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
+
+--*/
+// TODO: Controller - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ EFI_HANDLE HostBridgeHandle;
+ EFI_STATUS Status;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ //
+ // If PCI bus has already done the full enumeration, never do it again
+ //
+ if (!gFullEnumeration) {
+ return PciEnumeratorLight (Controller);
+ }
+
+ //
+ // If this host bridge has been already enumerated, then return successfully
+ //
+ if (RootBridgeExisted (Controller)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Get the rootbridge Io protocol to find the host bridge handle
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the host bridge handle
+ //
+ HostBridgeHandle = PciRootBridgeIo->ParentHandle;
+
+ //
+ // Get the pci host bridge resource allocation protocol
+ //
+ Status = gBS->OpenProtocol (
+ HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+ (VOID **) &PciResAlloc,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Notify the pci bus enumeration is about to begin
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);
+
+ //
+ // Start the bus allocation phase
+ //
+ Status = PciHostBridgeEnumerator (PciResAlloc);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Submit the resource request
+ //
+ Status = PciHostBridgeResourceAllocator (PciResAlloc);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Process P2C
+ //
+ Status = PciHostBridgeP2CProcess (PciResAlloc);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Process attributes for devices on this host bridge
+ //
+ Status = PciHostBridgeDeviceAttribute (PciResAlloc);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gFullEnumeration = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRootBridgeEnumerator (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: RootBridgeDev - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *pConfiguration;
+ UINT8 SubBusNumber;
+ UINT8 StartBusNumber;
+ UINT8 PaddedBusRange;
+ EFI_HANDLE RootBridgeHandle;
+
+ SubBusNumber = 0;
+ StartBusNumber = 0;
+ PaddedBusRange = 0;
+
+ //
+ // Get the root bridge handle
+ //
+ RootBridgeHandle = RootBridgeDev->Handle;
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,
+ RootBridgeDev->DevicePath
+ );
+
+ //
+ // Get the Bus information
+ //
+ Status = PciResAlloc->StartBusEnumeration (
+ PciResAlloc,
+ RootBridgeHandle,
+ (VOID **) &pConfiguration
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the bus number to start with
+ //
+ StartBusNumber = (UINT8) (pConfiguration->AddrRangeMin);
+
+ //
+ // Initialize the subordinate bus number
+ //
+ SubBusNumber = StartBusNumber;
+
+ //
+ // Assign bus number
+ //
+ Status = PciScanBus (
+ RootBridgeDev,
+ (UINT8) (pConfiguration->AddrRangeMin),
+ &SubBusNumber,
+ &PaddedBusRange
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+
+ //
+ // Assign max bus number scanned
+ //
+ pConfiguration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;
+
+ //
+ // Set bus number
+ //
+ Status = PciResAlloc->SetBusNumbers (
+ PciResAlloc,
+ RootBridgeHandle,
+ pConfiguration
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProcessOptionRom (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT64 RomBase,
+ IN UINT64 MaxLength
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to process option rom on a certain root bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: RomBase - add argument and description to function comment
+// TODO: MaxLength - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+ EFI_STATUS Status;
+
+ //
+ // Go through bridges to reach all devices
+ //
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ if (!IsListEmpty (&Temp->ChildList)) {
+
+ //
+ // Go further to process the option rom under this bridge
+ //
+ Status = ProcessOptionRom (Temp, RomBase, MaxLength);
+ }
+
+ if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {
+
+ //
+ // Load and process the option rom
+ //
+ Status = LoadOpRomImage (Temp, RomBase);
+ if (Status == EFI_SUCCESS) {
+ Status = ProcessOpRomImage (Temp);
+ }
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciAssignBusNumber (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to assign bus number to the given PCI bus system
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: StartBusNumber - add argument and description to function comment
+// TODO: SubBusNumber - add argument and description to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 Pci;
+ UINT8 Device;
+ UINT8 Func;
+ UINT64 Address;
+ UINTN SecondBus;
+ UINT16 Register;
+ UINT8 Register8;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+
+ SecondBus = 0;
+ Register = 0;
+
+ *SubBusNumber = StartBusNumber;
+
+ //
+ // First check to see whether the parent is ppb
+ //
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+ //
+ // Check to see whether a pci device is present
+ //
+
+ Status = PciDevicePresent (
+ PciRootBridgeIo,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func
+ );
+
+ if (!EFI_ERROR (Status) &&
+ (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
+
+ //
+ // Reserved one bus for cardbus bridge
+ //
+ SecondBus = ++(*SubBusNumber);
+
+ Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
+
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
+
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint16,
+ Address,
+ 1,
+ &Register
+ );
+
+ //
+ // Initialize SubBusNumber to SecondBus
+ //
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ SubBusNumber
+ );
+ //
+ // If it is PPB, resursively search down this bridge
+ //
+ if (IS_PCI_BRIDGE (&Pci)) {
+
+ Register8 = 0xFF;
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &Register8
+ );
+
+ Status = PciAssignBusNumber (
+ Bridge,
+ (UINT8) (SecondBus),
+ SubBusNumber
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Set the current maximum bus number under the PPB
+ //
+
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ SubBusNumber
+ );
+
+ }
+
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+
+ Func = PCI_MAX_FUNC;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DetermineRootBridgeAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to determine the root bridge attribute by interfacing
+ the host bridge resource allocation protocol.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: RootBridgeDev - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Attributes;
+ EFI_STATUS Status;
+ EFI_HANDLE RootBridgeHandle;
+
+ Attributes = 0;
+ RootBridgeHandle = RootBridgeDev->Handle;
+
+ //
+ // Get root bridge attribute by calling into pci host bridge resource allocation protocol
+ //
+ Status = PciResAlloc->GetAllocAttributes (
+ PciResAlloc,
+ RootBridgeHandle,
+ &Attributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Here is the point where PCI bus driver calls HOST bridge allocation protocol
+ // Currently we hardcoded for ea815
+ //
+
+ if (Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) {
+ RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;
+ }
+
+ if (Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) {
+ RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
+ }
+
+ RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
+ RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+ RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
+
+ return EFI_SUCCESS;
+}
+
+UINT64
+GetMaxOptionRomSize (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ Get Max Option Rom size on this bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+ UINT64 MaxOptionRomSize;
+ UINT64 TempOptionRomSize;
+
+ MaxOptionRomSize = 0;
+
+ //
+ // Go through bridges to reach all devices
+ //
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ if (!IsListEmpty (&Temp->ChildList)) {
+
+ //
+ // Get max option rom size under this bridge
+ //
+ TempOptionRomSize = GetMaxOptionRomSize (Temp);
+
+ //
+ // Compare with the option rom size of the bridge
+ // Get the larger one
+ //
+ if (Temp->RomSize > TempOptionRomSize) {
+ TempOptionRomSize = Temp->RomSize;
+ }
+
+ } else {
+
+ //
+ // For devices get the rom size directly
+ //
+ TempOptionRomSize = Temp->RomSize;
+ }
+
+ //
+ // Get the largest rom size on this bridge
+ //
+ if (TempOptionRomSize > MaxOptionRomSize) {
+ MaxOptionRomSize = TempOptionRomSize;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return MaxOptionRomSize;
+}
+
+EFI_STATUS
+PciHostBridgeDeviceAttribute (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ Process attributes of devices on this host bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE RootBridgeHandle;
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_STATUS Status;
+
+ RootBridgeHandle = NULL;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Set the attributes for devcies behind the Root Bridge
+ //
+ Status = DetermineDeviceAttribute (RootBridgeDev);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetResourceAllocationStatus (
+ VOID *AcpiConfig,
+ OUT UINT64 *IoResStatus,
+ OUT UINT64 *Mem32ResStatus,
+ OUT UINT64 *PMem32ResStatus,
+ OUT UINT64 *Mem64ResStatus,
+ OUT UINT64 *PMem64ResStatus
+ )
+/*++
+
+Routine Description:
+
+ Get resource allocation status from the ACPI pointer
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: AcpiConfig - add argument and description to function comment
+// TODO: IoResStatus - add argument and description to function comment
+// TODO: Mem32ResStatus - add argument and description to function comment
+// TODO: PMem32ResStatus - add argument and description to function comment
+// TODO: Mem64ResStatus - add argument and description to function comment
+// TODO: PMem64ResStatus - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ UINT8 *Temp;
+ UINT64 ResStatus;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
+
+ Temp = (UINT8 *) AcpiConfig;
+
+ while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+
+ ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+ ResStatus = ptr->AddrTranslationOffset;
+
+ switch (ptr->ResType) {
+ case 0:
+ if (ptr->AddrSpaceGranularity == 32) {
+ if (ptr->SpecificFlag == 0x06) {
+ //
+ // Pmem32
+ //
+ *PMem32ResStatus = ResStatus;
+ } else {
+ //
+ // Mem32
+ //
+ *Mem32ResStatus = ResStatus;
+ }
+ }
+
+ if (ptr->AddrSpaceGranularity == 64) {
+ if (ptr->SpecificFlag == 0x06) {
+ //
+ // PMem64
+ //
+ *PMem64ResStatus = ResStatus;
+ } else {
+ //
+ // Mem64
+ //
+ *Mem64ResStatus = ResStatus;
+ }
+ }
+
+ break;
+
+ case 1:
+ //
+ // Io
+ //
+ *IoResStatus = ResStatus;
+ break;
+
+ default:
+ break;
+ }
+
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RejectPciDevice (
+ IN PCI_IO_DEVICE *PciDevice
+ )
+/*++
+
+Routine Description:
+
+ Remove a PCI device from device pool and mark its bar
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ PCI_IO_DEVICE *Bridge;
+ PCI_IO_DEVICE *Temp;
+ LIST_ENTRY *CurrentLink;
+
+ //
+ // Remove the padding resource from a bridge
+ //
+ if ( IS_PCI_BRIDGE(&PciDevice->Pci) && \
+ PciDevice->ResourcePaddingDescriptors ) {
+ gBS->FreePool (PciDevice->ResourcePaddingDescriptors);
+ PciDevice->ResourcePaddingDescriptors = NULL;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Skip RB and PPB
+ //
+ if (IS_PCI_BRIDGE (&PciDevice->Pci) || (!PciDevice->Parent)) {
+ return EFI_ABORTED;
+ }
+
+ if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
+ //
+ // Get the root bridge device
+ //
+ Bridge = PciDevice;
+ while (Bridge->Parent) {
+ Bridge = Bridge->Parent;
+ }
+
+ RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);
+
+ //
+ // Mark its bar
+ //
+ InitializeP2C (PciDevice);
+ }
+
+ //
+ // Remove the device
+ //
+ Bridge = PciDevice->Parent;
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ if (Temp == PciDevice) {
+ InitializePciDevice (Temp);
+ RemoveEntryList (CurrentLink);
+ FreePciDevice (Temp);
+ return EFI_SUCCESS;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_ABORTED;
+}
+
+BOOLEAN
+IsRejectiveDevice (
+ IN PCI_RESOURCE_NODE *PciResNode
+ )
+/*++
+
+Routine Description:
+
+ Determine whethter a PCI device can be rejected
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResNode - add argument and description to function comment
+{
+ PCI_IO_DEVICE *Temp;
+
+ Temp = PciResNode->PciDev;
+
+ //
+ // Ensure the device is present
+ //
+ if (!Temp) {
+ return FALSE;
+ }
+
+ //
+ // PPB and RB should go ahead
+ //
+ if (IS_PCI_BRIDGE (&Temp->Pci) || (!Temp->Parent)) {
+ return TRUE;
+ }
+
+ //
+ // Skip device on Bus0
+ //
+ if ((Temp->Parent) && (Temp->BusNumber == 0)) {
+ return FALSE;
+ }
+
+ //
+ // Skip VGA
+ //
+ if (IS_PCI_VGA (&Temp->Pci)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+PCI_RESOURCE_NODE *
+GetLargerConsumerDevice (
+ IN PCI_RESOURCE_NODE *PciResNode1,
+ IN PCI_RESOURCE_NODE *PciResNode2
+ )
+/*++
+
+Routine Description:
+
+ Get the larger resource consumer
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResNode1 - add argument and description to function comment
+// TODO: PciResNode2 - add argument and description to function comment
+{
+ if (!PciResNode2) {
+ return PciResNode1;
+ }
+
+ if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || !(PciResNode2->PciDev->Parent)) \
+ && (PciResNode2->ResourceUsage != PciResUsagePadding) )
+ {
+ return PciResNode1;
+ }
+
+ if (!PciResNode1) {
+ return PciResNode2;
+ }
+
+ if ((PciResNode1->Length) > (PciResNode2->Length)) {
+ return PciResNode1;
+ }
+
+ return PciResNode2;
+
+}
+
+PCI_RESOURCE_NODE *
+GetMaxResourceConsumerDevice (
+ IN PCI_RESOURCE_NODE *ResPool
+ )
+/*++
+
+Routine Description:
+
+ Get the max resource consumer in the host resource pool
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: ResPool - add argument and description to function comment
+{
+ PCI_RESOURCE_NODE *Temp;
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *PciResNode;
+ PCI_RESOURCE_NODE *PPBResNode;
+
+ PciResNode = NULL;
+
+ CurrentLink = ResPool->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &ResPool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (!IsRejectiveDevice (Temp)) {
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+
+ if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (!Temp->PciDev->Parent)) \
+ && (Temp->ResourceUsage != PciResUsagePadding))
+ {
+ PPBResNode = GetMaxResourceConsumerDevice (Temp);
+ PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);
+ } else {
+ PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return PciResNode;
+}
+
+EFI_STATUS
+PciHostBridgeAdjustAllocation (
+ IN PCI_RESOURCE_NODE *IoPool,
+ IN PCI_RESOURCE_NODE *Mem32Pool,
+ IN PCI_RESOURCE_NODE *PMem32Pool,
+ IN PCI_RESOURCE_NODE *Mem64Pool,
+ IN PCI_RESOURCE_NODE *PMem64Pool,
+ IN UINT64 IoResStatus,
+ IN UINT64 Mem32ResStatus,
+ IN UINT64 PMem32ResStatus,
+ IN UINT64 Mem64ResStatus,
+ IN UINT64 PMem64ResStatus
+ )
+/*++
+
+Routine Description:
+
+ Adjust host bridge allocation so as to reduce resource requirement
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: IoPool - add argument and description to function comment
+// TODO: Mem32Pool - add argument and description to function comment
+// TODO: PMem32Pool - add argument and description to function comment
+// TODO: Mem64Pool - add argument and description to function comment
+// TODO: PMem64Pool - add argument and description to function comment
+// TODO: IoResStatus - add argument and description to function comment
+// TODO: Mem32ResStatus - add argument and description to function comment
+// TODO: PMem32ResStatus - add argument and description to function comment
+// TODO: Mem64ResStatus - add argument and description to function comment
+// TODO: PMem64ResStatus - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ BOOLEAN AllocationAjusted;
+ PCI_RESOURCE_NODE *PciResNode;
+ PCI_RESOURCE_NODE *ResPool[5];
+ PCI_IO_DEVICE *RemovedPciDev[5];
+ UINT64 ResStatus[5];
+ UINTN RemovedPciDevNum;
+ UINTN DevIndex;
+ UINTN ResType;
+ EFI_STATUS Status;
+ REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;
+
+ PciResNode = NULL;
+ ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
+ RemovedPciDevNum = 0;
+
+ ResPool[0] = IoPool;
+ ResPool[1] = Mem32Pool;
+ ResPool[2] = PMem32Pool;
+ ResPool[3] = Mem64Pool;
+ ResPool[4] = PMem64Pool;
+
+ ResStatus[0] = IoResStatus;
+ ResStatus[1] = Mem32ResStatus;
+ ResStatus[2] = PMem32ResStatus;
+ ResStatus[3] = Mem64ResStatus;
+ ResStatus[4] = PMem64ResStatus;
+
+ AllocationAjusted = FALSE;
+
+ for (ResType = 0; ResType < 5; ResType++) {
+
+ if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
+ continue;
+ }
+
+ if (ResStatus[ResType] == EFI_RESOURCE_NONEXISTENT) {
+ //
+ // Hostbridge hasn't this resource type
+ //
+ return EFI_ABORTED;
+ }
+
+ //
+ // Hostbridge hasn't enough resource
+ //
+ PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
+ if (!PciResNode) {
+ continue;
+ }
+
+ //
+ // Check if the device has been removed before
+ //
+ for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
+ if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
+ continue;
+ }
+ }
+
+ //
+ // Remove the device if it isn't in the array
+ //
+ Status = RejectPciDevice (PciResNode->PciDev);
+ if (Status == EFI_SUCCESS) {
+
+ //
+ // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
+ //
+ //
+ // Have no way to get ReqRes, AllocRes & Bar here
+ //
+ ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
+ AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);
+ AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;
+ AllocFailExtendedData.Bar = PciResNode->Bar;
+
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
+ (VOID *) &AllocFailExtendedData,
+ sizeof (AllocFailExtendedData)
+ );
+
+ //
+ // Add it to the array and indicate at least a device has been rejected
+ //
+ RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;
+ AllocationAjusted = TRUE;
+ }
+ }
+ //
+ // End for
+ //
+
+ if (AllocationAjusted) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_ABORTED;
+ }
+}
+
+EFI_STATUS
+ConstructAcpiResourceRequestor (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *IoNode,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node,
+ OUT VOID **pConfig
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: IoNode - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: pConfig - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT8 NumConfig;
+ UINT8 Aperture;
+ UINT8 *Configuration;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
+
+ NumConfig = 0;
+ Aperture = 0;
+
+ *pConfig = NULL;
+
+ //
+ // if there is io request, add to the io aperture
+ //
+ if (ResourceRequestExisted (IoNode)) {
+ NumConfig++;
+ Aperture |= 0x01;
+ }
+
+ //
+ // if there is mem32 request, add to the mem32 aperture
+ //
+ if (ResourceRequestExisted (Mem32Node)) {
+ NumConfig++;
+ Aperture |= 0x02;
+ }
+
+ //
+ // if there is pmem32 request, add to the pmem32 aperture
+ //
+ if (ResourceRequestExisted (PMem32Node)) {
+ NumConfig++;
+ Aperture |= 0x04;
+ }
+
+ //
+ // if there is mem64 request, add to the mem64 aperture
+ //
+ if (ResourceRequestExisted (Mem64Node)) {
+ NumConfig++;
+ Aperture |= 0x08;
+ }
+
+ //
+ // if there is pmem64 request, add to the pmem64 aperture
+ //
+ if (ResourceRequestExisted (PMem64Node)) {
+ NumConfig++;
+ Aperture |= 0x10;
+ }
+
+ if (NumConfig != 0) {
+
+ //
+ // If there is at least one type of resource request,
+ // allocate a acpi resource node
+ //
+ Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Configuration == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (
+ Configuration,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+ //
+ // Deal with io aperture
+ //
+ if (Aperture & 0x01) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ //
+ // Io
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+ //
+ // non ISA range
+ //
+ Ptr->SpecificFlag = 1;
+ Ptr->AddrLen = IoNode->Length;
+ Ptr->AddrRangeMax = IoNode->Alignment;
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+ //
+ // Deal with mem32 aperture
+ //
+ if (Aperture & 0x02) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // Nonprefechable
+ //
+ Ptr->SpecificFlag = 0;
+ //
+ // 32 bit
+ //
+ Ptr->AddrSpaceGranularity = 32;
+ Ptr->AddrLen = Mem32Node->Length;
+ Ptr->AddrRangeMax = Mem32Node->Alignment;
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+
+ //
+ // Deal with Pmem32 aperture
+ //
+ if (Aperture & 0x04) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // prefechable
+ //
+ Ptr->SpecificFlag = 0x6;
+ //
+ // 32 bit
+ //
+ Ptr->AddrSpaceGranularity = 32;
+ Ptr->AddrLen = PMem32Node->Length;
+ Ptr->AddrRangeMax = PMem32Node->Alignment;
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+ //
+ // Deal with mem64 aperture
+ //
+ if (Aperture & 0x08) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // nonprefechable
+ //
+ Ptr->SpecificFlag = 0;
+ //
+ // 64 bit
+ //
+ Ptr->AddrSpaceGranularity = 64;
+ Ptr->AddrLen = Mem64Node->Length;
+ Ptr->AddrRangeMax = Mem64Node->Alignment;
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+ //
+ // Deal with Pmem64 aperture
+ //
+ if (Aperture & 0x10) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // prefechable
+ //
+ Ptr->SpecificFlag = 0x06;
+ //
+ // 64 bit
+ //
+ Ptr->AddrSpaceGranularity = 64;
+ Ptr->AddrLen = PMem64Node->Length;
+ Ptr->AddrRangeMax = PMem64Node->Alignment;
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+
+ //
+ // put the checksum
+ //
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);
+
+ PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ PtrEnd->Checksum = 0;
+
+ } else {
+
+ //
+ // If there is no resource request
+ //
+ Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Configuration == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (Configuration, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ PtrEnd->Checksum = 0;
+ }
+
+ *pConfig = Configuration;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetResourceBase (
+ IN VOID *pConfig,
+ OUT UINT64 *IoBase,
+ OUT UINT64 *Mem32Base,
+ OUT UINT64 *PMem32Base,
+ OUT UINT64 *Mem64Base,
+ OUT UINT64 *PMem64Base
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: pConfig - add argument and description to function comment
+// TODO: IoBase - add argument and description to function comment
+// TODO: Mem32Base - add argument and description to function comment
+// TODO: PMem32Base - add argument and description to function comment
+// TODO: Mem64Base - add argument and description to function comment
+// TODO: PMem64Base - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT8 *Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ UINT64 ResStatus;
+
+ *IoBase = 0xFFFFFFFFFFFFFFFFULL;
+ *Mem32Base = 0xFFFFFFFFFFFFFFFFULL;
+ *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
+ *Mem64Base = 0xFFFFFFFFFFFFFFFFULL;
+ *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
+
+ Temp = (UINT8 *) pConfig;
+
+ while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+ ResStatus = Ptr->AddrTranslationOffset;
+
+ if (ResStatus == EFI_RESOURCE_SATISFIED) {
+
+ switch (Ptr->ResType) {
+
+ //
+ // Memory type aperture
+ //
+ case 0:
+
+ //
+ // Check to see the granularity
+ //
+ if (Ptr->AddrSpaceGranularity == 32) {
+ if (Ptr->SpecificFlag & 0x06) {
+ *PMem32Base = Ptr->AddrRangeMin;
+ } else {
+ *Mem32Base = Ptr->AddrRangeMin;
+ }
+ }
+
+ if (Ptr->AddrSpaceGranularity == 64) {
+ if (Ptr->SpecificFlag & 0x06) {
+ *PMem64Base = Ptr->AddrRangeMin;
+ } else {
+ *Mem64Base = Ptr->AddrRangeMin;
+ }
+ }
+ break;
+
+ case 1:
+
+ //
+ // Io type aperture
+ //
+ *IoBase = Ptr->AddrRangeMin;
+ break;
+
+ default:
+ break;
+
+ }
+ //
+ // End switch
+ //
+ }
+ //
+ // End for
+ //
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciBridgeEnumerator (
+ IN PCI_IO_DEVICE *BridgeDev
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: BridgeDev - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT8 SubBusNumber;
+ UINT8 StartBusNumber;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ SubBusNumber = 0;
+ StartBusNumber = 0;
+ PciIo = &(BridgeDev->PciIo);
+ Status = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciAssignBusNumber (
+ BridgeDev,
+ StartBusNumber,
+ &SubBusNumber
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciBridgeResourceAllocator (BridgeDev);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = DetermineDeviceAttribute (BridgeDev);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+PciBridgeResourceAllocator (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_RESOURCE_NODE *IoBridge;
+ PCI_RESOURCE_NODE *Mem32Bridge;
+ PCI_RESOURCE_NODE *PMem32Bridge;
+ PCI_RESOURCE_NODE *Mem64Bridge;
+ PCI_RESOURCE_NODE *PMem64Bridge;
+ UINT64 IoBase;
+ UINT64 Mem32Base;
+ UINT64 PMem32Base;
+ UINT64 Mem64Base;
+ UINT64 PMem64Base;
+ EFI_STATUS Status;
+
+ IoBridge = CreateResourceNode (
+ Bridge,
+ 0,
+ 0xFFF,
+ 0,
+ PciBarTypeIo16,
+ PciResUsageTypical
+ );
+
+ Mem32Bridge = CreateResourceNode (
+ Bridge,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem32,
+ PciResUsageTypical
+ );
+
+ PMem32Bridge = CreateResourceNode (
+ Bridge,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem32,
+ PciResUsageTypical
+ );
+
+ Mem64Bridge = CreateResourceNode (
+ Bridge,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem64,
+ PciResUsageTypical
+ );
+
+ PMem64Bridge = CreateResourceNode (
+ Bridge,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem64,
+ PciResUsageTypical
+ );
+
+ //
+ // Create resourcemap by going through all the devices subject to this root bridge
+ //
+ Status = CreateResourceMap (
+ Bridge,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GetResourceBaseFromBridge (
+ Bridge,
+ &IoBase,
+ &Mem32Base,
+ &PMem32Base,
+ &Mem64Base,
+ &PMem64Base
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Program IO resources
+ //
+ ProgramResource (
+ IoBase,
+ IoBridge
+ );
+
+ //
+ // Program Mem32 resources
+ //
+ ProgramResource (
+ Mem32Base,
+ Mem32Bridge
+ );
+
+ //
+ // Program PMem32 resources
+ //
+ ProgramResource (
+ PMem32Base,
+ PMem32Bridge
+ );
+
+ //
+ // Program Mem64 resources
+ //
+ ProgramResource (
+ Mem64Base,
+ Mem64Bridge
+ );
+
+ //
+ // Program PMem64 resources
+ //
+ ProgramResource (
+ PMem64Base,
+ PMem64Bridge
+ );
+
+ DestroyResourceTree (IoBridge);
+ DestroyResourceTree (Mem32Bridge);
+ DestroyResourceTree (PMem32Bridge);
+ DestroyResourceTree (PMem64Bridge);
+ DestroyResourceTree (Mem64Bridge);
+
+ gBS->FreePool (IoBridge);
+ gBS->FreePool (Mem32Bridge);
+ gBS->FreePool (PMem32Bridge);
+ gBS->FreePool (PMem64Bridge);
+ gBS->FreePool (Mem64Bridge);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetResourceBaseFromBridge (
+ IN PCI_IO_DEVICE *Bridge,
+ OUT UINT64 *IoBase,
+ OUT UINT64 *Mem32Base,
+ OUT UINT64 *PMem32Base,
+ OUT UINT64 *Mem64Base,
+ OUT UINT64 *PMem64Base
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: IoBase - add argument and description to function comment
+// TODO: Mem32Base - add argument and description to function comment
+// TODO: PMem32Base - add argument and description to function comment
+// TODO: Mem64Base - add argument and description to function comment
+// TODO: PMem64Base - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ if (!Bridge->Allocated) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *IoBase = gAllOne;
+ *Mem32Base = gAllOne;
+ *PMem32Base = gAllOne;
+ *Mem64Base = gAllOne;
+ *PMem64Base = gAllOne;
+
+ if (IS_PCI_BRIDGE (&Bridge->Pci)) {
+
+ if (Bridge->PciBar[PPB_IO_RANGE].Length) {
+ *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
+ }
+
+ if (Bridge->PciBar[PPB_MEM32_RANGE].Length) {
+ *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
+ }
+
+ if (Bridge->PciBar[PPB_PMEM32_RANGE].Length) {
+ *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
+ }
+
+ if (Bridge->PciBar[PPB_PMEM64_RANGE].Length) {
+ *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
+ } else {
+ *PMem64Base = gAllOne;
+ }
+
+ }
+
+ if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
+ if (Bridge->PciBar[P2C_IO_1].Length) {
+ *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
+ } else {
+ if (Bridge->PciBar[P2C_IO_2].Length) {
+ *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
+ }
+ }
+
+ if (Bridge->PciBar[P2C_MEM_1].Length) {
+ if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
+ *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
+ }
+
+ if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
+ *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
+ }
+ }
+
+ if (Bridge->PciBar[P2C_MEM_2].Length) {
+ if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
+ *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
+ }
+
+ if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
+ *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: Phase - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE HostBridgeHandle;
+ EFI_HANDLE RootBridgeHandle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ EFI_STATUS Status;
+
+ HostBridgeHandle = NULL;
+ RootBridgeHandle = NULL;
+ if (gPciPlatformProtocol != NULL) {
+ //
+ // Get Host Bridge Handle.
+ //
+ PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
+
+ //
+ // Get the rootbridge Io protocol to find the host bridge handle
+ //
+ Status = gBS->HandleProtocol (
+ RootBridgeHandle,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ HostBridgeHandle = PciRootBridgeIo->ParentHandle;
+
+ //
+ // Call PlatformPci::PhaseNotify() if the protocol is present.
+ //
+ gPciPlatformProtocol->PhaseNotify (
+ gPciPlatformProtocol,
+ HostBridgeHandle,
+ Phase,
+ ChipsetEntry
+ );
+ }
+
+ Status = PciResAlloc->NotifyPhase (
+ PciResAlloc,
+ Phase
+ );
+
+ if (gPciPlatformProtocol != NULL) {
+ //
+ // Call PlatformPci::PhaseNotify() if the protocol is present.
+ //
+ gPciPlatformProtocol->PhaseNotify (
+ gPciPlatformProtocol,
+ HostBridgeHandle,
+ Phase,
+ ChipsetExit
+ );
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PreprocessController (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Func,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+// TODO: Phase - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
+ EFI_HANDLE RootBridgeHandle;
+ EFI_HANDLE HostBridgeHandle;
+ EFI_STATUS Status;
+
+ //
+ // Get the host bridge handle
+ //
+ HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
+
+ //
+ // Get the pci host bridge resource allocation protocol
+ //
+ Status = gBS->OpenProtocol (
+ HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+ (VOID **) &PciResAlloc,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get Root Brige Handle
+ //
+ while (Bridge->Parent) {
+ Bridge = Bridge->Parent;
+ }
+
+ RootBridgeHandle = Bridge->Handle;
+
+ RootBridgePciAddress.Register = 0;
+ RootBridgePciAddress.Function = Func;
+ RootBridgePciAddress.Device = Device;
+ RootBridgePciAddress.Bus = Bus;
+ RootBridgePciAddress.ExtendedRegister = 0;
+
+ if (gPciPlatformProtocol != NULL) {
+ //
+ // Call PlatformPci::PrepController() if the protocol is present.
+ //
+ gPciPlatformProtocol->PlatformPrepController (
+ gPciPlatformProtocol,
+ HostBridgeHandle,
+ RootBridgeHandle,
+ RootBridgePciAddress,
+ Phase,
+ ChipsetEntry
+ );
+ }
+
+ Status = PciResAlloc->PreprocessController (
+ PciResAlloc,
+ RootBridgeHandle,
+ RootBridgePciAddress,
+ Phase
+ );
+
+ if (gPciPlatformProtocol != NULL) {
+ //
+ // Call PlatformPci::PrepController() if the protocol is present.
+ //
+ gPciPlatformProtocol->PlatformPrepController (
+ gPciPlatformProtocol,
+ HostBridgeHandle,
+ RootBridgeHandle,
+ RootBridgePciAddress,
+ Phase,
+ ChipsetExit
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciHotPlugRequestNotify (
+ IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
+ IN EFI_PCI_HOTPLUG_OPERATION Operation,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,
+ IN OUT UINT8 *NumberOfChildren,
+ IN OUT EFI_HANDLE * ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ Hot plug request notify.
+
+Arguments:
+
+ This - A pointer to the hot plug request protocol.
+ Operation - The operation.
+ Controller - A pointer to the controller.
+ RemainningDevicePath - A pointer to the device path.
+ NumberOfChildren - A the number of child handle in the ChildHandleBuffer.
+ ChildHandleBuffer - A pointer to the array contain the child handle.
+
+Returns:
+
+ Status code.
+
+--*/
+// TODO: RemainingDevicePath - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Bridge;
+ PCI_IO_DEVICE *Temp;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Index;
+ EFI_HANDLE RootBridgeHandle;
+ EFI_STATUS Status;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
+
+ //
+ // Get root bridge handle
+ //
+ Temp = Bridge;
+ while (Temp->Parent) {
+ Temp = Temp->Parent;
+ }
+
+ RootBridgeHandle = Temp->Handle;
+
+ if (Operation == EfiPciHotPlugRequestAdd) {
+
+ if (NumberOfChildren != NULL) {
+ *NumberOfChildren = 0;
+ }
+
+ if (IsListEmpty (&Bridge->ChildList)) {
+
+ Status = PciBridgeEnumerator (Bridge);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Status = StartPciDevicesOnBridge (
+ RootBridgeHandle,
+ Bridge,
+ RemainingDevicePath,
+ NumberOfChildren,
+ ChildHandleBuffer
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ if (Operation == EfiPciHotplugRequestRemove) {
+
+ if (*NumberOfChildren == 0) {
+ //
+ // Remove all devices on the bridge
+ //
+ Status = RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
+ return Status;
+
+ }
+
+ for (Index = 0; Index < *NumberOfChildren; Index++) {
+ //
+ // De register all the pci device
+ //
+ Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+ //
+ // End for
+ //
+ return EFI_SUCCESS;
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+SearchHostBridgeHandle (
+ IN EFI_HANDLE RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: RootBridgeHandle - add argument and description to function comment
+{
+ EFI_HANDLE HostBridgeHandle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ //
+ // Get the rootbridge Io protocol to find the host bridge handle
+ //
+ Status = gBS->OpenProtocol (
+ RootBridgeHandle,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ RootBridgeHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ HostBridgeHandle = PciRootBridgeIo->ParentHandle;
+ for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
+ if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+AddHostBridgeEnumerator (
+ IN EFI_HANDLE HostBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: HostBridgeHandle - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINTN Index;
+
+ if (!HostBridgeHandle) {
+ return EFI_ABORTED;
+ }
+
+ for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
+ if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
+ return EFI_ABORTED;
+ }
+ }
+
+ if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
+ gPciHostBrigeHandles[Index] = HostBridgeHandle;
+ gPciHostBridgeNumber++;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.h new file mode 100644 index 0000000000..e7667d5c49 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.h @@ -0,0 +1,628 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciEnumerator.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_ENUMERATOR_H
+#define _EFI_PCI_ENUMERATOR_H
+
+#include "PciResourceSupport.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
+
+--*/
+;
+
+EFI_STATUS
+PciRootBridgeEnumerator (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+ RootBridgeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProcessOptionRom (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT64 RomBase,
+ IN UINT64 MaxLength
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ RomBase - TODO: add argument description
+ MaxLength - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciAssignBusNumber (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ StartBusNumber - TODO: add argument description
+ SubBusNumber - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DetermineRootBridgeAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+ RootBridgeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+UINT64
+GetMaxOptionRomSize (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeDeviceAttribute (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourceAllocationStatus (
+ VOID *AcpiConfig,
+ OUT UINT64 *IoResStatus,
+ OUT UINT64 *Mem32ResStatus,
+ OUT UINT64 *PMem32ResStatus,
+ OUT UINT64 *Mem64ResStatus,
+ OUT UINT64 *PMem64ResStatus
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AcpiConfig - TODO: add argument description
+ IoResStatus - TODO: add argument description
+ Mem32ResStatus - TODO: add argument description
+ PMem32ResStatus - TODO: add argument description
+ Mem64ResStatus - TODO: add argument description
+ PMem64ResStatus - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RejectPciDevice (
+ IN PCI_IO_DEVICE *PciDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsRejectiveDevice (
+ IN PCI_RESOURCE_NODE *PciResNode
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResNode - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_RESOURCE_NODE *
+GetLargerConsumerDevice (
+ IN PCI_RESOURCE_NODE *PciResNode1,
+ IN PCI_RESOURCE_NODE *PciResNode2
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResNode1 - TODO: add argument description
+ PciResNode2 - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_RESOURCE_NODE *
+GetMaxResourceConsumerDevice (
+ IN PCI_RESOURCE_NODE *ResPool
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ResPool - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeAdjustAllocation (
+ IN PCI_RESOURCE_NODE *IoPool,
+ IN PCI_RESOURCE_NODE *Mem32Pool,
+ IN PCI_RESOURCE_NODE *PMem32Pool,
+ IN PCI_RESOURCE_NODE *Mem64Pool,
+ IN PCI_RESOURCE_NODE *PMem64Pool,
+ IN UINT64 IoResStatus,
+ IN UINT64 Mem32ResStatus,
+ IN UINT64 PMem32ResStatus,
+ IN UINT64 Mem64ResStatus,
+ IN UINT64 PMem64ResStatus
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IoPool - TODO: add argument description
+ Mem32Pool - TODO: add argument description
+ PMem32Pool - TODO: add argument description
+ Mem64Pool - TODO: add argument description
+ PMem64Pool - TODO: add argument description
+ IoResStatus - TODO: add argument description
+ Mem32ResStatus - TODO: add argument description
+ PMem32ResStatus - TODO: add argument description
+ Mem64ResStatus - TODO: add argument description
+ PMem64ResStatus - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ConstructAcpiResourceRequestor (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *IoNode,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node,
+ OUT VOID **pConfig
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+ pConfig - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourceBase (
+ IN VOID *pConfig,
+ OUT UINT64 *IoBase,
+ OUT UINT64 *Mem32Base,
+ OUT UINT64 *PMem32Base,
+ OUT UINT64 *Mem64Base,
+ OUT UINT64 *PMem64Base
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ pConfig - TODO: add argument description
+ IoBase - TODO: add argument description
+ Mem32Base - TODO: add argument description
+ PMem32Base - TODO: add argument description
+ Mem64Base - TODO: add argument description
+ PMem64Base - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciBridgeEnumerator (
+ IN PCI_IO_DEVICE *BridgeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ BridgeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciBridgeResourceAllocator (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourceBaseFromBridge (
+ IN PCI_IO_DEVICE *Bridge,
+ OUT UINT64 *IoBase,
+ OUT UINT64 *Mem32Base,
+ OUT UINT64 *PMem32Base,
+ OUT UINT64 *Mem64Base,
+ OUT UINT64 *PMem64Base
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ IoBase - TODO: add argument description
+ Mem32Base - TODO: add argument description
+ PMem32Base - TODO: add argument description
+ Mem64Base - TODO: add argument description
+ PMem64Base - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeP2CProcess (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+NotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+ Phase - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PreprocessController (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Func,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+ Phase - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciHotPlugRequestNotify (
+ IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
+ IN EFI_PCI_HOTPLUG_OPERATION Operation,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,
+ IN OUT UINT8 *NumberOfChildren,
+ IN OUT EFI_HANDLE * ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Operation - TODO: add argument description
+ Controller - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+ NumberOfChildren - TODO: add argument description
+ ChildHandleBuffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+SearchHostBridgeHandle (
+ IN EFI_HANDLE RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AddHostBridgeEnumerator (
+ IN EFI_HANDLE HostBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ HostBridgeHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c new file mode 100644 index 0000000000..8020ab120f --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c @@ -0,0 +1,2254 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciEnumeratorSupport.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+#include "PciEnumeratorSupport.h"
+#include "PciCommand.h"
+#include "PciIo.h"
+
+EFI_STATUS
+PciDevicePresent (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to check whether the pci device is present
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciRootBridgeIo - add argument and description to function comment
+// TODO: Pci - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ UINT64 Address;
+ EFI_STATUS Status;
+
+ //
+ // Create PCI address map in terms of Bus, Device and Func
+ //
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+ //
+ // Read the Vendor Id register
+ //
+ Status = PciRootBridgeIoRead (
+ PciRootBridgeIo,
+ NULL,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ Pci
+ );
+
+ if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
+
+ //
+ // Read the entire config header for the device
+ //
+
+ Status = PciRootBridgeIoRead (
+ PciRootBridgeIo,
+ NULL,
+ EfiPciWidthUint32,
+ Address,
+ sizeof (PCI_TYPE00) / sizeof (UINT32),
+ Pci
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+PciPciDeviceInfoCollector (
+ IN PCI_IO_DEVICE *Bridge,
+ UINT8 StartBusNumber
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: StartBusNumber - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 Pci;
+ UINT8 Device;
+ UINT8 Func;
+ UINT8 SecBus;
+ PCI_IO_DEVICE *PciIoDevice;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ Status = EFI_SUCCESS;
+ SecBus = 0;
+
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+ //
+ // Check to see whether PCI device is present
+ //
+
+ Status = PciDevicePresent (
+ Bridge->PciRootBridgeIo,
+ &Pci,
+ (UINT8) StartBusNumber,
+ (UINT8) Device,
+ (UINT8) Func
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Call back to host bridge function
+ //
+ PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);
+
+ //
+ // Collect all the information about the PCI device discovered
+ //
+ Status = PciSearchDevice (
+ Bridge,
+ &Pci,
+ (UINT8) StartBusNumber,
+ Device,
+ Func,
+ &PciIoDevice
+ );
+
+ //
+ // Recursively scan PCI busses on the other side of PCI-PCI bridges
+ //
+ //
+
+ if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
+
+ //
+ // If it is PPB, we need to get the secondary bus to continue the enumeration
+ //
+ PciIo = &(PciIoDevice->PciIo);
+
+ Status = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get resource padding for PPB
+ //
+ GetResourcePaddingPpb (PciIoDevice);
+
+ //
+ // Deep enumerate the next level bus
+ //
+ Status = PciPciDeviceInfoCollector (
+ PciIoDevice,
+ (UINT8) (SecBus)
+ );
+
+ }
+
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+ Func = PCI_MAX_FUNC;
+ }
+ }
+
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciSearchDevice (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Func,
+ OUT PCI_IO_DEVICE **PciDevice
+ )
+/*++
+
+Routine Description:
+
+ Search required device.
+
+Arguments:
+
+ Bridge - A pointer to the PCI_IO_DEVICE.
+ Pci - A pointer to the PCI_TYPE00.
+ Bus - Bus number.
+ Device - Device number.
+ Func - Function number.
+ PciDevice - The Required pci device.
+
+Returns:
+
+ Status code.
+
+--*/
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = NULL;
+
+ if (!IS_PCI_BRIDGE (Pci)) {
+
+ if (IS_CARDBUS_BRIDGE (Pci)) {
+ PciIoDevice = GatherP2CInfo (
+ Bridge,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+ if ((PciIoDevice != NULL) && gFullEnumeration) {
+ InitializeP2C (PciIoDevice);
+ }
+ } else {
+
+ //
+ // Create private data for Pci Device
+ //
+ PciIoDevice = GatherDeviceInfo (
+ Bridge,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+
+ }
+
+ } else {
+
+ //
+ // Create private data for PPB
+ //
+ PciIoDevice = GatherPpbInfo (
+ Bridge,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+
+ //
+ // Special initialization for PPB including making the PPB quiet
+ //
+ if ((PciIoDevice != NULL) && gFullEnumeration) {
+ InitializePpb (PciIoDevice);
+ }
+ }
+
+ if (!PciIoDevice) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Update the bar information for this PCI device so as to support some specific device
+ //
+ if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT) {
+ UpdatePciInfo (PciIoDevice);
+ }
+
+ if (PciIoDevice->DevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Detect this function has option rom
+ //
+ if (gFullEnumeration) {
+
+ if (!IS_CARDBUS_BRIDGE (Pci)) {
+
+ GetOpRomInfo (PciIoDevice);
+
+ }
+
+ ResetPowerManagementFeature (PciIoDevice);
+
+ }
+
+ //
+ // Insert it into a global tree for future reference
+ //
+ InsertPciDevice (Bridge, PciIoDevice);
+
+ //
+ // Determine PCI device attributes
+ //
+
+ if (PciDevice != NULL) {
+ *PciDevice = PciIoDevice;
+ }
+
+ return EFI_SUCCESS;
+}
+
+PCI_IO_DEVICE *
+GatherDeviceInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: Pci - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+{
+ UINTN Offset;
+ UINTN BarIndex;
+ PCI_IO_DEVICE *PciIoDevice;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ PciIoDevice = CreatePciIoDevice (
+ PciRootBridgeIo,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+
+ if (!PciIoDevice) {
+ return NULL;
+ }
+
+ //
+ // Create a device path for this PCI device and store it into its private data
+ //
+ CreatePciDevicePath (
+ Bridge->DevicePath,
+ PciIoDevice
+ );
+
+ //
+ // If it is a full enumeration, disconnect the device in advance
+ //
+ if (gFullEnumeration) {
+
+ PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
+
+ }
+
+ //
+ // Start to parse the bars
+ //
+ for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {
+ Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
+ }
+
+ return PciIoDevice;
+}
+
+PCI_IO_DEVICE *
+GatherPpbInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: Pci - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ PCI_IO_DEVICE *PciIoDevice;
+ EFI_STATUS Status;
+ UINT32 Value;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Temp;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ PciIoDevice = CreatePciIoDevice (
+ PciRootBridgeIo,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+
+ if (!PciIoDevice) {
+ return NULL;
+ }
+
+ //
+ // Create a device path for this PCI device and store it into its private data
+ //
+ CreatePciDevicePath (
+ Bridge->DevicePath,
+ PciIoDevice
+ );
+
+ if (gFullEnumeration) {
+ PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
+
+ //
+ // Initalize the bridge control register
+ //
+ PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
+
+ }
+
+ //
+ // PPB can have two BARs
+ //
+ if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {
+ //
+ // Not 64-bit bar
+ //
+ PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);
+ }
+
+ PciIo = &PciIoDevice->PciIo;
+
+ //
+ // Test whether it support 32 decode or not
+ //
+ PciIoRead (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
+ PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
+ PciIoRead (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
+ PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
+
+ if (Value) {
+ if (Value & 0x01) {
+ PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
+ } else {
+ PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
+ }
+ }
+
+ Status = BarExisted (
+ PciIoDevice,
+ 0x24,
+ NULL,
+ NULL
+ );
+
+ //
+ // test if it supports 64 memory or not
+ //
+ if (!EFI_ERROR (Status)) {
+
+ Status = BarExisted (
+ PciIoDevice,
+ 0x28,
+ NULL,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+ PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
+ } else {
+ PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+ }
+ }
+
+ //
+ // Memory 32 code is required for ppb
+ //
+ PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
+
+ GetResourcePaddingPpb (PciIoDevice);
+
+ return PciIoDevice;
+}
+
+PCI_IO_DEVICE *
+GatherP2CInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: Pci - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ PciIoDevice = CreatePciIoDevice (
+ PciRootBridgeIo,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+
+ if (!PciIoDevice) {
+ return NULL;
+ }
+
+ //
+ // Create a device path for this PCI device and store it into its private data
+ //
+ CreatePciDevicePath (
+ Bridge->DevicePath,
+ PciIoDevice
+ );
+
+ if (gFullEnumeration) {
+ PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
+
+ //
+ // Initalize the bridge control register
+ //
+ PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
+
+ }
+ //
+ // P2C only has one bar that is in 0x10
+ //
+ PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);
+
+ //
+ // Read PciBar information from the bar register
+ //
+ GetBackPcCardBar (PciIoDevice);
+ PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
+ EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
+ EFI_BRIDGE_IO32_DECODE_SUPPORTED;
+
+ return PciIoDevice;
+}
+
+EFI_DEVICE_PATH_PROTOCOL *
+CreatePciDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: ParentDevicePath - add argument and description to function comment
+// TODO: PciIoDevice - add argument and description to function comment
+{
+
+ PCI_DEVICE_PATH PciNode;
+
+ //
+ // Create PCI device path
+ //
+ PciNode.Header.Type = HARDWARE_DEVICE_PATH;
+ PciNode.Header.SubType = HW_PCI_DP;
+ SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
+
+ PciNode.Device = PciIoDevice->DeviceNumber;
+ PciNode.Function = PciIoDevice->FunctionNumber;
+ PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
+
+ return PciIoDevice->DevicePath;
+}
+
+EFI_STATUS
+BarExisted (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINTN Offset,
+ OUT UINT32 *BarLengthValue,
+ OUT UINT32 *OriginalBarValue
+ )
+/*++
+
+Routine Description:
+
+ Check the bar is existed or not.
+
+Arguments:
+
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+ Offset - The offset.
+ BarLengthValue - The bar length value.
+ OriginalBarValue - The original bar value.
+
+Returns:
+
+ EFI_NOT_FOUND - The bar don't exist.
+ EFI_SUCCESS - The bar exist.
+
+--*/
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 OriginalValue;
+ UINT32 Value;
+ EFI_TPL OldTpl;
+
+ PciIo = &PciIoDevice->PciIo;
+
+ //
+ // Preserve the original value
+ //
+
+ PciIoRead (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
+
+ //
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed
+ //
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
+ PciIoRead (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
+
+ //
+ // Write back the original value
+ //
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
+
+ //
+ // Restore TPL to its original level
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ if (BarLengthValue != NULL) {
+ *BarLengthValue = Value;
+ }
+
+ if (OriginalBarValue != NULL) {
+ *OriginalBarValue = OriginalValue;
+ }
+
+ if (Value == 0) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+EFI_STATUS
+PciTestSupportedAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 *Command,
+ IN UINT16 *BridgeControl,
+ IN UINT16 *OldCommand,
+ IN UINT16 *OldBridgeControl
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Command - add argument and description to function comment
+// TODO: BridgeControl - add argument and description to function comment
+// TODO: OldCommand - add argument and description to function comment
+// TODO: OldBridgeControl - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_TPL OldTpl;
+
+ //
+ // Preserve the original value
+ //
+ PciReadCommandRegister (PciIoDevice, OldCommand);
+
+ //
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed
+ //
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ PciSetCommandRegister (PciIoDevice, *Command);
+ PciReadCommandRegister (PciIoDevice, Command);
+
+ //
+ // Write back the original value
+ //
+ PciSetCommandRegister (PciIoDevice, *OldCommand);
+
+ //
+ // Restore TPL to its original level
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+
+ //
+ // Preserve the original value
+ //
+ PciReadBridgeControlRegister (PciIoDevice, OldBridgeControl);
+
+ //
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed
+ //
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ PciSetBridgeControlRegister (PciIoDevice, *BridgeControl);
+ PciReadBridgeControlRegister (PciIoDevice, BridgeControl);
+
+ //
+ // Write back the original value
+ //
+ PciSetBridgeControlRegister (PciIoDevice, *OldBridgeControl);
+
+ //
+ // Restore TPL to its original level
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ } else {
+ *OldBridgeControl = 0;
+ *BridgeControl = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciSetDeviceAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 Command,
+ IN UINT16 BridgeControl,
+ IN UINTN Option
+ )
+/*++
+
+ Routine Description:
+ Set the supported or current attributes of a PCI device
+
+ Arguments:
+ PciIoDevice - Structure pointer for PCI device.
+ Command - Command register value.
+ BridgeControl - Bridge control value for PPB or P2C.
+ Option - Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
+
+ Returns:
+
+--*/
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+Returns:
+
+ EFI_SUCCESS Always success
+
+
+--*/
+{
+ UINT64 Attributes;
+
+ Attributes = 0;
+
+ if (Command & EFI_PCI_COMMAND_IO_SPACE) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
+ }
+
+ if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
+ }
+
+ if (Command & EFI_PCI_COMMAND_BUS_MASTER) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
+ }
+
+ if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+ }
+
+ if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
+ }
+
+ if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+ }
+
+ if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;
+ }
+
+ if (Option == EFI_SET_SUPPORTS) {
+
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |
+ EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |
+ EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |
+ EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
+ EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_IO) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
+ }
+
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+ //
+ // For bridge, it should support IDE attributes
+ //
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
+ } else {
+
+ if (IS_PCI_IDE (&PciIoDevice->Pci)) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
+ }
+
+ if (IS_PCI_VGA (&PciIoDevice->Pci)) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
+ }
+ }
+
+ PciIoDevice->Supports = Attributes;
+ PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \
+ EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \
+ EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );
+
+ } else {
+ PciIoDevice->Attributes = Attributes;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetFastBackToBackSupport (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT8 StatusIndex
+ )
+/*++
+
+Routine Description:
+
+ Determine if the device can support Fast Back to Back attribute
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: StatusIndex - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ UINT32 StatusRegister;
+
+ //
+ // Read the status register
+ //
+ PciIo = &PciIoDevice->PciIo;
+ Status = PciIoRead (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check the Fast B2B bit
+ //
+ if (StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+}
+
+STATIC
+EFI_STATUS
+ProcessOptionRomLight (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Process the option ROM for all the children of the specified parent PCI device.
+ It can only be used after the first full Option ROM process.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Temp;
+ LIST_ENTRY *CurrentLink;
+
+ //
+ // For RootBridge, PPB , P2C, go recursively to traverse all its children
+ //
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ ProcessOptionRomLight (Temp);
+ }
+
+ PciRomGetImageMapping (Temp);
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DetermineDeviceAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Determine the related attributes of all devices under a Root Bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT16 Command;
+ UINT16 BridgeControl;
+ UINT16 OldCommand;
+ UINT16 OldBridgeControl;
+ BOOLEAN FastB2BSupport;
+
+ /*
+ UINT8 IdePI;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ */
+ PCI_IO_DEVICE *Temp;
+ LIST_ENTRY *CurrentLink;
+ EFI_STATUS Status;
+
+ //
+ // For Root Bridge, just copy it by RootBridgeIo proctocol
+ // so as to keep consistent with the actual attribute
+ //
+ if (!PciIoDevice->Parent) {
+ Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
+ PciIoDevice->PciRootBridgeIo,
+ &PciIoDevice->Supports,
+ &PciIoDevice->Attributes
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+
+ //
+ // Set the attributes to be checked for common PCI devices and PPB or P2C
+ // Since some devices only support part of them, it is better to set the
+ // attribute according to its command or bridge control register
+ //
+ Command = EFI_PCI_COMMAND_IO_SPACE |
+ EFI_PCI_COMMAND_MEMORY_SPACE |
+ EFI_PCI_COMMAND_BUS_MASTER |
+ EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+
+ BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;
+
+ //
+ // Test whether the device can support attributes above
+ //
+ PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);
+
+ //
+ // Set the supported attributes for specified PCI device
+ //
+ PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);
+
+ //
+ // Set the current attributes for specified PCI device
+ //
+ PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);
+
+ //
+ // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
+ //
+ PciEnableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);
+
+ //
+ // Enable IDE native mode
+ //
+ /*
+ if (IS_PCI_IDE(&PciIoDevice->Pci)) {
+
+ PciIo = &PciIoDevice->PciIo;
+
+ PciIoRead (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0x09,
+ 1,
+ &IdePI
+ );
+
+ //
+ // Set native mode if it can be supported
+ //
+ IdePI |= (((IdePI & 0x0F) >> 1) & 0x05);
+
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0x09,
+ 1,
+ &IdePI
+ );
+
+ }
+ */
+ }
+
+ FastB2BSupport = TRUE;
+
+ //
+ // P2C can not support FB2B on the secondary side
+ //
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+ FastB2BSupport = FALSE;
+ }
+
+ //
+ // For RootBridge, PPB , P2C, go recursively to traverse all its children
+ //
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ Status = DetermineDeviceAttribute (Temp);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Detect Fast Bact to Bact support for the device under the bridge
+ //
+ Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);
+ if (FastB2BSupport && EFI_ERROR (Status)) {
+ FastB2BSupport = FALSE;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+ //
+ // Set or clear Fast Back to Back bit for the whole bridge
+ //
+ if (!IsListEmpty (&PciIoDevice->ChildList)) {
+
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+
+ Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);
+
+ if (EFI_ERROR (Status) || (!FastB2BSupport)) {
+ FastB2BSupport = FALSE;
+ PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
+ } else {
+ PciEnableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
+ }
+ }
+
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ if (FastB2BSupport) {
+ PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
+ } else {
+ PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+ }
+ //
+ // End for IsListEmpty
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdatePciInfo (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to update the bar information for those incompatible PCI device
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ UINTN BarIndex;
+ UINTN BarEndIndex;
+ BOOLEAN SetFlag;
+ EFI_PCI_DEVICE_INFO PciDeviceInfo;
+ VOID *Configuration;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+
+ Configuration = NULL;
+
+ //
+ // Check whether the device belongs to incompatible devices or not
+ // If it is , then get its special requirement in the ACPI table
+ //
+ PciDeviceInfo.VendorID = PciIoDevice->Pci.Hdr.VendorId;
+ PciDeviceInfo.DeviceID = PciIoDevice->Pci.Hdr.DeviceId;
+ PciDeviceInfo.RevisionID = PciIoDevice->Pci.Hdr.RevisionID;
+ PciDeviceInfo.SubsystemVendorID = PciIoDevice->Pci.Device.SubsystemVendorID;
+ PciDeviceInfo.SubsystemID = PciIoDevice->Pci.Device.SubsystemID;
+
+ Status = PciResourceUpdateCheck (&PciDeviceInfo, &Configuration);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Update PCI device information from the ACPI table
+ //
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+ while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {
+
+ if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ //
+ // The format is not support
+ //
+ break;
+ }
+
+ BarIndex = (UINTN) Ptr->AddrTranslationOffset;
+ BarEndIndex = BarIndex;
+
+ //
+ // Update all the bars in the device
+ //
+ if (BarIndex == PCI_BAR_ALL) {
+ BarIndex = 0;
+ BarEndIndex = PCI_MAX_BAR - 1;
+ }
+
+ if (BarIndex >= PCI_MAX_BAR) {
+ Ptr++;
+ continue;
+ }
+
+ for (; BarIndex <= BarEndIndex; BarIndex++) {
+ SetFlag = FALSE;
+ switch (Ptr->ResType) {
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:
+
+ //
+ // Make sure the bar is memory type
+ //
+ if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {
+ SetFlag = TRUE;
+ }
+ break;
+
+ case ACPI_ADDRESS_SPACE_TYPE_IO:
+
+ //
+ // Make sure the bar is IO type
+ //
+ if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {
+ SetFlag = TRUE;
+ }
+ break;
+ }
+
+ if (SetFlag) {
+
+ //
+ // Update the new alignment for the device
+ //
+ SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);
+
+ //
+ // Update the new length for the device
+ //
+ if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {
+ PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;
+ }
+ }
+ }
+
+ Ptr++;
+ }
+
+ gBS->FreePool (Configuration);
+ return Status;
+
+}
+
+VOID
+SetNewAlign (
+ IN UINT64 *Alignment,
+ IN UINT64 NewAlignment
+ )
+/*++
+
+Routine Description:
+
+ This routine will update the alignment with the new alignment
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Alignment - add argument and description to function comment
+// TODO: NewAlignment - add argument and description to function comment
+{
+ UINT64 OldAlignment;
+ UINTN ShiftBit;
+
+ //
+ // The new alignment is the same as the original,
+ // so skip it
+ //
+ if (NewAlignment == PCI_BAR_OLD_ALIGN) {
+ return ;
+ }
+ //
+ // Check the validity of the parameter
+ //
+ if (NewAlignment != PCI_BAR_EVEN_ALIGN &&
+ NewAlignment != PCI_BAR_SQUAD_ALIGN &&
+ NewAlignment != PCI_BAR_DQUAD_ALIGN ) {
+ *Alignment = NewAlignment;
+ return ;
+ }
+
+ OldAlignment = (*Alignment) + 1;
+ ShiftBit = 0;
+
+ //
+ // Get the first non-zero hex value of the length
+ //
+ while ((OldAlignment & 0x0F) == 0x00) {
+ OldAlignment = RShiftU64 (OldAlignment, 4);
+ ShiftBit += 4;
+ }
+
+ //
+ // Adjust the alignment to even, quad or double quad boundary
+ //
+ if (NewAlignment == PCI_BAR_EVEN_ALIGN) {
+ if (OldAlignment & 0x01) {
+ OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);
+ }
+ } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {
+ if (OldAlignment & 0x03) {
+ OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);
+ }
+ } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {
+ if (OldAlignment & 0x07) {
+ OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);
+ }
+ }
+
+ //
+ // Update the old value
+ //
+ NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;
+ *Alignment = NewAlignment;
+
+ return ;
+}
+
+UINTN
+PciParseBar (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINTN Offset,
+ IN UINTN BarIndex
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+{
+ UINT32 Value;
+ UINT32 OriginalValue;
+ UINT32 Mask;
+ UINT32 Data;
+ UINT8 Index;
+ EFI_STATUS Status;
+
+ OriginalValue = 0;
+ Value = 0;
+
+ Status = BarExisted (
+ PciIoDevice,
+ Offset,
+ &Value,
+ &OriginalValue
+ );
+
+ if (EFI_ERROR (Status)) {
+ PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
+ PciIoDevice->PciBar[BarIndex].Length = 0;
+ PciIoDevice->PciBar[BarIndex].Alignment = 0;
+
+ //
+ // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
+ //
+ PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
+ return Offset + 4;
+ }
+
+ PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
+ if (Value & 0x01) {
+ //
+ // Device I/Os
+ //
+ Mask = 0xfffffffc;
+
+ if (Value & 0xFFFF0000) {
+ //
+ // It is a IO32 bar
+ //
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
+ PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ } else {
+ //
+ // It is a IO16 bar
+ //
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
+ PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ }
+ //
+ // Workaround. Some platforms inplement IO bar with 0 length
+ // Need to treat it as no-bar
+ //
+ if (PciIoDevice->PciBar[BarIndex].Length == 0) {
+ PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;
+ }
+
+ PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;
+ PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
+
+ } else {
+
+ Mask = 0xfffffff0;
+
+ PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
+
+ switch (Value & 0x07) {
+
+ //
+ //memory space; anywhere in 32 bit address space
+ //
+ case 0x00:
+ if (Value & 0x08) {
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
+ } else {
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
+ }
+
+ PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ break;
+
+ //
+ // memory space; anywhere in 64 bit address space
+ //
+ case 0x04:
+ if (Value & 0x08) {
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
+ } else {
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
+ }
+
+ //
+ // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
+ // is regarded as an extension for the first bar. As a result
+ // the sizing will be conducted on combined 64 bit value
+ // Here just store the masked first 32bit value for future size
+ // calculation
+ //
+ PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ //
+ // Increment the offset to point to next DWORD
+ //
+ Offset += 4;
+
+ Status = BarExisted (
+ PciIoDevice,
+ Offset,
+ &Value,
+ &OriginalValue
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Offset + 4;
+ }
+
+ //
+ // Fix the length to support some spefic 64 bit BAR
+ //
+ Data = Value;
+ Index = 0;
+ for (Data = Value; Data != 0; Data >>= 1) {
+ Index ++;
+ }
+ Value |= ((UINT32)(-1) << Index);
+
+ //
+ // Calculate the size of 64bit bar
+ //
+ PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
+
+ PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
+ PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ break;
+
+ //
+ // reserved
+ //
+ default:
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
+ PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ break;
+ }
+ }
+
+ //
+ // Check the length again so as to keep compatible with some special bars
+ //
+ if (PciIoDevice->PciBar[BarIndex].Length == 0) {
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
+ PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
+ PciIoDevice->PciBar[BarIndex].Alignment = 0;
+ }
+
+ //
+ // Increment number of bar
+ //
+ return Offset + 4;
+}
+
+EFI_STATUS
+InitializePciDevice (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to initialize the bar of a PCI device
+ It can be called typically when a device is going to be rejected
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Offset;
+
+ PciIo = &(PciIoDevice->PciIo);
+
+ //
+ // Put all the resource apertures
+ // Resource base is set to all ones so as to indicate its resource
+ // has not been alloacted
+ //
+ for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializePpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ PciIo = &(PciIoDevice->PciIo);
+
+ //
+ // Put all the resource apertures including IO16
+ // Io32, pMem32, pMem64 to quiescent state
+ // Resource base all ones, Resource limit all zeros
+ //
+ PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
+ PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
+
+ PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
+ PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
+
+ PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
+ PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
+
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
+
+ //
+ // don't support use io32 as for now
+ //
+ PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
+ PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
+
+ //
+ // Force Interrupt line to zero for cards that come up randomly
+ //
+ PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializeP2C (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ PciIo = &(PciIoDevice->PciIo);
+
+ //
+ // Put all the resource apertures including IO16
+ // Io32, pMem32, pMem64 to quiescent state(
+ // Resource base all ones, Resource limit all zeros
+ //
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
+
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
+
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
+
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
+
+ //
+ // Force Interrupt line to zero for cards that come up randomly
+ //
+ PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
+ return EFI_SUCCESS;
+}
+
+PCI_IO_DEVICE *
+CreatePciIoDevice (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciRootBridgeIo - add argument and description to function comment
+// TODO: Pci - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+{
+
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = NULL;
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (PCI_IO_DEVICE),
+ (VOID **) &PciIoDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));
+
+ PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
+ PciIoDevice->Handle = NULL;
+ PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;
+ PciIoDevice->DevicePath = NULL;
+ PciIoDevice->BusNumber = Bus;
+ PciIoDevice->DeviceNumber = Device;
+ PciIoDevice->FunctionNumber = Func;
+ PciIoDevice->Decodes = 0;
+ if (gFullEnumeration) {
+ PciIoDevice->Allocated = FALSE;
+ } else {
+ PciIoDevice->Allocated = TRUE;
+ }
+
+ PciIoDevice->Registered = FALSE;
+ PciIoDevice->Attributes = 0;
+ PciIoDevice->Supports = 0;
+ PciIoDevice->BusOverride = FALSE;
+ PciIoDevice->AllOpRomProcessed = FALSE;
+
+ PciIoDevice->IsPciExp = FALSE;
+
+ CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
+
+ //
+ // Initialize the PCI I/O instance structure
+ //
+
+ Status = InitializePciIoInstance (PciIoDevice);
+ Status = InitializePciDriverOverrideInstance (PciIoDevice);
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (PciIoDevice);
+ return NULL;
+ }
+
+ //
+ // Initialize the reserved resource list
+ //
+ InitializeListHead (&PciIoDevice->ReservedResourceList);
+
+ //
+ // Initialize the driver list
+ //
+ InitializeListHead (&PciIoDevice->OptionRomDriverList);
+
+ //
+ // Initialize the child list
+ //
+ InitializeListHead (&PciIoDevice->ChildList);
+
+ return PciIoDevice;
+}
+
+EFI_STATUS
+PciEnumeratorLight (
+ IN EFI_HANDLE Controller
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to enumerate entire pci bus system
+ in a given platform
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Controller - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ PCI_IO_DEVICE *RootBridgeDev;
+ UINT16 MinBus;
+ UINT16 MaxBus;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+ MinBus = 0;
+ MaxBus = PCI_MAX_BUS;
+ Descriptors = NULL;
+
+ //
+ // If this host bridge has been already enumerated, then return successfully
+ //
+ if (RootBridgeExisted (Controller)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Open pci root bridge io protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ return Status;
+ }
+
+ Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
+
+ //
+ // Create a device node for root bridge device with a NULL host bridge controller handle
+ //
+ RootBridgeDev = CreateRootBridge (Controller);
+
+ if (!RootBridgeDev) {
+ Descriptors++;
+ continue;
+ }
+
+ //
+ // Record the root bridge io protocol
+ //
+ RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
+
+ Status = PciPciDeviceInfoCollector (
+ RootBridgeDev,
+ (UINT8) MinBus
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Remove those PCI devices which are rejected when full enumeration
+ //
+ RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);
+
+ //
+ // Process option rom light
+ //
+ ProcessOptionRomLight (RootBridgeDev);
+
+ //
+ // Determine attributes for all devices under this root bridge
+ //
+ DetermineDeviceAttribute (RootBridgeDev);
+
+ //
+ // If successfully, insert the node into device pool
+ //
+ InsertRootBridge (RootBridgeDev);
+ } else {
+
+ //
+ // If unsuccessly, destroy the entire node
+ //
+ DestroyRootBridge (RootBridgeDev);
+ }
+
+ Descriptors++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciGetBusRange (
+ IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
+ OUT UINT16 *MinBus,
+ OUT UINT16 *MaxBus,
+ OUT UINT16 *BusRange
+ )
+/*++
+
+Routine Description:
+
+ Get the bus range.
+
+Arguments:
+
+ Descriptors - A pointer to the address space descriptor.
+ MinBus - The min bus.
+ MaxBus - The max bus.
+ BusRange - The bus range.
+
+Returns:
+
+ Status Code.
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+
+ while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
+ if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ if (MinBus != NULL) {
+ *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;
+ }
+
+ if (MaxBus != NULL) {
+ *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;
+ }
+
+ if (BusRange != NULL) {
+ *BusRange = (UINT16) (*Descriptors)->AddrLen;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ (*Descriptors)++;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+StartManagingRootBridge (
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: RootBridgeDev - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE RootBridgeHandle;
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ //
+ // Get the root bridge handle
+ //
+ RootBridgeHandle = RootBridgeDev->Handle;
+ PciRootBridgeIo = NULL;
+
+ //
+ // Get the pci root bridge io protocol
+ //
+ Status = gBS->OpenProtocol (
+ RootBridgeHandle,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ RootBridgeHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ return Status;
+ }
+
+ //
+ // Store the PciRootBridgeIo protocol into root bridge private data
+ //
+ RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
+
+ return EFI_SUCCESS;
+
+}
+
+BOOLEAN
+IsPciDeviceRejected (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ This routine can be used to check whether a PCI device should be rejected when light enumeration
+
+Arguments:
+
+Returns:
+
+ TRUE This device should be rejected
+ FALSE This device shouldn't be rejected
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ UINT32 TestValue;
+ UINT32 OldValue;
+ UINT32 Mask;
+ UINT8 BarOffset;
+
+ //
+ // PPB should be skip!
+ //
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+ return FALSE;
+ }
+
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+ //
+ // Only test base registers for P2C
+ //
+ for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {
+
+ Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
+ Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ TestValue = TestValue & Mask;
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+ //
+ // The bar isn't programed, so it should be rejected
+ //
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
+
+ for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {
+ //
+ // Test PCI devices
+ //
+ Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (TestValue & 0x01) {
+
+ //
+ // IO Bar
+ //
+
+ Mask = 0xFFFFFFFC;
+ TestValue = TestValue & Mask;
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+ return TRUE;
+ }
+
+ } else {
+
+ //
+ // Mem Bar
+ //
+
+ Mask = 0xFFFFFFF0;
+ TestValue = TestValue & Mask;
+
+ if ((TestValue & 0x07) == 0x04) {
+
+ //
+ // Mem64 or PMem64
+ //
+ BarOffset += sizeof (UINT32);
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+
+ //
+ // Test its high 32-Bit BAR
+ //
+
+ Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
+ if (TestValue == OldValue) {
+ return TRUE;
+ }
+ }
+
+ } else {
+
+ //
+ // Mem32 or PMem32
+ //
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+ResetAllPpbBusReg (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ StartBusNumber - TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 Pci;
+ UINT8 Device;
+ UINT32 Register;
+ UINT8 Func;
+ UINT64 Address;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+ //
+ // Check to see whether a pci device is present
+ //
+ Status = PciDevicePresent (
+ PciRootBridgeIo,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func
+ );
+
+ if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {
+ Register = 0;
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
+ Status = PciRootBridgeIoRead (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ &Register
+ );
+ //
+ // Reset register 18h, 19h, 1Ah on PCI Bridge
+ //
+ Register &= 0xFF000000;
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ &Register
+ );
+ }
+
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+ Func = PCI_MAX_FUNC;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.h new file mode 100644 index 0000000000..41d6efb102 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.h @@ -0,0 +1,598 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciEnumeratorSupport.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H
+#define _EFI_PCI_ENUMERATOR_SUPPORT_H
+
+EFI_STATUS
+PciDevicePresent (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciRootBridgeIo - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+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
+PciSearchDevice (
+ IN PCI_IO_DEVICE *Bridge,
+ PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func,
+ PCI_IO_DEVICE **PciDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+ PciDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+GatherDeviceInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+GatherPpbInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+GatherP2CInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_DEVICE_PATH_PROTOCOL *
+CreatePciDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ParentDevicePath - TODO: add argument description
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+BarExisted (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINTN Offset,
+ OUT UINT32 *BarLengthValue,
+ OUT UINT32 *OriginalBarValue
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Offset - TODO: add argument description
+ BarLengthValue - TODO: add argument description
+ OriginalBarValue - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciTestSupportedAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 *Command,
+ IN UINT16 *BridgeControl,
+ IN UINT16 *OldCommand,
+ IN UINT16 *OldBridgeControl
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Command - TODO: add argument description
+ BridgeControl - TODO: add argument description
+ OldCommand - TODO: add argument description
+ OldBridgeControl - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciSetDeviceAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 Command,
+ IN UINT16 BridgeControl,
+ IN UINTN Option
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Command - TODO: add argument description
+ BridgeControl - TODO: add argument description
+ Option - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetFastBackToBackSupport (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT8 StatusIndex
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ StatusIndex - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DetermineDeviceAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+UpdatePciInfo (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+SetNewAlign (
+ IN UINT64 *Alignment,
+ IN UINT64 NewAlignment
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Alignment - TODO: add argument description
+ NewAlignment - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+UINTN
+PciParseBar (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINTN Offset,
+ IN UINTN BarIndex
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Offset - TODO: add argument description
+ BarIndex - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InitializePciDevice (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InitializePpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InitializeP2C (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+CreatePciIoDevice (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciRootBridgeIo - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+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
+
+--*/
+;
+
+EFI_STATUS
+StartManagingRootBridge (
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsPciDeviceRejected (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c new file mode 100644 index 0000000000..3ef1daf69e --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c @@ -0,0 +1,463 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciHotPlugSupport.c
+
+Abstract:
+
+
+
+Revision History
+
+--*/
+
+#include "Pcibus.h"
+#include "PciHotPlugSupport.h"
+
+EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit;
+EFI_HPC_LOCATION *gPciRootHpcPool;
+UINTN gPciRootHpcCount;
+ROOT_HPC_DATA *gPciRootHpcData;
+
+VOID
+EFIAPI
+PciHPCInitialized (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Event - add argument and description to function comment
+// TODO: Context - add argument and description to function comment
+{
+ ROOT_HPC_DATA *HpcData;
+
+ HpcData = (ROOT_HPC_DATA *) Context;
+ HpcData->Initialized = TRUE;
+
+}
+
+BOOLEAN
+EfiCompareDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: DevicePath1 - add argument and description to function comment
+// TODO: DevicePath2 - add argument and description to function comment
+{
+ UINTN Size1;
+ UINTN Size2;
+
+ Size1 = GetDevicePathSize (DevicePath1);
+ Size2 = GetDevicePathSize (DevicePath2);
+
+ if (Size1 != Size2) {
+ return FALSE;
+ }
+
+ if (CompareMem (DevicePath1, DevicePath2, Size1)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+EFI_STATUS
+InitializeHotPlugSupport (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_HPC_LOCATION *HpcList;
+ UINTN HpcCount;
+
+ //
+ // Locate the PciHotPlugInit Protocol
+ // If it doesn't exist, that means there is no
+ // hot plug controller supported on the platform
+ // the PCI Bus driver is running on. HotPlug Support
+ // is an optional feature, so absence of the protocol
+ // won't incur the penalty
+ //
+ gPciHotPlugInit = NULL;
+ gPciRootHpcPool = NULL;
+ gPciRootHpcCount = 0;
+ gPciRootHpcData = NULL;
+
+ Status = gBS->LocateProtocol (
+ &gEfiPciHotPlugInitProtocolGuid,
+ NULL,
+ (VOID **) &gPciHotPlugInit
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = gPciHotPlugInit->GetRootHpcList (
+ gPciHotPlugInit,
+ &HpcCount,
+ &HpcList
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ gPciRootHpcPool = HpcList;
+ gPciRootHpcCount = HpcCount;
+ gPciRootHpcData = AllocateZeroPool (sizeof (ROOT_HPC_DATA) * gPciRootHpcCount);
+ if (gPciRootHpcData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsRootPciHotPlugBus (
+ IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath,
+ OUT UINTN *HpIndex
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+ HpIndex - A pointer to the Index.
+
+Returns:
+
+ None
+
+--*/
+// TODO: HpbDevicePath - add argument and description to function comment
+{
+ UINTN Index;
+
+ for (Index = 0; Index < gPciRootHpcCount; Index++) {
+
+ if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpbDevicePath, HpbDevicePath)) {
+
+ if (HpIndex != NULL) {
+ *HpIndex = Index;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+IsRootPciHotPlugController (
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ OUT UINTN *HpIndex
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+ HpIndex - A pointer to the Index.
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Index;
+
+ for (Index = 0; Index < gPciRootHpcCount; Index++) {
+
+ if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpcDevicePath, HpcDevicePath)) {
+
+ if (HpIndex != NULL) {
+ *HpIndex = Index;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+CreateEventForHpc (
+ IN UINTN HpIndex,
+ OUT EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: HpIndex - add argument and description to function comment
+// TODO: Event - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ PciHPCInitialized,
+ gPciRootHpcData + HpIndex,
+ &((gPciRootHpcData + HpIndex)->Event)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ *Event = (gPciRootHpcData + HpIndex)->Event;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+AllRootHPCInitialized (
+ IN UINTN TimeoutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+ TimeoutInMicroSeconds - microseconds to wait for all root hpc's initialization
+
+Returns:
+ EFI_SUCCESS - All root hpc's initialization is finished before the timeout
+ EFI_TIMEOUT - Time out
+
+--*/
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_TIMEOUT - add return value to function comment
+{
+ UINT32 Delay;
+ UINTN Index;
+
+ Delay = (UINT32) ((TimeoutInMicroSeconds / 30) + 1);
+ do {
+
+ for (Index = 0; Index < gPciRootHpcCount; Index++) {
+
+ if (!gPciRootHpcData[Index].Initialized) {
+ break;
+ }
+ }
+
+ if (Index == gPciRootHpcCount) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+
+ } while (Delay);
+
+ return EFI_TIMEOUT;
+}
+
+EFI_STATUS
+IsSHPC (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+
+ EFI_STATUS Status;
+ UINT8 Offset;
+
+ if (!PciIoDevice) {
+ return EFI_NOT_FOUND;
+ }
+
+ Offset = 0;
+ Status = LocateCapabilityRegBlock (
+ PciIoDevice,
+ EFI_PCI_CAPABILITY_ID_HOTPLUG,
+ &Offset,
+ NULL
+ );
+
+ //
+ // If the PPB has the hot plug controller build-in,
+ // then return TRUE;
+ //
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+GetResourcePaddingForHpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_HPC_STATE State;
+ UINT64 PciAddress;
+ EFI_HPC_PADDING_ATTRIBUTES Attributes;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+ Status = IsPciHotPlugBus (PciIoDevice);
+
+ if (!EFI_ERROR (Status)) {
+ PciAddress = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
+ Status = gPciHotPlugInit->GetResourcePadding (
+ gPciHotPlugInit,
+ PciIoDevice->DevicePath,
+ PciAddress,
+ &State,
+ (VOID **) &Descriptors,
+ &Attributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((State & EFI_HPC_STATE_ENABLED) && (State & EFI_HPC_STATE_INITIALIZED)) {
+ PciIoDevice->ResourcePaddingDescriptors = Descriptors;
+ PciIoDevice->PaddingAttributes = Attributes;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+IsPciHotPlugBus (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ BOOLEAN Result;
+ EFI_STATUS Status;
+
+ Status = IsSHPC (PciIoDevice);
+
+ //
+ // If the PPB has the hot plug controller build-in,
+ // then return TRUE;
+ //
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Otherwise, see if it is a Root HPC
+ //
+ Result = IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL);
+
+ if (Result) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.h new file mode 100644 index 0000000000..7b15a3cd37 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.h @@ -0,0 +1,264 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciHotPlugSupport.h
+
+Abstract:
+
+
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_HOT_PLUG_SUPPORT_H
+#define _EFI_PCI_HOT_PLUG_SUPPORT_H
+
+
+//
+// stall 1 second
+//
+#define STALL_1_SECOND 1000000
+
+typedef struct {
+ EFI_EVENT Event;
+ BOOLEAN Initialized;
+ VOID *Padding;
+} ROOT_HPC_DATA;
+
+extern EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit;
+extern EFI_HPC_LOCATION *gPciRootHpcPool;
+extern UINTN gPciRootHpcCount;
+extern ROOT_HPC_DATA *gPciRootHpcData;
+
+VOID
+EFIAPI
+PciHPCInitialized (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Event - TODO: add argument description
+ Context - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+EfiCompareDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ DevicePath1 - TODO: add argument description
+ DevicePath2 - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InitializeHotPlugSupport (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+IsPciHotPlugBus (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsRootPciHotPlugBus (
+ IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath,
+ OUT UINTN *HpIndex
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ HpbDevicePath - TODO: add argument description
+ HpIndex - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsRootPciHotPlugController (
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ OUT UINTN *HpIndex
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ HpcDevicePath - TODO: add argument description
+ HpIndex - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CreateEventForHpc (
+ IN UINTN HpIndex,
+ OUT EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ HpIndex - TODO: add argument description
+ Event - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AllRootHPCInitialized (
+ IN UINTN TimeoutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+ TimeoutInMicroSeconds - microseconds to wait for all root hpc's initialization
+
+Returns:
+ EFI_SUCCESS - All root hpc's initialization is finished before the timeout
+ EFI_TIMEOUT - Time out
+
+--*/
+;
+
+EFI_STATUS
+IsSHPC (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourcePaddingForHpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.c new file mode 100644 index 0000000000..a636d4ff2c --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.c @@ -0,0 +1,1980 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciIo.c
+
+Abstract:
+
+ PCI I/O Abstraction Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+
+//
+// Internal use only
+//
+STATIC
+EFI_STATUS
+ReportErrorStatusCode (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_STATUS_CODE_VALUE Code
+ );
+
+//
+// PCI I/O Support Function Prototypes
+//
+//
+//
+// Pci Io Protocol Interface
+//
+static EFI_PCI_IO_PROTOCOL PciIoInterface = {
+ PciIoPollMem,
+ PciIoPollIo,
+ {
+ PciIoMemRead,
+ PciIoMemWrite
+ },
+ {
+ PciIoIoRead,
+ PciIoIoWrite
+ },
+ {
+ PciIoConfigRead,
+ PciIoConfigWrite
+ },
+ PciIoCopyMem,
+ PciIoMap,
+ PciIoUnmap,
+ PciIoAllocateBuffer,
+ PciIoFreeBuffer,
+ PciIoFlush,
+ PciIoGetLocation,
+ PciIoAttributes,
+ PciIoGetBarAttributes,
+ PciIoSetBarAttributes,
+ 0,
+ NULL
+};
+
+STATIC
+EFI_STATUS
+ReportErrorStatusCode (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_STATUS_CODE_VALUE Code
+ )
+/*++
+
+Routine Description:
+
+ report a error Status code of PCI bus driver controller
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Code - add argument and description to function comment
+{
+ return REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ Code,
+ PciIoDevice->DevicePath
+ );
+}
+
+EFI_STATUS
+InitializePciIoInstance (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Initializes a PCI I/O Instance
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoVerifyBarAccess (
+ PCI_IO_DEVICE *PciIoDevice,
+ UINT8 BarIndex,
+ PCI_BAR_TYPE Type,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ UINT64 *Offset
+ )
+/*++
+
+Routine Description:
+
+ Verifies access to a PCI Base Address Register (BAR)
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Type - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // BarIndex 0-5 is legal
+ //
+ if (BarIndex >= PCI_MAX_BAR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!CheckBarType (PciIoDevice, BarIndex, Type)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
+ // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
+ //
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ Count = 1;
+ }
+
+ Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
+
+ if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoVerifyConfigAccess (
+ PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN UINT64 *Offset
+ )
+/*++
+
+Routine Description:
+
+ Verifies access to a PCI Config Header
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 ExtendOffset;
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
+ //
+ Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
+
+ if (PciIoDevice->IsPciExp) {
+ if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ExtendOffset = LShiftU64 (*Offset, 32);
+ *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
+ *Offset = (*Offset) | ExtendOffset;
+
+ } else {
+ if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoPollMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ Poll PCI Memmory
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Mask - add argument and description to function comment
+// TODO: Value - add argument and description to function comment
+// TODO: Delay - add argument and description to function comment
+// TODO: Result - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Width > EfiPciIoWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->PollMem (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Mask,
+ Value,
+ Delay,
+ Result
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoPollIo (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ Poll PCI IO
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Mask - add argument and description to function comment
+// TODO: Value - add argument and description to function comment
+// TODO: Delay - add argument and description to function comment
+// TODO: Result - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width > EfiPciIoWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->PollIo (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Mask,
+ Value,
+ Delay,
+ Result
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoMemRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI Memory Read Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Mem.Read (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoMemWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI Memory Write Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Mem.Write (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoIoRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI I/O Read Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Io.Read (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoIoWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI I/O Write Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Io.Write (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoConfigRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI Configuration Read Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+ UINT64 Address;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ Address = Offset;
+ Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Pci.Read (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoConfigWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI Configuration Write Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+ UINT64 Address;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ Address = Offset;
+ Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Pci.Write (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoCopyMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 DestBarIndex,
+ IN UINT64 DestOffset,
+ IN UINT8 SrcBarIndex,
+ IN UINT64 SrcOffset,
+ IN UINTN Count
+ )
+/*++
+
+Routine Description:
+
+ Copy PCI Memory
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: DestBarIndex - add argument and description to function comment
+// TODO: DestOffset - add argument and description to function comment
+// TODO: SrcBarIndex - add argument and description to function comment
+// TODO: SrcOffset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width == EfiPciIoWidthFifoUint8 ||
+ Width == EfiPciIoWidthFifoUint16 ||
+ Width == EfiPciIoWidthFifoUint32 ||
+ Width == EfiPciIoWidthFifoUint64 ||
+ Width == EfiPciIoWidthFillUint8 ||
+ Width == EfiPciIoWidthFillUint16 ||
+ Width == EfiPciIoWidthFillUint32 ||
+ Width == EfiPciIoWidthFillUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->CopyMem (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ DestOffset,
+ SrcOffset,
+ Count
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoMap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+/*++
+
+Routine Description:
+
+ Maps a memory region for DMA
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: HostAddress - add argument and description to function comment
+// TODO: NumberOfBytes - add argument and description to function comment
+// TODO: DeviceAddress - add argument and description to function comment
+// TODO: Mapping - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
+ Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Map (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
+ HostAddress,
+ NumberOfBytes,
+ DeviceAddress,
+ Mapping
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoUnmap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+/*++
+
+Routine Description:
+
+ Unmaps a memory region for DMA
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Mapping - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ Status = PciIoDevice->PciRootBridgeIo->Unmap (
+ PciIoDevice->PciRootBridgeIo,
+ Mapping
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoAllocateBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Allocates a common buffer for DMA
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Type - add argument and description to function comment
+// TODO: MemoryType - add argument and description to function comment
+// TODO: Pages - add argument and description to function comment
+// TODO: HostAddress - add argument and description to function comment
+// TODO: Attributes - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ if (Attributes &
+ (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
+ Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (
+ PciIoDevice->PciRootBridgeIo,
+ Type,
+ MemoryType,
+ Pages,
+ HostAddress,
+ Attributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoFreeBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+/*++
+
+Routine Description:
+
+ Frees a common buffer
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Pages - add argument and description to function comment
+// TODO: HostAddress - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (
+ PciIoDevice->PciRootBridgeIo,
+ Pages,
+ HostAddress
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoFlush (
+ IN EFI_PCI_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Flushes a DMA buffer
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ Status = PciIoDevice->PciRootBridgeIo->Flush (
+ PciIoDevice->PciRootBridgeIo
+ );
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoGetLocation (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ OUT UINTN *Segment,
+ OUT UINTN *Bus,
+ OUT UINTN *Device,
+ OUT UINTN *Function
+ )
+/*++
+
+Routine Description:
+
+ Gets a PCI device's current bus number, device number, and function number.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Segment - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Function - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber;
+ *Bus = PciIoDevice->BusNumber;
+ *Device = PciIoDevice->DeviceNumber;
+ *Function = PciIoDevice->FunctionNumber;
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+CheckBarType (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ UINT8 BarIndex,
+ PCI_BAR_TYPE BarType
+ )
+/*++
+
+Routine Description:
+
+ Sets a PCI controllers attributes on a resource range
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: BarType - add argument and description to function comment
+{
+ switch (BarType) {
+
+ case PciBarTypeMem:
+
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 &&
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) {
+ return FALSE;
+ }
+
+ return TRUE;
+
+ case PciBarTypeIo:
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){
+ return FALSE;
+ }
+
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+ModifyRootBridgeAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT64 Attributes,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
+ )
+/*++
+
+Routine Description:
+
+ Set new attributes to a Root Bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Attributes - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 PciRootBridgeSupports;
+ UINT64 PciRootBridgeAttributes;
+ UINT64 NewPciRootBridgeAttributes;
+ EFI_STATUS Status;
+
+ //
+ // Get the current attributes of this PCI device's PCI Root Bridge
+ //
+ Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
+ PciIoDevice->PciRootBridgeIo,
+ &PciRootBridgeSupports,
+ &PciRootBridgeAttributes
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Record the new attribute of the Root Bridge
+ //
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ NewPciRootBridgeAttributes = PciRootBridgeAttributes | Attributes;
+ } else {
+ NewPciRootBridgeAttributes = PciRootBridgeAttributes & (~Attributes);
+ }
+
+ //
+ // Call the PCI Root Bridge to attempt to modify the attributes
+ //
+ if (NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) {
+
+ Status = PciIoDevice->PciRootBridgeIo->SetAttributes (
+ PciIoDevice->PciRootBridgeIo,
+ NewPciRootBridgeAttributes,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // The PCI Root Bridge could not modify the attributes, so return the error.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Also update the attributes for this Root Bridge structure
+ //
+ PciIoDevice->Attributes = NewPciRootBridgeAttributes;
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+SupportPaletteSnoopAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
+ )
+/*++
+
+Routine Description:
+
+ Check whether this device can be enable/disable to snoop
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Temp;
+ UINT16 VGACommand;
+
+ //
+ // Snoop attribute can be only modified by GFX
+ //
+ if (!IS_PCI_GFX (&PciIoDevice->Pci)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the boot VGA on the same segement
+ //
+ Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
+
+ if (!Temp) {
+ //
+ // If there is no VGA device on the segement, set
+ // this graphics card to decode the palette range
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Check these two agents are on the same path
+ //
+ if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) {
+ //
+ // they are not on the same path, so snoop can be enabled or disabled
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // Check if they are on the same bus
+ //
+ if (Temp->Parent == PciIoDevice->Parent) {
+
+ PciReadCommandRegister (Temp, &VGACommand);
+
+ //
+ // If they are on the same bus, either one can
+ // be set to snoop, the other set to decode
+ //
+ if (VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
+ //
+ // VGA has set to snoop, so GFX can be only set to disable snoop
+ //
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ //
+ // VGA has disabled to snoop, so GFX can be only enabled
+ //
+ if (Operation == EfiPciIoAttributeOperationDisable) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If they are on the same path but on the different bus
+ // The first agent is set to snoop, the second one set to
+ // decode
+ //
+
+ if (Temp->BusNumber < PciIoDevice->BusNumber) {
+ //
+ // GFX should be set to decode
+ //
+ if (Operation == EfiPciIoAttributeOperationDisable) {
+ PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+ Temp->Attributes |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ } else {
+ //
+ // GFX should be set to snoop
+ //
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+ Temp->Attributes &= (~EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoAttributes (
+ IN EFI_PCI_IO_PROTOCOL * This,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes,
+ OUT UINT64 *Result OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: Attributes - add argument and description to function comment
+// TODO: Result - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+
+ PCI_IO_DEVICE *PciIoDevice;
+ PCI_IO_DEVICE *UpStreamBridge;
+ PCI_IO_DEVICE *Temp;
+
+ UINT64 Supports;
+ UINT64 UpStreamAttributes;
+ UINT16 BridgeControl;
+ UINT16 Command;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ switch (Operation) {
+ case EfiPciIoAttributeOperationGet:
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Result = PciIoDevice->Attributes;
+ return EFI_SUCCESS;
+
+ case EfiPciIoAttributeOperationSupported:
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Result = PciIoDevice->Supports;
+ return EFI_SUCCESS;
+
+ case EfiPciIoAttributeOperationSet:
+ Status = PciIoDevice->PciIo.Attributes (
+ &(PciIoDevice->PciIo),
+ EfiPciIoAttributeOperationEnable,
+ Attributes,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciIo.Attributes (
+ &(PciIoDevice->PciIo),
+ EfiPciIoAttributeOperationDisable,
+ (~Attributes) & (PciIoDevice->Supports),
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+
+ case EfiPciIoAttributeOperationEnable:
+ case EfiPciIoAttributeOperationDisable:
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Just a trick for ENABLE attribute
+ //
+ if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) {
+ Attributes &= (PciIoDevice->Supports);
+
+ //
+ // Raise the EFI_P_PC_ENABLE Status code
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_P_PC_ENABLE,
+ PciIoDevice->DevicePath
+ );
+ }
+
+ //
+ // If no attributes can be supported, then return.
+ // Otherwise, set the attributes that it can support.
+ //
+ Supports = (PciIoDevice->Supports) & Attributes;
+ if (Supports != Attributes) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // For Root Bridge, just call RootBridgeIo to set attributes;
+ //
+ if (!PciIoDevice->Parent) {
+ Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation);
+ return Status;
+ }
+
+ Command = 0;
+ BridgeControl = 0;
+
+ //
+ // Check VGA and VGA16, they can not be set at the same time
+ //
+ if (((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) &&
+ (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) ||
+ ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) &&
+ (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) ||
+ ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) &&
+ (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) ||
+ ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) &&
+ (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // For PPB & P2C, set relevant attribute bits
+ //
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+
+ if (Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {
+ BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA;
+ }
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {
+ BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA;
+ }
+
+ if (Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) {
+ Command |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+ }
+
+ if (Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {
+ BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA_16;
+ }
+
+ } else {
+ //
+ // Do with the attributes on VGA
+ // Only for VGA's legacy resource, we just can enable once.
+ //
+ if (Attributes &
+ (EFI_PCI_IO_ATTRIBUTE_VGA_IO |
+ EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 |
+ EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY)) {
+ //
+ // Check if a VGA has been enabled before enabling a new one
+ //
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ //
+ // Check if there have been an active VGA device on the same segment
+ //
+ Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
+ if (Temp && Temp != PciIoDevice) {
+ //
+ // An active VGA has been detected, so can not enable another
+ //
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+
+ //
+ // Do with the attributes on GFX
+ //
+ if (Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) {
+
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ //
+ // Check if snoop can be enabled in current configuration
+ //
+ Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation);
+
+ if (EFI_ERROR (Status)) {
+
+ //
+ // Enable operation is forbidden, so mask the bit in attributes
+ // so as to keep consistent with the actual Status
+ //
+ // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
+ //
+ //
+ //
+ return EFI_UNSUPPORTED;
+
+ }
+ }
+
+ //
+ // It can be supported, so get ready to set the bit
+ //
+ Command |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+ }
+ }
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_IO) {
+ Command |= EFI_PCI_COMMAND_IO_SPACE;
+ }
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {
+ Command |= EFI_PCI_COMMAND_MEMORY_SPACE;
+ }
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {
+ Command |= EFI_PCI_COMMAND_BUS_MASTER;
+ }
+ //
+ // The upstream bridge should be also set to revelant attribute
+ // expect for IO, Mem and BusMaster
+ //
+ UpStreamAttributes = Attributes &
+ (~(EFI_PCI_IO_ATTRIBUTE_IO |
+ EFI_PCI_IO_ATTRIBUTE_MEMORY |
+ EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
+ )
+ );
+ UpStreamBridge = PciIoDevice->Parent;
+
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ //
+ // Enable relevant attributes to command register and bridge control register
+ //
+ Status = PciEnableCommandRegister (PciIoDevice, Command);
+ if (BridgeControl) {
+ Status = PciEnableBridgeControlRegister (PciIoDevice, BridgeControl);
+ }
+
+ PciIoDevice->Attributes |= Attributes;
+
+ //
+ // Enable attributes of the upstream bridge
+ //
+ Status = UpStreamBridge->PciIo.Attributes (
+ &(UpStreamBridge->PciIo),
+ EfiPciIoAttributeOperationEnable,
+ UpStreamAttributes,
+ NULL
+ );
+ } else {
+
+ //
+ // Disable relevant attributes to command register and bridge control register
+ //
+ Status = PciDisableCommandRegister (PciIoDevice, Command);
+ if (BridgeControl) {
+ Status = PciDisableBridgeControlRegister (PciIoDevice, BridgeControl);
+ }
+
+ PciIoDevice->Attributes &= (~Attributes);
+ Status = EFI_SUCCESS;
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoGetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL * This,
+ IN UINT8 BarIndex,
+ OUT UINT64 *Supports, OPTIONAL
+ OUT VOID **Resources OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Supports - add argument and description to function comment
+// TODO: Resources - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ UINT8 *Configuration;
+ UINT8 NumConfig;
+ PCI_IO_DEVICE *PciIoDevice;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
+
+ NumConfig = 0;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Supports == NULL && Resources == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BarIndex >= PCI_MAX_BAR) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // This driver does not support modifications to the WRITE_COMBINE or
+ // CACHED attributes for BAR ranges.
+ //
+ if (Supports != NULL) {
+ *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
+ }
+
+ if (Resources != NULL) {
+
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {
+ NumConfig = 1;
+ }
+
+ Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Configuration == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (
+ Configuration,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+ if (NumConfig == 1) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+
+ Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;
+ Ptr->AddrLen = PciIoDevice->PciBar[BarIndex].Length;
+ Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;
+
+ switch (PciIoDevice->PciBar[BarIndex].BarType) {
+ case PciBarTypeIo16:
+ case PciBarTypeIo32:
+ //
+ // Io
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+ break;
+
+ case PciBarTypeMem32:
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // 32 bit
+ //
+ Ptr->AddrSpaceGranularity = 32;
+ break;
+
+ case PciBarTypePMem32:
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // prefechable
+ //
+ Ptr->SpecificFlag = 0x6;
+ //
+ // 32 bit
+ //
+ Ptr->AddrSpaceGranularity = 32;
+ break;
+
+ case PciBarTypeMem64:
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // 64 bit
+ //
+ Ptr->AddrSpaceGranularity = 64;
+ break;
+
+ case PciBarTypePMem64:
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // prefechable
+ //
+ Ptr->SpecificFlag = 0x6;
+ //
+ // 64 bit
+ //
+ Ptr->AddrSpaceGranularity = 64;
+ break;
+
+ default:
+ break;
+ }
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+
+ //
+ // put the checksum
+ //
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);
+ PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ PtrEnd->Checksum = 0;
+
+ *Resources = Configuration;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoSetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN UINT8 BarIndex,
+ IN OUT UINT64 *Offset,
+ IN OUT UINT64 *Length
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Attributes - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Length - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+ UINT64 NonRelativeOffset;
+ UINT64 Supports;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ //
+ // Make sure Offset and Length are not NULL
+ //
+ if (Offset == NULL || Length == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
+ // If Attributes is not 0, then return EFI_UNSUPPORTED.
+ //
+ Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
+
+ if (Attributes != (Attributes & Supports)) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and
+ // Length are valid for this PCI device.
+ //
+ NonRelativeOffset = *Offset;
+ Status = PciIoVerifyBarAccess (
+ PciIoDevice,
+ BarIndex,
+ PciBarTypeMem,
+ EfiPciIoWidthUint8,
+ (UINT32) *Length,
+ &NonRelativeOffset
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpStreamBridgesAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: Attributes - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Parent;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ Parent = PciIoDevice->Parent;
+
+ while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {
+
+ //
+ // Get the PciIo Protocol
+ //
+ PciIo = &Parent->PciIo;
+
+ PciIo->Attributes (PciIo, Operation, Attributes, NULL);
+
+ Parent = Parent->Parent;
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+PciDevicesOnTheSamePath (
+ IN PCI_IO_DEVICE *PciDevice1,
+ IN PCI_IO_DEVICE *PciDevice2
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDevice1 - add argument and description to function comment
+// TODO: PciDevice2 - add argument and description to function comment
+{
+ BOOLEAN Existed1;
+ BOOLEAN Existed2;
+
+ if (PciDevice1->Parent == PciDevice2->Parent) {
+ return TRUE;
+ }
+
+ Existed1 = PciDeviceExisted (PciDevice1->Parent, PciDevice2);
+ Existed2 = PciDeviceExisted (PciDevice2->Parent, PciDevice1);
+
+ return (BOOLEAN) (Existed1 || Existed2);
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.h new file mode 100644 index 0000000000..5733f592e3 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.h @@ -0,0 +1,773 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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
+
+--*/
+;
+
+EFI_STATUS
+PciIoVerifyBarAccess (
+ PCI_IO_DEVICE *PciIoDevice,
+ UINT8 BarIndex,
+ PCI_BAR_TYPE Type,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ UINT64 *Offset
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Type - TODO: add argument description
+ Width - TODO: add argument description
+ Count - TODO: add argument description
+ Offset - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciIoVerifyConfigAccess (
+ PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN UINT64 *Offset
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Width - TODO: add argument description
+ Count - TODO: add argument description
+ Offset - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoPollMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Mask - TODO: add argument description
+ Value - TODO: add argument description
+ Delay - TODO: add argument description
+ Result - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoPollIo (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Mask - TODO: add argument description
+ Value - TODO: add argument description
+ Delay - TODO: add argument description
+ Result - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoMemRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoMemWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoIoRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoIoWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoConfigRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoConfigWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoCopyMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 DestBarIndex,
+ IN UINT64 DestOffset,
+ IN UINT8 SrcBarIndex,
+ IN UINT64 SrcOffset,
+ IN UINTN Count
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ DestBarIndex - TODO: add argument description
+ DestOffset - TODO: add argument description
+ SrcBarIndex - TODO: add argument description
+ SrcOffset - TODO: add argument description
+ Count - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoMap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Operation - TODO: add argument description
+ HostAddress - TODO: add argument description
+ NumberOfBytes - TODO: add argument description
+ DeviceAddress - TODO: add argument description
+ Mapping - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoUnmap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Mapping - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoAllocateBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Type - TODO: add argument description
+ MemoryType - TODO: add argument description
+ Pages - TODO: add argument description
+ HostAddress - TODO: add argument description
+ Attributes - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoFreeBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Pages - TODO: add argument description
+ HostAddress - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoFlush (
+ IN EFI_PCI_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoGetLocation (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ OUT UINTN *Segment,
+ OUT UINTN *Bus,
+ OUT UINTN *Device,
+ OUT UINTN *Function
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Segment - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Function - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+CheckBarType (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ UINT8 BarIndex,
+ PCI_BAR_TYPE BarType
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ BarIndex - TODO: add argument description
+ BarType - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ModifyRootBridgeAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT64 Attributes,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Attributes - TODO: add argument description
+ Operation - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SupportPaletteSnoopAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Operation - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoAttributes (
+ IN EFI_PCI_IO_PROTOCOL * This,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes,
+ OUT UINT64 *Result OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Operation - TODO: add argument description
+ Attributes - TODO: add argument description
+ Result - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoGetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL * This,
+ IN UINT8 BarIndex,
+ OUT UINT64 *Supports, OPTIONAL
+ OUT VOID **Resources OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Supports - TODO: add argument description
+ Resources - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoSetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN UINT8 BarIndex,
+ IN OUT UINT64 *Offset,
+ IN OUT UINT64 *Length
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Attributes - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Length - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+UpStreamBridgesAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Operation - TODO: add argument description
+ Attributes - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+PciDevicesOnTheSamePath (
+ IN PCI_IO_DEVICE *PciDevice1,
+ IN PCI_IO_DEVICE *PciDevice2
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice1 - TODO: add argument description
+ PciDevice2 - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c new file mode 100644 index 0000000000..eaeca2ad4f --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c @@ -0,0 +1,2885 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciLib.c
+
+Abstract:
+
+ PCI Bus Driver Lib file
+ It abstracts some functions that can be different
+ between light PCI bus driver and full PCI bus driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest = {
+ PciHotPlugRequestNotify
+};
+
+
+VOID
+InstallHotPlugRequestProtocol (
+ IN EFI_STATUS *Status
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+ Status - A pointer to the status.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_HANDLE Handle;
+
+ if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+ return;
+ }
+
+ Handle = NULL;
+ *Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiPciHotPlugRequestProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gPciHotPlugRequest
+ );
+}
+
+VOID
+InstallPciHotplugGuid (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+
+ if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+ return;
+ }
+
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Parent->Pci)) {
+
+ Status = gBS->InstallProtocolInterface (
+ &PciIoDevice->Handle,
+ &gEfiPciHotplugDeviceGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+VOID
+UninstallPciHotplugGuid (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+
+ if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+ return;
+ }
+
+ Status = gBS->OpenProtocol (
+ PciIoDevice->Handle,
+ &gEfiPciHotplugDeviceGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // This may triger CardBus driver to stop for
+ // Pccard devices opened the GUID via BY_DRIVER
+ //
+ Status = gBS->UninstallProtocolInterface (
+ PciIoDevice->Handle,
+ &gEfiPciHotplugDeviceGuid,
+ NULL
+ );
+ }
+}
+
+VOID
+GetBackPcCardBar (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT32 Address;
+
+ if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+ return;
+ }
+
+ //
+ // Read PciBar information from the bar register
+ //
+ if (!gFullEnumeration) {
+
+ Address = 0;
+ PciIoRead (
+ &(PciIoDevice->PciIo),
+ EfiPciIoWidthUint32,
+ 0x1c,
+ 1,
+ &Address
+ );
+
+ (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);
+ (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;
+ (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;
+
+ Address = 0;
+ PciIoRead (
+ &(PciIoDevice->PciIo),
+ EfiPciIoWidthUint32,
+ 0x20,
+ 1,
+ &Address
+ );
+ (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);
+ (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;
+ (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;
+
+ Address = 0;
+ PciIoRead (
+ &(PciIoDevice->PciIo),
+ EfiPciIoWidthUint32,
+ 0x2c,
+ 1,
+ &Address
+ );
+ (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);
+ (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;
+ (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;
+
+ Address = 0;
+ PciIoRead (
+ &(PciIoDevice->PciIo),
+ EfiPciIoWidthUint32,
+ 0x34,
+ 1,
+ &Address
+ );
+ (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);
+ (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;
+ (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;
+
+ }
+
+ if (gPciHotPlugInit != NULL) {
+ GetResourcePaddingForHpb (PciIoDevice);
+ }
+}
+
+EFI_STATUS
+RemoveRejectedPciDevices (
+ EFI_HANDLE RootBridgeHandle,
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ RootBridgeHandle - An efi handle.
+ Bridge - An pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Temp;
+ LIST_ENTRY *CurrentLink;
+ LIST_ENTRY *LastLink;
+
+ if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+ return EFI_SUCCESS;
+ }
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (IS_PCI_BRIDGE (&Temp->Pci)) {
+ //
+ // Remove rejected devices recusively
+ //
+ RemoveRejectedPciDevices (RootBridgeHandle, Temp);
+ } else {
+ //
+ // Skip rejection for all PPBs, while detect rejection for others
+ //
+ if (IsPciDeviceRejected (Temp)) {
+
+ //
+ // For P2C, remove all devices on it
+ //
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
+ }
+
+ //
+ // Finally remove itself
+ //
+
+ LastLink = CurrentLink->BackLink;
+ RemoveEntryList (CurrentLink);
+ FreePciDevice (Temp);
+
+ CurrentLink = LastLink;
+ }
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciHostBridgeResourceAllocator (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+{
+ if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+ return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
+ PciResAlloc
+ );
+ } else {
+ return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
+ PciResAlloc
+ );
+ }
+}
+
+
+EFI_STATUS
+PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_HANDLE RootBridgeHandle;
+ VOID *AcpiConfig;
+ EFI_STATUS Status;
+ UINT64 IoBase;
+ UINT64 Mem32Base;
+ UINT64 PMem32Base;
+ UINT64 Mem64Base;
+ UINT64 PMem64Base;
+ UINT64 MaxOptionRomSize;
+ PCI_RESOURCE_NODE *IoBridge;
+ PCI_RESOURCE_NODE *Mem32Bridge;
+ PCI_RESOURCE_NODE *PMem32Bridge;
+ PCI_RESOURCE_NODE *Mem64Bridge;
+ PCI_RESOURCE_NODE *PMem64Bridge;
+ PCI_RESOURCE_NODE IoPool;
+ PCI_RESOURCE_NODE Mem32Pool;
+ PCI_RESOURCE_NODE PMem32Pool;
+ PCI_RESOURCE_NODE Mem64Pool;
+ PCI_RESOURCE_NODE PMem64Pool;
+ REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;
+
+ //
+ // Initialize resource pool
+ //
+
+ InitializeResourcePool (&IoPool, PciBarTypeIo16);
+ InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
+ InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
+ InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
+ InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
+
+ RootBridgeDev = NULL;
+ RootBridgeHandle = 0;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get host bridge handle for status report
+ //
+ ExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
+
+ //
+ // Create the entire system resource map from the information collected by
+ // enumerator. Several resource tree was created
+ //
+
+ IoBridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFF,
+ 0,
+ PciBarTypeIo16,
+ PciResUsageTypical
+ );
+
+ Mem32Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem32,
+ PciResUsageTypical
+ );
+
+ PMem32Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem32,
+ PciResUsageTypical
+ );
+
+ Mem64Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem64,
+ PciResUsageTypical
+ );
+
+ PMem64Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem64,
+ PciResUsageTypical
+ );
+
+ //
+ // Create resourcemap by going through all the devices subject to this root bridge
+ //
+ Status = CreateResourceMap (
+ RootBridgeDev,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge
+ );
+
+ //
+ // Get the max ROM size that the root bridge can process
+ //
+ RootBridgeDev->RomSize = Mem32Bridge->Length;
+
+ //
+ // Get Max Option Rom size for current root bridge
+ //
+ MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
+
+ //
+ // Enlarger the mem32 resource to accomdate the option rom
+ // if the mem32 resource is not enough to hold the rom
+ //
+ if (MaxOptionRomSize > Mem32Bridge->Length) {
+
+ Mem32Bridge->Length = MaxOptionRomSize;
+ RootBridgeDev->RomSize = MaxOptionRomSize;
+
+ //
+ // Alignment should be adjusted as well
+ //
+ if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
+ Mem32Bridge->Alignment = MaxOptionRomSize - 1;
+ }
+ }
+
+ //
+ // Based on the all the resource tree, contruct ACPI resource node to
+ // submit the resource aperture to pci host bridge protocol
+ //
+ Status = ConstructAcpiResourceRequestor (
+ RootBridgeDev,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge,
+ &AcpiConfig
+ );
+
+ //
+ // Insert these resource nodes into the database
+ //
+ InsertResourceNode (&IoPool, IoBridge);
+ InsertResourceNode (&Mem32Pool, Mem32Bridge);
+ InsertResourceNode (&PMem32Pool, PMem32Bridge);
+ InsertResourceNode (&Mem64Pool, Mem64Bridge);
+ InsertResourceNode (&PMem64Pool, PMem64Bridge);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Submit the resource requirement
+ //
+ Status = PciResAlloc->SubmitResources (
+ PciResAlloc,
+ RootBridgeDev->Handle,
+ AcpiConfig
+ );
+ }
+ //
+ // Free acpi resource node
+ //
+ if (AcpiConfig != NULL) {
+ FreePool (AcpiConfig);
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Destroy all the resource tree
+ //
+ DestroyResourceTree (&IoPool);
+ DestroyResourceTree (&Mem32Pool);
+ DestroyResourceTree (&PMem32Pool);
+ DestroyResourceTree (&Mem64Pool);
+ DestroyResourceTree (&PMem64Pool);
+ return Status;
+ }
+ }
+ //
+ // End while
+ //
+
+ //
+ // Notify pci bus driver starts to program the resource
+ //
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Allocation failed, then return
+ //
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Raise the EFI_IOB_PCI_RES_ALLOC status code
+ //
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
+ (VOID *) &ExtendedData,
+ sizeof (ExtendedData)
+ );
+
+ //
+ // Notify pci bus driver starts to program the resource
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
+
+ RootBridgeDev = NULL;
+
+ RootBridgeHandle = 0;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get acpi resource node for all the resource types
+ //
+ AcpiConfig = NULL;
+ Status = PciResAlloc->GetProposedResources (
+ PciResAlloc,
+ RootBridgeDev->Handle,
+ &AcpiConfig
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the resource base by interpreting acpi resource node
+ //
+ //
+ GetResourceBase (
+ AcpiConfig,
+ &IoBase,
+ &Mem32Base,
+ &PMem32Base,
+ &Mem64Base,
+ &PMem64Base
+ );
+
+ //
+ // Process option rom for this root bridge
+ //
+ Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
+
+ //
+ // Create the entire system resource map from the information collected by
+ // enumerator. Several resource tree was created
+ //
+ Status = GetResourceMap (
+ RootBridgeDev,
+ &IoBridge,
+ &Mem32Bridge,
+ &PMem32Bridge,
+ &Mem64Bridge,
+ &PMem64Bridge,
+ &IoPool,
+ &Mem32Pool,
+ &PMem32Pool,
+ &Mem64Pool,
+ &PMem64Pool
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Program IO resources
+ //
+ ProgramResource (
+ IoBase,
+ IoBridge
+ );
+
+ //
+ // Program Mem32 resources
+ //
+ ProgramResource (
+ Mem32Base,
+ Mem32Bridge
+ );
+
+ //
+ // Program PMem32 resources
+ //
+ ProgramResource (
+ PMem32Base,
+ PMem32Bridge
+ );
+
+ //
+ // Program Mem64 resources
+ //
+ ProgramResource (
+ Mem64Base,
+ Mem64Bridge
+ );
+
+ //
+ // Program PMem64 resources
+ //
+ ProgramResource (
+ PMem64Base,
+ PMem64Bridge
+ );
+
+ if (AcpiConfig != NULL) {
+ FreePool (AcpiConfig);
+ }
+ }
+
+ //
+ // Destroy all the resource tree
+ //
+ DestroyResourceTree (&IoPool);
+ DestroyResourceTree (&Mem32Pool);
+ DestroyResourceTree (&PMem32Pool);
+ DestroyResourceTree (&Mem64Pool);
+ DestroyResourceTree (&PMem64Pool);
+
+ //
+ // Notify the resource allocation phase is to end
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ Host brige resource allocator.
+
+Arguments:
+
+ PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+
+Returns:
+
+ EFI Status.
+
+--*/
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_HANDLE RootBridgeHandle;
+ VOID *AcpiConfig;
+ EFI_STATUS Status;
+ UINT64 IoBase;
+ UINT64 Mem32Base;
+ UINT64 PMem32Base;
+ UINT64 Mem64Base;
+ UINT64 PMem64Base;
+ UINT64 IoResStatus;
+ UINT64 Mem32ResStatus;
+ UINT64 PMem32ResStatus;
+ UINT64 Mem64ResStatus;
+ UINT64 PMem64ResStatus;
+ UINT64 MaxOptionRomSize;
+ PCI_RESOURCE_NODE *IoBridge;
+ PCI_RESOURCE_NODE *Mem32Bridge;
+ PCI_RESOURCE_NODE *PMem32Bridge;
+ PCI_RESOURCE_NODE *Mem64Bridge;
+ PCI_RESOURCE_NODE *PMem64Bridge;
+ PCI_RESOURCE_NODE IoPool;
+ PCI_RESOURCE_NODE Mem32Pool;
+ PCI_RESOURCE_NODE PMem32Pool;
+ PCI_RESOURCE_NODE Mem64Pool;
+ PCI_RESOURCE_NODE PMem64Pool;
+ BOOLEAN ReAllocate;
+ REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA HandleExtendedData;
+ REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;
+
+ //
+ // Reallocate flag
+ //
+ ReAllocate = FALSE;
+
+ //
+ // It will try several times if the resource allocation fails
+ //
+ while (TRUE) {
+
+ //
+ // Initialize resource pool
+ //
+ InitializeResourcePool (&IoPool, PciBarTypeIo16);
+ InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
+ InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
+ InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
+ InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
+
+ RootBridgeDev = NULL;
+ RootBridgeHandle = 0;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Create the entire system resource map from the information collected by
+ // enumerator. Several resource tree was created
+ //
+
+ IoBridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFF,
+ 0,
+ PciBarTypeIo16,
+ PciResUsageTypical
+ );
+
+ Mem32Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem32,
+ PciResUsageTypical
+ );
+
+ PMem32Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem32,
+ PciResUsageTypical
+ );
+
+ Mem64Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem64,
+ PciResUsageTypical
+ );
+
+ PMem64Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem64,
+ PciResUsageTypical
+ );
+
+ //
+ // Create resourcemap by going through all the devices subject to this root bridge
+ //
+ Status = CreateResourceMap (
+ RootBridgeDev,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge
+ );
+
+ //
+ // Get the max ROM size that the root bridge can process
+ //
+ RootBridgeDev->RomSize = Mem32Bridge->Length;
+
+ //
+ // Skip to enlarge the resource request during realloction
+ //
+ if (!ReAllocate) {
+ //
+ // Get Max Option Rom size for current root bridge
+ //
+ MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
+
+ //
+ // Enlarger the mem32 resource to accomdate the option rom
+ // if the mem32 resource is not enough to hold the rom
+ //
+ if (MaxOptionRomSize > Mem32Bridge->Length) {
+
+ Mem32Bridge->Length = MaxOptionRomSize;
+ RootBridgeDev->RomSize = MaxOptionRomSize;
+
+ //
+ // Alignment should be adjusted as well
+ //
+ if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
+ Mem32Bridge->Alignment = MaxOptionRomSize - 1;
+ }
+ }
+ }
+
+ //
+ // Based on the all the resource tree, contruct ACPI resource node to
+ // submit the resource aperture to pci host bridge protocol
+ //
+ Status = ConstructAcpiResourceRequestor (
+ RootBridgeDev,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge,
+ &AcpiConfig
+ );
+
+ //
+ // Insert these resource nodes into the database
+ //
+ InsertResourceNode (&IoPool, IoBridge);
+ InsertResourceNode (&Mem32Pool, Mem32Bridge);
+ InsertResourceNode (&PMem32Pool, PMem32Bridge);
+ InsertResourceNode (&Mem64Pool, Mem64Bridge);
+ InsertResourceNode (&PMem64Pool, PMem64Bridge);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Submit the resource requirement
+ //
+ Status = PciResAlloc->SubmitResources (
+ PciResAlloc,
+ RootBridgeDev->Handle,
+ AcpiConfig
+ );
+ }
+
+ //
+ // Free acpi resource node
+ //
+ if (AcpiConfig != NULL) {
+ FreePool (AcpiConfig);
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Destroy all the resource tree
+ //
+ DestroyResourceTree (&IoPool);
+ DestroyResourceTree (&Mem32Pool);
+ DestroyResourceTree (&PMem32Pool);
+ DestroyResourceTree (&Mem64Pool);
+ DestroyResourceTree (&PMem64Pool);
+ return Status;
+ }
+ }
+
+ //
+ // Notify pci bus driver starts to program the resource
+ //
+
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Allocation succeed, then continue the following
+ //
+ break;
+ }
+
+ //
+ // If the resource allocation is unsuccessful, free resources on bridge
+ //
+
+ RootBridgeDev = NULL;
+ RootBridgeHandle = 0;
+
+ IoResStatus = EFI_RESOURCE_SATISFIED;
+ Mem32ResStatus = EFI_RESOURCE_SATISFIED;
+ PMem32ResStatus = EFI_RESOURCE_SATISFIED;
+ Mem64ResStatus = EFI_RESOURCE_SATISFIED;
+ PMem64ResStatus = EFI_RESOURCE_SATISFIED;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get host bridge handle for status report
+ //
+ HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
+
+ //
+ // Get acpi resource node for all the resource types
+ //
+ AcpiConfig = NULL;
+
+ Status = PciResAlloc->GetProposedResources (
+ PciResAlloc,
+ RootBridgeDev->Handle,
+ &AcpiConfig
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (AcpiConfig != NULL) {
+ //
+ // Adjust resource allocation policy for each RB
+ //
+ GetResourceAllocationStatus (
+ AcpiConfig,
+ &IoResStatus,
+ &Mem32ResStatus,
+ &PMem32ResStatus,
+ &Mem64ResStatus,
+ &PMem64ResStatus
+ );
+ FreePool (AcpiConfig);
+ }
+ }
+ //
+ // End while
+ //
+
+ //
+ // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
+ //
+ //
+ // It is very difficult to follow the spec here
+ // Device path , Bar index can not be get here
+ //
+ ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
+
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
+ (VOID *) &AllocFailExtendedData,
+ sizeof (AllocFailExtendedData)
+ );
+
+ Status = PciHostBridgeAdjustAllocation (
+ &IoPool,
+ &Mem32Pool,
+ &PMem32Pool,
+ &Mem64Pool,
+ &PMem64Pool,
+ IoResStatus,
+ Mem32ResStatus,
+ PMem32ResStatus,
+ Mem64ResStatus,
+ PMem64ResStatus
+ );
+
+ //
+ // Destroy all the resource tree
+ //
+ DestroyResourceTree (&IoPool);
+ DestroyResourceTree (&Mem32Pool);
+ DestroyResourceTree (&PMem32Pool);
+ DestroyResourceTree (&Mem64Pool);
+ DestroyResourceTree (&PMem64Pool);
+
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ReAllocate = TRUE;
+
+ }
+ //
+ // End main while
+ //
+
+ //
+ // Raise the EFI_IOB_PCI_RES_ALLOC status code
+ //
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
+ (VOID *) &HandleExtendedData,
+ sizeof (HandleExtendedData)
+ );
+
+ //
+ // Notify pci bus driver starts to program the resource
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
+
+ RootBridgeDev = NULL;
+
+ RootBridgeHandle = 0;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get acpi resource node for all the resource types
+ //
+ AcpiConfig = NULL;
+ Status = PciResAlloc->GetProposedResources (
+ PciResAlloc,
+ RootBridgeDev->Handle,
+ &AcpiConfig
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the resource base by interpreting acpi resource node
+ //
+ //
+ GetResourceBase (
+ AcpiConfig,
+ &IoBase,
+ &Mem32Base,
+ &PMem32Base,
+ &Mem64Base,
+ &PMem64Base
+ );
+
+ //
+ // Process option rom for this root bridge
+ //
+ Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
+
+ //
+ // Create the entire system resource map from the information collected by
+ // enumerator. Several resource tree was created
+ //
+ Status = GetResourceMap (
+ RootBridgeDev,
+ &IoBridge,
+ &Mem32Bridge,
+ &PMem32Bridge,
+ &Mem64Bridge,
+ &PMem64Bridge,
+ &IoPool,
+ &Mem32Pool,
+ &PMem32Pool,
+ &Mem64Pool,
+ &PMem64Pool
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Program IO resources
+ //
+ ProgramResource (
+ IoBase,
+ IoBridge
+ );
+
+ //
+ // Program Mem32 resources
+ //
+ ProgramResource (
+ Mem32Base,
+ Mem32Bridge
+ );
+
+ //
+ // Program PMem32 resources
+ //
+ ProgramResource (
+ PMem32Base,
+ PMem32Bridge
+ );
+
+ //
+ // Program Mem64 resources
+ //
+ ProgramResource (
+ Mem64Base,
+ Mem64Bridge
+ );
+
+ //
+ // Program PMem64 resources
+ //
+ ProgramResource (
+ PMem64Base,
+ PMem64Bridge
+ );
+
+ if (AcpiConfig != NULL) {
+ gBS->FreePool (AcpiConfig);
+ }
+ }
+
+ //
+ // Destroy all the resource tree
+ //
+ DestroyResourceTree (&IoPool);
+ DestroyResourceTree (&Mem32Pool);
+ DestroyResourceTree (&PMem32Pool);
+ DestroyResourceTree (&Mem64Pool);
+ DestroyResourceTree (&PMem64Pool);
+
+ //
+ // Notify the resource allocation phase is to end
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+PciScanBus (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber,
+ OUT UINT8 *PaddedBusRange
+ )
+{
+ if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+ return PciScanBus_WithHotPlugDeviceSupport (
+ Bridge,
+ StartBusNumber,
+ SubBusNumber,
+ PaddedBusRange
+ );
+ } else {
+ return PciScanBus_WithoutHotPlugDeviceSupport (
+ Bridge,
+ StartBusNumber,
+ SubBusNumber,
+ PaddedBusRange
+ );
+ }
+}
+
+
+EFI_STATUS
+PciScanBus_WithoutHotPlugDeviceSupport (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber,
+ OUT UINT8 *PaddedBusRange
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to assign bus number to the given PCI bus system
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: StartBusNumber - add argument and description to function comment
+// TODO: SubBusNumber - add argument and description to function comment
+// TODO: PaddedBusRange - add argument and description to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 Pci;
+ UINT8 Device;
+ UINT8 Func;
+ UINT64 Address;
+ UINTN SecondBus;
+ UINT16 Register;
+ PCI_IO_DEVICE *PciDevice;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ SecondBus = 0;
+ Register = 0;
+
+ ResetAllPpbBusReg (Bridge, StartBusNumber);
+
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+ //
+ // Check to see whether a pci device is present
+ //
+ Status = PciDevicePresent (
+ PciRootBridgeIo,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func
+ );
+
+ if (!EFI_ERROR (Status) &&
+ (IS_PCI_BRIDGE (&Pci) ||
+ IS_CARDBUS_BRIDGE (&Pci))) {
+
+ //
+ // Get the bridge information
+ //
+ Status = PciSearchDevice (
+ Bridge,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func,
+ &PciDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ (*SubBusNumber)++;
+
+ SecondBus = (*SubBusNumber);
+
+ Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
+
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
+
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint16,
+ Address,
+ 1,
+ &Register
+ );
+
+ //
+ // Initialize SubBusNumber to SecondBus
+ //
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ SubBusNumber
+ );
+ //
+ // If it is PPB, resursively search down this bridge
+ //
+ if (IS_PCI_BRIDGE (&Pci)) {
+ //
+ // Temporarily initialize SubBusNumber to maximum bus number to ensure the
+ // PCI configuration transaction to go through any PPB
+ //
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+ Register = 0xFF;
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &Register
+ );
+
+ PreprocessController (
+ PciDevice,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ EfiPciBeforeChildBusEnumeration
+ );
+
+ Status = PciScanBus (
+ PciDevice,
+ (UINT8) (SecondBus),
+ SubBusNumber,
+ PaddedBusRange
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Set the current maximum bus number under the PPB
+ //
+
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ SubBusNumber
+ );
+
+ }
+
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+
+ Func = PCI_MAX_FUNC;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciScanBus_WithHotPlugDeviceSupport (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber,
+ OUT UINT8 *PaddedBusRange
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to assign bus number to the given PCI bus system
+
+Arguments:
+
+ Bridge - A pointer to the PCI_IO_DEVICE structure.
+ StartBusNumber - The start bus number.
+ SubBusNumber - A pointer to the sub bus number.
+ PaddedBusRange - A pointer to the padded bus range.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 Pci;
+ UINT8 Device;
+ UINT8 Func;
+ UINT64 Address;
+ UINTN SecondBus;
+ UINT16 Register;
+ UINTN HpIndex;
+ PCI_IO_DEVICE *PciDevice;
+ EFI_EVENT Event;
+ EFI_HPC_STATE State;
+ UINT64 PciAddress;
+ EFI_HPC_PADDING_ATTRIBUTES Attributes;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+ UINT16 BusRange;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ BOOLEAN BusPadding;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ SecondBus = 0;
+ Register = 0;
+ State = 0;
+ Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;
+ BusRange = 0;
+
+ ResetAllPpbBusReg (Bridge, StartBusNumber);
+
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+ //
+ // Check to see whether a pci device is present
+ //
+ Status = PciDevicePresent (
+ PciRootBridgeIo,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Func == 0) {
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+ Func = PCI_MAX_FUNC;
+ }
+
+ continue;
+ }
+
+ //
+ // Get the PCI device information
+ //
+ Status = PciSearchDevice (
+ Bridge,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func,
+ &PciDevice
+ );
+
+ ASSERT (!EFI_ERROR (Status));
+
+ PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
+
+ if (!IS_PCI_BRIDGE (&Pci)) {
+ //
+ // PCI bridges will be called later
+ // Here just need for PCI device or PCI to cardbus controller
+ // EfiPciBeforeChildBusEnumeration for PCI Device Node
+ //
+ PreprocessController (
+ PciDevice,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ EfiPciBeforeChildBusEnumeration
+ );
+ }
+
+ //
+ // For Pci Hotplug controller devcie only
+ //
+ if (gPciHotPlugInit != NULL) {
+ //
+ // Check if it is a Hotplug PCI controller
+ //
+ if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
+
+ if (!gPciRootHpcData[HpIndex].Initialized) {
+
+ Status = CreateEventForHpc (HpIndex, &Event);
+
+ ASSERT (!EFI_ERROR (Status));
+
+ Status = gPciHotPlugInit->InitializeRootHpc (
+ gPciHotPlugInit,
+ gPciRootHpcPool[HpIndex].HpcDevicePath,
+ PciAddress,
+ Event,
+ &State
+ );
+
+ PreprocessController (
+ PciDevice,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ EfiPciBeforeChildBusEnumeration
+ );
+ continue;
+ }
+ }
+ }
+
+ if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
+ //
+ // For PPB
+ // Get the bridge information
+ //
+ BusPadding = FALSE;
+ if (gPciHotPlugInit != NULL) {
+
+ if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {
+
+ //
+ // If it is initialized, get the padded bus range
+ //
+ Status = gPciHotPlugInit->GetResourcePadding (
+ gPciHotPlugInit,
+ gPciRootHpcPool[HpIndex].HpbDevicePath,
+ PciAddress,
+ &State,
+ (VOID **) &Descriptors,
+ &Attributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BusRange = 0;
+ Status = PciGetBusRange (
+ &Descriptors,
+ NULL,
+ NULL,
+ &BusRange
+ );
+
+ gBS->FreePool (Descriptors);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BusPadding = TRUE;
+ }
+ }
+
+ (*SubBusNumber)++;
+ SecondBus = *SubBusNumber;
+
+ Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
+
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint16,
+ Address,
+ 1,
+ &Register
+ );
+
+
+ //
+ // If it is PPB, resursively search down this bridge
+ //
+ if (IS_PCI_BRIDGE (&Pci)) {
+
+ //
+ // Initialize SubBusNumber to Maximum bus number
+ //
+ Register = 0xFF;
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &Register
+ );
+
+ //
+ // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
+ //
+ PreprocessController (
+ PciDevice,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ EfiPciBeforeChildBusEnumeration
+ );
+
+ Status = PciScanBus (
+ PciDevice,
+ (UINT8) (SecondBus),
+ SubBusNumber,
+ PaddedBusRange
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ if (BusPadding) {
+ //
+ // Ensure the device is enabled and initialized
+ //
+ if ((Attributes == EfiPaddingPciRootBridge) &&
+ (State & EFI_HPC_STATE_ENABLED) &&
+ (State & EFI_HPC_STATE_INITIALIZED) ) {
+ *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);
+ } else {
+ *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);
+ }
+ }
+
+ //
+ // Set the current maximum bus number under the PPB
+ //
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+
+ Status = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &Pci,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ SubBusNumber
+ );
+ }
+
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+ Func = PCI_MAX_FUNC;
+ }
+
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRootBridgeP2CProcess (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ Process Option Rom on this host bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+ EFI_HPC_STATE State;
+ UINT64 PciAddress;
+ EFI_STATUS Status;
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
+
+ if (gPciHotPlugInit && Temp->Allocated) {
+
+ //
+ // Raise the EFI_IOB_PCI_HPC_INIT status code
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,
+ Temp->DevicePath
+ );
+
+ PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
+ Status = gPciHotPlugInit->InitializeRootHpc (
+ gPciHotPlugInit,
+ Temp->DevicePath,
+ PciAddress,
+ NULL,
+ &State
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = PciBridgeEnumerator (Temp);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+
+ }
+ }
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ Status = PciRootBridgeP2CProcess (Temp);
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciHostBridgeP2CProcess (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE RootBridgeHandle;
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_STATUS Status;
+
+ if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+ return EFI_SUCCESS;
+ }
+
+ RootBridgeHandle = NULL;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = PciRootBridgeP2CProcess (RootBridgeDev);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciHostBridgeEnumerator (
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ This function is used to enumerate the entire host bridge
+ in a given platform
+
+Arguments:
+
+ PciResAlloc - A pointer to the resource allocate protocol.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE RootBridgeHandle;
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ UINT16 MinBus;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+ InitializeHotPlugSupport ();
+
+ //
+ // Notify the bus allocation phase is about to start
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+
+ RootBridgeHandle = NULL;
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // if a root bridge instance is found, create root bridge device for it
+ //
+
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Enumerate all the buses under this root bridge
+ //
+
+ Status = PciRootBridgeEnumerator (
+ PciResAlloc,
+ RootBridgeDev
+ );
+
+ DestroyRootBridge (RootBridgeDev);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Notify the bus allocation phase is finished for the first time
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
+
+ if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+
+ if (gPciHotPlugInit != NULL) {
+ //
+ // Wait for all HPC initialized
+ //
+ Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Notify the bus allocation phase is about to start for the 2nd time
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+
+ RootBridgeHandle = NULL;
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // if a root bridge instance is found, create root bridge device for it
+ //
+
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Enumerate all the buses under this root bridge
+ //
+
+ Status = PciRootBridgeEnumerator (
+ PciResAlloc,
+ RootBridgeDev
+ );
+
+ DestroyRootBridge (RootBridgeDev);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Notify the bus allocation phase is to end for the 2nd time
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
+ }
+ }
+
+ //
+ // Notify the resource allocation phase is to start
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
+
+ RootBridgeHandle = NULL;
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // if a root bridge instance is found, create root bridge device for it
+ //
+
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = StartManagingRootBridge (RootBridgeDev);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
+ Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Determine root bridge attribute by calling interface of Pcihostbridge
+ // protocol
+ //
+ DetermineRootBridgeAttributes (
+ PciResAlloc,
+ RootBridgeDev
+ );
+
+ //
+ // Collect all the resource information under this root bridge
+ // A database that records all the information about pci device subject to this
+ // root bridge will then be created
+ //
+ Status = PciPciDeviceInfoCollector (
+ RootBridgeDev,
+ (UINT8) MinBus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ InsertRootBridge (RootBridgeDev);
+
+ //
+ // Record the hostbridge handle
+ //
+ AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCI device configuration register by specified address.
+
+ This function check the incompatiblilites on PCI device. Return the register
+ value.
+
+ @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param PciIo A pointer to EFI_PCI_PROTOCOL.
+ @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+STATIC
+EFI_STATUS
+ReadConfigData (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
+ IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
+ IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
+ IN UINT64 Width,
+ IN UINT64 Address,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT64 AccessWidth;
+ EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;
+ UINT64 AccessAddress;
+ UINTN Stride;
+ UINT64 TempBuffer;
+ UINT8 *Pointer;
+
+ ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
+
+ if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {
+ //
+ // check access compatibility at first time
+ //
+ Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, Address & 0xff, Width, &PciRegisterAccessData);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // there exist incompatibility on this operation
+ //
+ AccessWidth = Width;
+
+ if (PciRegisterAccessData->Width != VALUE_NOCARE) {
+ AccessWidth = PciRegisterAccessData->Width;
+ }
+
+ AccessAddress = Address & ~((1 << AccessWidth) - 1);
+
+ TempBuffer = 0;
+ Stride = 0;
+ Pointer = (UINT8 *) &TempBuffer;
+
+ while (1) {
+
+ if (PciRootBridgeIo != NULL) {
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,
+ AccessAddress,
+ 1,
+ Pointer
+ );
+ } else if (PciIo != NULL) {
+ Status = PciIo->Pci.Read (
+ PciIo,
+ (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,
+ (UINT32) AccessAddress,
+ 1,
+ Pointer
+ );
+ }
+
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ Stride = 1 << AccessWidth;
+ AccessAddress += Stride;
+ if (AccessAddress >= (Address + (1 << Width))) {
+ //
+ // if all datas have been read, exist
+ //
+ break;
+ }
+
+ Pointer += Stride;
+
+ if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {
+ //
+ // if current offset doesn't reach the end
+ //
+ continue;
+ }
+
+ FreePool (PciRegisterAccessData);
+
+ //
+ // continue checking access incompatibility
+ //
+ Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);
+ if (Status == EFI_SUCCESS) {
+ if (PciRegisterAccessData->Width != VALUE_NOCARE) {
+ AccessWidth = PciRegisterAccessData->Width;
+ }
+ }
+ }
+
+ FreePool (PciRegisterAccessData);
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ * (UINT8 *) Buffer = (UINT8) TempBuffer;
+ break;
+ case EfiPciWidthUint16:
+ * (UINT16 *) Buffer = (UINT16) TempBuffer;
+ break;
+ case EfiPciWidthUint32:
+ * (UINT32 *) Buffer = (UINT32) TempBuffer;
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ return Status;
+ }
+ }
+ //
+ // AccessWidth incompatible check not supportted
+ // or, there doesn't exist incompatibility on this operation
+ //
+ if (PciRootBridgeIo != NULL) {
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ 1,
+ Buffer
+ );
+
+ } else {
+ Status = PciIo->Pci.Read (
+ PciIo,
+ (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
+ (UINT32) Address,
+ 1,
+ Buffer
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Update register value by checking PCI device incompatibility.
+
+ This function check register value incompatibilites on PCI device. Return the register
+ value.
+
+ @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
+ @param AccessType Access type, READ or WRITE.
+ @Param Address The address within the PCI configuration space.
+ @param Buffer Store the register data.
+
+ @retval EFI_SUCCESS The data has been updated.
+
+**/
+STATIC
+EFI_STATUS
+UpdateConfigData (
+ IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
+ IN UINT64 AccessType,
+ IN UINT64 Width,
+ IN UINT64 Address,
+ IN OUT VOID *Buffer
+)
+{
+ EFI_STATUS Status;
+ EFI_PCI_REGISTER_VALUE_DATA *PciRegisterData;
+ UINT32 AndValue;
+ UINT32 OrValue;
+ UINT32 TempValue;
+
+ //
+ // check register value incompatibility
+ //
+ Status = PciRegisterUpdateCheck (PciDeviceInfo, AccessType, Address & 0xff, &PciRegisterData);
+
+ if (Status == EFI_SUCCESS) {
+
+ AndValue = ((UINT32) PciRegisterData->AndValue) >> (((UINT8) Address & 0x3) * 8);
+ OrValue = ((UINT32) PciRegisterData->OrValue) >> (((UINT8) Address & 0x3) * 8);
+
+ TempValue = * (UINT32 *) Buffer;
+ if (PciRegisterData->AndValue != VALUE_NOCARE) {
+ TempValue &= AndValue;
+ }
+ if (PciRegisterData->OrValue != VALUE_NOCARE) {
+ TempValue |= OrValue;
+ }
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ *(UINT8 *)Buffer = (UINT8) TempValue;
+ break;
+
+ case EfiPciWidthUint16:
+ *(UINT16 *)Buffer = (UINT16) TempValue;
+ break;
+ case EfiPciWidthUint32:
+ *(UINT32 *)Buffer = TempValue;
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ FreePool (PciRegisterData);
+ }
+
+ return Status;
+}
+
+/**
+ Write PCI device configuration register by specified address.
+
+ This function check the incompatiblilites on PCI device, and write date
+ into register.
+
+ @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param PciIo A pointer to EFI_PCI_PROTOCOL.
+ @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+STATIC
+EFI_STATUS
+WriteConfigData (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
+ IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
+ IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
+ IN UINT64 Width,
+ IN UINT64 Address,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT64 AccessWidth;
+ EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;
+ UINT64 AccessAddress;
+ UINTN Stride;
+ UINT8 *Pointer;
+ UINT64 Data;
+ UINTN Shift;
+
+ ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
+
+ if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {
+ //
+ // check access compatibility at first time
+ //
+ Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, Address & 0xff, Width, &PciRegisterAccessData);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // there exist incompatibility on this operation
+ //
+ AccessWidth = Width;
+
+ if (PciRegisterAccessData->Width != VALUE_NOCARE) {
+ AccessWidth = PciRegisterAccessData->Width;
+ }
+
+ AccessAddress = Address & ~((1 << AccessWidth) - 1);
+
+ Stride = 0;
+ Pointer = (UINT8 *) &Buffer;
+ Data = * (UINT64 *) Buffer;
+
+ while (1) {
+
+ if (AccessWidth > Width) {
+ //
+ // if actual access width is larger than orignal one, additional data need to be read back firstly
+ //
+ Status = ReadConfigData (PciRootBridgeIo, PciIo, PciDeviceInfo, AccessWidth, AccessAddress, &Data);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ //
+ // check data read incompatibility
+ //
+ UpdateConfigData (PciDeviceInfo, PCI_REGISTER_READ, AccessWidth, AccessAddress & 0xff, &Data);
+
+ Shift = (UINTN) ((Address - AccessAddress) * 8);
+ switch (Width) {
+ case EfiPciWidthUint8:
+ Data = (* (UINT8 *) Buffer) << Shift | (Data & ~(0xff << Shift));
+ break;
+
+ case EfiPciWidthUint16:
+ Data = (* (UINT16 *) Buffer) << Shift | (Data & ~(0xffff << Shift));
+ break;
+ }
+
+ //
+ // check data write incompatibility
+ //
+ UpdateConfigData (PciDeviceInfo, PCI_REGISTER_WRITE, AccessWidth, AccessAddress * 0xff, &Data);
+ }
+
+ if (PciRootBridgeIo != NULL) {
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,
+ AccessAddress,
+ 1,
+ &Data
+ );
+ } else {
+ Status = PciIo->Pci.Write (
+ PciIo,
+ (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,
+ (UINT32) AccessAddress,
+ 1,
+ &Data
+ );
+ }
+
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ Data = RShiftU64 (Data, ((1 << AccessWidth) * 8));
+
+ Stride = 1 << AccessWidth;
+ AccessAddress += Stride;
+ if (AccessAddress >= (Address + (1 << Width))) {
+ //
+ // if all datas have been written, exist
+ //
+ break;
+ }
+
+ Pointer += Stride;
+
+ if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {
+ //
+ // if current offset doesn't reach the end
+ //
+ continue;
+ }
+
+ FreePool (PciRegisterAccessData);
+
+ //
+ // continue checking access incompatibility
+ //
+ Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);
+ if (Status == EFI_SUCCESS) {
+ if (PciRegisterAccessData->Width != VALUE_NOCARE) {
+ AccessWidth = PciRegisterAccessData->Width;
+ }
+ }
+ };
+
+ FreePool (PciRegisterAccessData);
+
+ return Status;
+ }
+
+ }
+ //
+ // AccessWidth incompatible check not supportted
+ // or, there doesn't exist incompatibility on this operation
+ //
+ if (PciRootBridgeIo != NULL) {
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ 1,
+ Buffer
+ );
+ } else {
+ Status = PciIo->Pci.Write (
+ PciIo,
+ (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
+ (UINT32) Address,
+ 1,
+ Buffer
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Abstract PCI device device information.
+
+ @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param PciIo A pointer to EFI_PCI_PROTOCOL.
+ @param Pci A pointer to PCI_TYPE00.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
+
+ @retval EFI_SUCCESS Pci device device information has been abstracted.
+
+**/
+STATIC
+EFI_STATUS
+GetPciDeviceDeviceInfo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
+ IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
+ IN PCI_TYPE00 *Pci, OPTIONAL
+ IN UINT64 Address, OPTIONAL
+ OUT EFI_PCI_DEVICE_INFO *PciDeviceInfo
+)
+{
+ EFI_STATUS Status;
+ UINT64 PciAddress;
+ UINT32 PciConfigData;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
+
+ if (PciIo != NULL) {
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
+
+ //
+ // get pointer to PCI_TYPE00 from PciIoDevice
+ //
+ Pci = &PciIoDevice->Pci;
+ }
+
+ if (Pci == NULL) {
+ //
+ // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly
+ //
+ PciAddress = Address & 0xffffffffffffff00ULL;
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ PciAddress,
+ 1,
+ &PciConfigData
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((PciConfigData & 0xffff) == 0xffff) {
+ return EFI_NOT_FOUND;
+ }
+
+ PciDeviceInfo->VendorID = PciConfigData & 0xffff;
+ PciDeviceInfo->DeviceID = PciConfigData >> 16;
+
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ PciAddress + 8,
+ 1,
+ &PciConfigData
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciDeviceInfo->RevisionID = PciConfigData & 0xf;
+
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ PciAddress + 0x2c,
+ 1,
+ &PciConfigData
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciDeviceInfo->SubsystemVendorID = PciConfigData & 0xffff;
+ PciDeviceInfo->SubsystemID = PciConfigData >> 16;
+
+ } else {
+ PciDeviceInfo->VendorID = Pci->Hdr.VendorId;
+ PciDeviceInfo->DeviceID = Pci->Hdr.DeviceId;
+ PciDeviceInfo->RevisionID = Pci->Hdr.RevisionID;
+ PciDeviceInfo->SubsystemVendorID = Pci->Device.SubsystemVendorID;
+ PciDeviceInfo->SubsystemID = Pci->Device.SubsystemID;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCI configuration space with incompatibility check.
+
+ @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
+ @param Pci A pointer to PCI_TYPE00.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+STATIC
+EFI_STATUS
+PciIncompatibilityCheckRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
+ IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
+ IN PCI_TYPE00 *Pci, OPTIONAL
+ IN UINTN Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ EFI_STATUS Status;
+ EFI_PCI_DEVICE_INFO PciDeviceInfo;
+ UINT32 Stride;
+
+ ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
+
+ //
+ // get PCI device device information
+ //
+ Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ Stride = 1 << Width;
+
+ for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *)Buffer + Stride) {
+
+ //
+ // read configuration register
+ //
+ Status = ReadConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, (UINT64) Width, Address, Buffer);
+
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ //
+ // update the data read from configuration register
+ //
+ if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {
+ UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_READ, Width, Address & 0xff, Buffer);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write PCI configuration space with incompatibility check.
+
+ @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
+ @param Pci A pointer to PCI_TYPE00.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+STATIC
+EFI_STATUS
+PciIncompatibilityCheckWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
+ IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
+ IN PCI_TYPE00 *Pci, OPTIONAL
+ IN UINTN Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ EFI_STATUS Status;
+ EFI_PCI_DEVICE_INFO PciDeviceInfo;
+ UINT32 Stride;
+ UINT64 Data;
+
+ ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
+
+ //
+ // get PCI device device information
+ //
+ Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ Stride = 1 << Width;
+
+ for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *) Buffer + Stride) {
+
+ Data = 0;
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ Data = * (UINT8 *) Buffer;
+ break;
+ case EfiPciWidthUint16:
+ Data = * (UINT16 *) Buffer;
+ break;
+
+ case EfiPciWidthUint32:
+ Data = * (UINT32 *) Buffer;
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // update the data writen into configuration register
+ //
+ if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {
+ UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_WRITE, Width, Address & 0xff, &Data);
+ }
+
+ //
+ // write configuration register
+ //
+ Status = WriteConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, Width, Address, &Data);
+
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pci A pointer to PCI_TYPE00.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+PciRootBridgeIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN PCI_TYPE00 *Pci, OPTIONAL
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {
+ //
+ // if PCI incompatibility check enabled
+ //
+ return PciIncompatibilityCheckRead (
+ PciRootBridgeIo,
+ NULL,
+ Pci,
+ (UINTN) Width,
+ Address,
+ Count,
+ Buffer
+ );
+ } else {
+ return PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ Width,
+ Address,
+ Count,
+ Buffer
+ );
+ }
+}
+
+/**
+ Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pci A pointer to PCI_TYPE00.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+PciRootBridgeIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN PCI_TYPE00 *Pci,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {
+ //
+ // if PCI incompatibility check enabled
+ //
+ return PciIncompatibilityCheckWrite (
+ PciRootBridgeIo,
+ NULL,
+ Pci,
+ Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ } else {
+ return PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ Width,
+ Address,
+ Count,
+ Buffer
+ );
+ }
+}
+
+/**
+ Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
+
+ @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+PciIoRead (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {
+ //
+ // if PCI incompatibility check enabled
+ //
+ return PciIncompatibilityCheckRead (
+ NULL,
+ PciIo,
+ NULL,
+ (UINTN) Width,
+ Address,
+ Count,
+ Buffer
+ );
+ } else {
+ return PciIo->Pci.Read (
+ PciIo,
+ Width,
+ Address,
+ Count,
+ Buffer
+ );
+ }
+}
+
+/**
+ Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
+
+ @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+PciIoWrite (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {
+
+ //
+ // if PCI incompatibility check enabled
+ //
+ return PciIncompatibilityCheckWrite (
+ NULL,
+ PciIo,
+ NULL,
+ Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ } else {
+ return PciIo->Pci.Write (
+ PciIo,
+ Width,
+ Address,
+ Count,
+ Buffer
+ );
+ }
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.h new file mode 100644 index 0000000000..17e3587cb0 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.h @@ -0,0 +1,385 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciLib.h
+
+Abstract:
+
+ PCI Bus Driver Lib header file.
+ Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable
+ support hot plug.
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_LIB_H
+#define _EFI_PCI_LIB_H
+
+//
+// Mask definistions for PCD PcdPciIncompatibleDeviceSupportMask
+//
+#define PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT 0x01
+#define PCI_INCOMPATIBLE_READ_SUPPORT 0x02
+#define PCI_INCOMPATIBLE_WRITE_SUPPORT 0x04
+#define PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT 0x08
+#define PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT 0x0a
+
+VOID
+InstallHotPlugRequestProtocol (
+ IN EFI_STATUS *Status
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Status - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+InstallPciHotplugGuid (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+UninstallPciHotplugGuid (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+GetBackPcCardBar (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RemoveRejectedPciDevices (
+ EFI_HANDLE RootBridgeHandle,
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeHandle - TODO: add argument description
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeResourceAllocator (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+;
+
+EFI_STATUS
+PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+;
+
+EFI_STATUS
+PciScanBus (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber,
+ OUT UINT8 *PaddedBusRange
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ StartBusNumber - TODO: add argument description
+ SubBusNumber - TODO: add argument description
+ PaddedBusRange - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciScanBus_WithHotPlugDeviceSupport (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber,
+ OUT UINT8 *PaddedBusRange
+ )
+;
+
+EFI_STATUS
+PciScanBus_WithoutHotPlugDeviceSupport (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber,
+ OUT UINT8 *PaddedBusRange
+ )
+;
+
+EFI_STATUS
+PciRootBridgeP2CProcess (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeP2CProcess (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeEnumerator (
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+/**
+ Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
+
+ @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+PciIoRead (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
+
+ @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+PciIoWrite (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pci A pointer to PCI_TYPE00.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+PciRootBridgeIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN PCI_TYPE00 *Pci,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pci A pointer to PCI_TYPE00.
+ @param Width Signifies the width of the memory operations.
+ @Param Address The address within the PCI configuration space for the PCI controller.
+ @param Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+PciRootBridgeIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN PCI_TYPE00 *Pci,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.c new file mode 100644 index 0000000000..f6b371f8a5 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.c @@ -0,0 +1,564 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciOptionRomSupport.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+#include "PciResourceSupport.h"
+
+//
+// Min Max
+//
+#define EFI_MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define EFI_MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+
+EFI_STATUS
+GetOpRomInfo (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ 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_DEVICE_ROMBAR;
+
+ 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 = PciRootBridgeIoWrite (
+ PciRootBridgeIo,
+ &PciIoDevice->Pci,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ &AllOnes
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // read back
+ //
+ Status = PciRootBridgeIoRead (
+ PciRootBridgeIo,
+ &PciIoDevice->Pci,
+ 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;
+ }
+
+ PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LoadOpRomImage (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN UINT64 RomBase
+ )
+/*++
+
+Routine Description:
+
+ Load option rom image for specified PCI device
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: PciDevice - add argument and description to function comment
+// TODO: RomBase - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+{
+ 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;
+ UINT8 *RomInMemory;
+ UINT8 CodeType;
+
+ RomSize = PciDevice->RomSize;
+
+ Indicator = 0;
+ RomImageSize = 0;
+ RomInMemory = NULL;
+ CodeType = 0xFF;
+
+ //
+ // Get the RomBarIndex
+ //
+
+ //
+ // 0x30
+ //
+ RomBarIndex = PCI_DEVICE_ROMBAR;
+ 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) RomBase;
+
+ //
+ // Enable RomBar
+ //
+ RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);
+
+ RomBarOffset = RomBar;
+ retStatus = EFI_NOT_FOUND;
+ FirstCheck = TRUE;
+
+ 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;
+ PciDevice->PciRootBridgeIo->Mem.Read (
+ PciDevice->PciRootBridgeIo,
+ EfiPciWidthUint8,
+ RomBarOffset + OffsetPcir,
+ sizeof (PCI_DATA_STRUCTURE),
+ (UINT8 *) RomPcir
+ );
+ if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
+ CodeType = PCI_CODE_TYPE_PCAT_IMAGE;
+ }
+ 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 = EFI_MAX(RomImageSize, (((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512 * 512));
+ }
+
+ 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;
+
+ PciRomAddImageMapping (
+ NULL,
+ PciDevice->PciRootBridgeIo->SegmentNumber,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ (UINT64) (UINTN) PciDevice->PciIo.RomImage,
+ PciDevice->PciIo.RomSize
+ );
+
+ //
+ // 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:
+
+--*/
+// TODO: PciDevice - add argument and description to function comment
+// TODO: RomBarIndex - add argument and description to function comment
+// TODO: RomBar - add argument and description to function comment
+// TODO: Enable - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT32 Value32;
+ UINT32 Offset;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ PciIo = &PciDevice->PciIo;
+ if (Enable) {
+ //
+ // Clear all bars
+ //
+ for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
+ PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);
+ }
+
+ //
+ // set the Rom base address: now is hardcode
+ // enable its decoder
+ //
+ Value32 = RomBar | 0x1;
+ PciIoWrite (
+ PciIo,
+ (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,
+ RomBarIndex,
+ 1,
+ &Value32
+ );
+
+ //
+ // Programe all upstream bridge
+ //
+ ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);
+
+ //
+ // Setting the memory space bit in the function's command register
+ //
+ PciEnableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ } else {
+
+ //
+ // disable command register decode to memory
+ //
+ PciDisableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ //
+ // Destroy the programmed bar in all the upstream bridge.
+ //
+ ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);
+
+ //
+ // disable rom decode
+ //
+ Value32 = 0xFFFFFFFE;
+ PciIoWrite (
+ PciIo,
+ (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,
+ RomBarIndex,
+ 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 FirstCheck;
+ 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;
+
+ Indicator = 0;
+
+ //
+ // Get the Address of the Rom image
+ //
+ RomBar = PciDevice->PciIo.RomImage;
+ RomBarOffset = (UINT8 *) RomBar;
+ retStatus = EFI_NOT_FOUND;
+ FirstCheck = TRUE;
+
+ do {
+ EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;
+ if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+ RomBarOffset = RomBarOffset + 512;
+ if (FirstCheck) {
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ FirstCheck = FALSE;
+ Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);
+ ImageSize = (UINT32) (Pcir->ImageLength * 512);
+ Indicator = Pcir->Indicator;
+
+ if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
+ (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)) {
+
+ if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
+ (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {
+
+ ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
+ ImageSize = (UINT32) (EfiRomHeader->InitializationSize * 512);
+
+ ImageBuffer = (VOID *) (RomBarOffset + ImageOffset);
+ ImageLength = ImageSize - (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,
+ PciDevice->Handle,
+ ImageBuffer,
+ ImageLength,
+ &ImageHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);
+ if (!EFI_ERROR (Status)) {
+ AddDriver (PciDevice, ImageHandle);
+ PciRomAddImageMapping (
+ ImageHandle,
+ PciDevice->PciRootBridgeIo->SegmentNumber,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ (UINT64) (UINTN) PciDevice->PciIo.RomImage,
+ PciDevice->PciIo.RomSize
+ );
+ 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;
+
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.h new file mode 100644 index 0000000000..2bb11bf3d3 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.h @@ -0,0 +1,119 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ 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 RomBase
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice - TODO: add argument description
+ RomBase - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RomDecode (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN UINT8 RomBarIndex,
+ IN UINT32 RomBar,
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice - TODO: add argument description
+ RomBarIndex - TODO: add argument description
+ RomBar - TODO: add argument description
+ Enable - 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
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.c new file mode 100644 index 0000000000..4584198a9c --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.c @@ -0,0 +1,83 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciPowerManagement.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+
+EFI_STATUS
+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
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ UINT8 PowerManagementRegBlock;
+ UINT16 PMCSR;
+
+ 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
+ //
+ PMCSR = 0x8000;
+
+ //
+ // Write PMCSR
+ //
+ PciIoWrite (
+ &PciIoDevice->PciIo,
+ EfiPciIoWidthUint16,
+ PowerManagementRegBlock + 4,
+ 1,
+ &PMCSR
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.h new file mode 100644 index 0000000000..f33f7ab0de --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.h @@ -0,0 +1,48 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciPowerManagement.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_POWER_MANAGEMENT_H
+#define _EFI_PCI_POWER_MANAGEMENT_H
+
+EFI_STATUS
+ResetPowerManagementFeature (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c new file mode 100644 index 0000000000..a6ae80f4c5 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c @@ -0,0 +1,2314 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciResourceSupport.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+#include "PciResourceSupport.h"
+#include "PciCommand.h"
+
+EFI_STATUS
+SkipVGAAperture (
+ OUT UINT64 *Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ The function is used to skip VGA range
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Start - add argument and description to function comment
+// TODO: Length - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Original;
+ UINT64 Mask;
+ UINT64 StartOffset;
+ UINT64 LimitOffset;
+
+ //
+ // For legacy VGA, bit 10 to bit 15 is not decoded
+ //
+ Mask = 0x3FF;
+
+ Original = *Start;
+ StartOffset = Original & Mask;
+ LimitOffset = ((*Start) + Length - 1) & Mask;
+ if (LimitOffset >= VGABASE1) {
+ *Start = *Start - StartOffset + VGALIMIT2 + 1;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SkipIsaAliasAperture (
+ OUT UINT64 *Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ This function is used to skip ISA aliasing aperture
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Start - add argument and description to function comment
+// TODO: Length - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ UINT64 Original;
+ UINT64 Mask;
+ UINT64 StartOffset;
+ UINT64 LimitOffset;
+
+ //
+ // For legacy ISA, bit 10 to bit 15 is not decoded
+ //
+ Mask = 0x3FF;
+
+ Original = *Start;
+ StartOffset = Original & Mask;
+ LimitOffset = ((*Start) + Length - 1) & Mask;
+
+ if (LimitOffset >= ISABASE) {
+ *Start = *Start - StartOffset + ISALIMIT + 1;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InsertResourceNode (
+ PCI_RESOURCE_NODE *Bridge,
+ PCI_RESOURCE_NODE *ResNode
+ )
+/*++
+
+Routine Description:
+
+ This function inserts a resource node into the resource list.
+ The resource list is sorted in descend order.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: ResNode - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *Temp;
+ UINT64 ResNodeAlignRest;
+ UINT64 TempAlignRest;
+
+ InsertHeadList (&Bridge->ChildList, &ResNode->Link);
+
+ CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;
+ while (CurrentLink != &Bridge->ChildList) {
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (ResNode->Alignment > Temp->Alignment) {
+ break;
+ } else if (ResNode->Alignment == Temp->Alignment) {
+ ResNodeAlignRest = ResNode->Length & ResNode->Alignment;
+ TempAlignRest = Temp->Length & Temp->Alignment;
+ if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {
+ break;
+ }
+ }
+
+ SwapListEntries (&ResNode->Link, CurrentLink);
+
+ CurrentLink = ResNode->Link.ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MergeResourceTree (
+ PCI_RESOURCE_NODE *Dst,
+ PCI_RESOURCE_NODE *Res,
+ BOOLEAN TypeMerge
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to merge two different resource tree in need of
+ resoure degradation. For example, if a upstream PPB doesn't support,
+ prefetchable memory decoding, the PCI bus driver will choose to call this function
+ to merge prefectchable memory resource list into normal memory list.
+
+ If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
+ type.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Dst - add argument and description to function comment
+// TODO: Res - add argument and description to function comment
+// TODO: TypeMerge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *Temp;
+
+ while (!IsListEmpty (&Res->ChildList)) {
+ CurrentLink = Res->ChildList.ForwardLink;
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (TypeMerge) {
+ Temp->ResType = Dst->ResType;
+ }
+
+ RemoveEntryList (CurrentLink);
+ InsertResourceNode (Dst, Temp);
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CalculateApertureIo16 (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ This function is used to calculate the IO16 aperture
+ for a bridge.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ UINT64 Aperture;
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *Node;
+ UINT64 offset;
+ BOOLEAN IsaEnable;
+ BOOLEAN VGAEnable;
+
+ //
+ // Always assume there is ISA device and VGA device on the platform
+ // will be customized later
+ //
+ IsaEnable = FALSE;
+ VGAEnable = FALSE;
+
+ if (FeaturePcdGet (PcdPciIsaEnable)){
+ IsaEnable = TRUE;
+ }
+
+ if (FeaturePcdGet (PcdPciVgaEnable)){
+ VGAEnable = TRUE;
+ }
+
+ Aperture = 0;
+
+ if (!Bridge) {
+ return EFI_SUCCESS;
+ }
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ //
+ // Assume the bridge is aligned
+ //
+ while (CurrentLink != &Bridge->ChildList) {
+
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ //
+ // Consider the aperture alignment
+ //
+ offset = Aperture & (Node->Alignment);
+
+ if (offset) {
+
+ Aperture = Aperture + (Node->Alignment + 1) - offset;
+
+ }
+
+ //
+ // IsaEnable and VGAEnable can not be implemented now.
+ // If both of them are enabled, then the IO resource would
+ // become too limited to meet the requirement of most of devices.
+ //
+
+ if (IsaEnable || VGAEnable) {
+ if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
+ //
+ // Check if there is need to support ISA/VGA decoding
+ // If so, we need to avoid isa/vga aliasing range
+ //
+ if (IsaEnable) {
+ SkipIsaAliasAperture (
+ &Aperture,
+ Node->Length
+ );
+ offset = Aperture & (Node->Alignment);
+ if (offset) {
+ Aperture = Aperture + (Node->Alignment + 1) - offset;
+ }
+ } else if (VGAEnable) {
+ SkipVGAAperture (
+ &Aperture,
+ Node->Length
+ );
+ offset = Aperture & (Node->Alignment);
+ if (offset) {
+ Aperture = Aperture + (Node->Alignment + 1) - offset;
+ }
+ }
+ }
+ }
+
+ Node->Offset = Aperture;
+
+ //
+ // Increment aperture by the length of node
+ //
+ Aperture += Node->Length;
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // At last, adjust the aperture with the bridge's
+ // alignment
+ //
+ offset = Aperture & (Bridge->Alignment);
+
+ if (offset) {
+ Aperture = Aperture + (Bridge->Alignment + 1) - offset;
+ }
+
+ Bridge->Length = Aperture;
+ //
+ // At last, adjust the bridge's alignment to the first child's alignment
+ // if the bridge has at least one child
+ //
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ if (CurrentLink != &Bridge->ChildList) {
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+ if (Node->Alignment > Bridge->Alignment) {
+ Bridge->Alignment = Node->Alignment;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CalculateResourceAperture (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ This function is used to calculate the resource aperture
+ for a given bridge device
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Aperture;
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *Node;
+
+ UINT64 offset;
+
+ Aperture = 0;
+
+ if (!Bridge) {
+ return EFI_SUCCESS;
+ }
+
+ if (Bridge->ResType == PciBarTypeIo16) {
+ return CalculateApertureIo16 (Bridge);
+ }
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ //
+ // Assume the bridge is aligned
+ //
+ while (CurrentLink != &Bridge->ChildList) {
+
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ //
+ // Apply padding resource if available
+ //
+
+ offset = Aperture & (Node->Alignment);
+
+ if (offset) {
+
+ Aperture = Aperture + (Node->Alignment + 1) - offset;
+
+ }
+
+ //
+ // Recode current aperture as a offset
+ // this offset will be used in future real allocation
+ //
+ Node->Offset = Aperture;
+
+ //
+ // Increment aperture by the length of node
+ //
+ Aperture += Node->Length;
+
+ //
+ // Consider the aperture alignment
+ //
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // At last, adjust the aperture with the bridge's
+ // alignment
+ //
+ offset = Aperture & (Bridge->Alignment);
+ if (offset) {
+ Aperture = Aperture + (Bridge->Alignment + 1) - offset;
+ }
+
+ //
+ // If the bridge has already padded the resource and the
+ // amount of padded resource is larger, then keep the
+ // padded resource
+ //
+ if (Bridge->Length < Aperture) {
+ Bridge->Length = Aperture;
+ }
+
+ //
+ // At last, adjust the bridge's alignment to the first child's alignment
+ // if the bridge has at least one child
+ //
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ if (CurrentLink != &Bridge->ChildList) {
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+ if (Node->Alignment > Bridge->Alignment) {
+ Bridge->Alignment = Node->Alignment;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetResourceFromDevice (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDev - add argument and description to function comment
+// TODO: IoNode - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ UINT8 Index;
+ PCI_RESOURCE_NODE *Node;
+ BOOLEAN ResourceRequested;
+
+ Node = NULL;
+ ResourceRequested = FALSE;
+
+ for (Index = 0; Index < PCI_MAX_BAR; Index++) {
+
+ switch ((PciDev->PciBar)[Index].BarType) {
+
+ case PciBarTypeMem32:
+
+ Node = CreateResourceNode (
+ PciDev,
+ (PciDev->PciBar)[Index].Length,
+ (PciDev->PciBar)[Index].Alignment,
+ Index,
+ PciBarTypeMem32,
+ PciResUsageTypical
+ );
+
+ InsertResourceNode (
+ Mem32Node,
+ Node
+ );
+
+ ResourceRequested = TRUE;
+ break;
+
+ case PciBarTypeMem64:
+
+ Node = CreateResourceNode (
+ PciDev,
+ (PciDev->PciBar)[Index].Length,
+ (PciDev->PciBar)[Index].Alignment,
+ Index,
+ PciBarTypeMem64,
+ PciResUsageTypical
+ );
+
+ InsertResourceNode (
+ Mem64Node,
+ Node
+ );
+
+ ResourceRequested = TRUE;
+ break;
+
+ case PciBarTypePMem64:
+
+ Node = CreateResourceNode (
+ PciDev,
+ (PciDev->PciBar)[Index].Length,
+ (PciDev->PciBar)[Index].Alignment,
+ Index,
+ PciBarTypePMem64,
+ PciResUsageTypical
+ );
+
+ InsertResourceNode (
+ PMem64Node,
+ Node
+ );
+
+ ResourceRequested = TRUE;
+ break;
+
+ case PciBarTypePMem32:
+
+ Node = CreateResourceNode (
+ PciDev,
+ (PciDev->PciBar)[Index].Length,
+ (PciDev->PciBar)[Index].Alignment,
+ Index,
+ PciBarTypePMem32,
+ PciResUsageTypical
+ );
+
+ InsertResourceNode (
+ PMem32Node,
+ Node
+ );
+ ResourceRequested = TRUE;
+ break;
+
+ case PciBarTypeIo16:
+ case PciBarTypeIo32:
+
+ Node = CreateResourceNode (
+ PciDev,
+ (PciDev->PciBar)[Index].Length,
+ (PciDev->PciBar)[Index].Alignment,
+ Index,
+ PciBarTypeIo16,
+ PciResUsageTypical
+ );
+
+ InsertResourceNode (
+ IoNode,
+ Node
+ );
+ ResourceRequested = TRUE;
+ break;
+
+ case PciBarTypeUnknown:
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ //
+ // If there is no resource requested from this device,
+ // then we indicate this device has been allocated naturally.
+ //
+ if (!ResourceRequested) {
+ PciDev->Allocated = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+PCI_RESOURCE_NODE *
+CreateResourceNode (
+ IN PCI_IO_DEVICE *PciDev,
+ IN UINT64 Length,
+ IN UINT64 Alignment,
+ IN UINT8 Bar,
+ IN PCI_BAR_TYPE ResType,
+ IN PCI_RESOURCE_USAGE ResUsage
+ )
+/*++
+
+Routine Description:
+
+ This function is used to create a resource node
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDev - add argument and description to function comment
+// TODO: Length - add argument and description to function comment
+// TODO: Alignment - add argument and description to function comment
+// TODO: Bar - add argument and description to function comment
+// TODO: ResType - add argument and description to function comment
+// TODO: ResUsage - add argument and description to function comment
+{
+ PCI_RESOURCE_NODE *Node;
+
+ Node = NULL;
+
+ Node = AllocatePool (sizeof (PCI_RESOURCE_NODE));
+ if (Node == NULL) {
+ return NULL;
+ }
+
+ ZeroMem (Node, sizeof (PCI_RESOURCE_NODE));
+
+ Node->Signature = PCI_RESOURCE_SIGNATURE;
+ Node->PciDev = PciDev;
+ Node->Length = Length;
+ Node->Alignment = Alignment;
+ Node->Bar = Bar;
+ Node->ResType = ResType;
+ Node->Reserved = FALSE;
+ Node->ResourceUsage = ResUsage;
+ InitializeListHead (&Node->ChildList);
+ return Node;
+}
+
+EFI_STATUS
+CreateResourceMap (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *IoNode,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to extract resource request from
+ device node list.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: IoNode - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Temp;
+ PCI_RESOURCE_NODE *IoBridge;
+ PCI_RESOURCE_NODE *Mem32Bridge;
+ PCI_RESOURCE_NODE *PMem32Bridge;
+ PCI_RESOURCE_NODE *Mem64Bridge;
+ PCI_RESOURCE_NODE *PMem64Bridge;
+ LIST_ENTRY *CurrentLink;
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ //
+ // Create resource nodes for this device by scanning the
+ // Bar array in the device private data
+ // If the upstream bridge doesn't support this device,
+ // no any resource node will be created for this device
+ //
+ GetResourceFromDevice (
+ Temp,
+ IoNode,
+ Mem32Node,
+ PMem32Node,
+ Mem64Node,
+ PMem64Node
+ );
+
+ if (IS_PCI_BRIDGE (&Temp->Pci)) {
+
+ //
+ // If the device has children, create a bridge resource node for this PPB
+ // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
+ // is aligned with 4KB
+ // This device is typically a bridge device like PPB and P2C
+ //
+ IoBridge = CreateResourceNode (
+ Temp,
+ 0,
+ 0xFFF,
+ PPB_IO_RANGE,
+ PciBarTypeIo16,
+ PciResUsageTypical
+ ); //0x1000 aligned
+
+ Mem32Bridge = CreateResourceNode (
+ Temp,
+ 0,
+ 0xFFFFF,
+ PPB_MEM32_RANGE,
+ PciBarTypeMem32,
+ PciResUsageTypical
+ );
+
+ PMem32Bridge = CreateResourceNode (
+ Temp,
+ 0,
+ 0xFFFFF,
+ PPB_PMEM32_RANGE,
+ PciBarTypePMem32,
+ PciResUsageTypical
+ );
+
+ Mem64Bridge = CreateResourceNode (
+ Temp,
+ 0,
+ 0xFFFFF,
+ PPB_MEM64_RANGE,
+ PciBarTypeMem64,
+ PciResUsageTypical
+ );
+
+ PMem64Bridge = CreateResourceNode (
+ Temp,
+ 0,
+ 0xFFFFF,
+ PPB_PMEM64_RANGE,
+ PciBarTypePMem64,
+ PciResUsageTypical
+ );
+
+ //
+ // Recursively create resouce map on this bridge
+ //
+ CreateResourceMap (
+ Temp,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge
+ );
+
+ if (ResourceRequestExisted (IoBridge)) {
+ InsertResourceNode (
+ IoNode,
+ IoBridge
+ );
+ } else {
+ gBS->FreePool (IoBridge);
+ IoBridge = NULL;
+ }
+
+ //
+ // If there is node under this resource bridge,
+ // then calculate bridge's aperture of this type
+ // and insert it into the respective resource tree.
+ // If no, delete this resource bridge
+ //
+ if (ResourceRequestExisted (Mem32Bridge)) {
+ InsertResourceNode (
+ Mem32Node,
+ Mem32Bridge
+ );
+ } else {
+ gBS->FreePool (Mem32Bridge);
+ Mem32Bridge = NULL;
+ }
+
+ //
+ // If there is node under this resource bridge,
+ // then calculate bridge's aperture of this type
+ // and insert it into the respective resource tree.
+ // If no, delete this resource bridge
+ //
+ if (ResourceRequestExisted (PMem32Bridge)) {
+ InsertResourceNode (
+ PMem32Node,
+ PMem32Bridge
+ );
+ } else {
+ gBS->FreePool (PMem32Bridge);
+ PMem32Bridge = NULL;
+ }
+
+ //
+ // If there is node under this resource bridge,
+ // then calculate bridge's aperture of this type
+ // and insert it into the respective resource tree.
+ // If no, delete this resource bridge
+ //
+ if (ResourceRequestExisted (Mem64Bridge)) {
+ InsertResourceNode (
+ Mem64Node,
+ Mem64Bridge
+ );
+ } else {
+ gBS->FreePool (Mem64Bridge);
+ Mem64Bridge = NULL;
+ }
+
+ //
+ // If there is node under this resource bridge,
+ // then calculate bridge's aperture of this type
+ // and insert it into the respective resource tree.
+ // If no, delete this resource bridge
+ //
+ if (ResourceRequestExisted (PMem64Bridge)) {
+ InsertResourceNode (
+ PMem64Node,
+ PMem64Bridge
+ );
+ } else {
+ gBS->FreePool (PMem64Bridge);
+ PMem64Bridge = NULL;
+ }
+
+ }
+
+ //
+ // If it is P2C, apply hard coded resource padding
+ //
+ //
+ if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
+ ResourcePaddingForCardBusBridge (
+ Temp,
+ IoNode,
+ Mem32Node,
+ PMem32Node,
+ Mem64Node,
+ PMem64Node
+ );
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+ //
+ //
+ // To do some platform specific resource padding ...
+ //
+ ResourcePaddingPolicy (
+ Bridge,
+ IoNode,
+ Mem32Node,
+ PMem32Node,
+ Mem64Node,
+ PMem64Node
+ );
+
+ //
+ // Degrade resource if necessary
+ //
+ DegradeResource (
+ Bridge,
+ Mem32Node,
+ PMem32Node,
+ Mem64Node,
+ PMem64Node
+ );
+
+ //
+ // Calculate resource aperture for this bridge device
+ //
+ CalculateResourceAperture (Mem32Node);
+ CalculateResourceAperture (PMem32Node);
+ CalculateResourceAperture (Mem64Node);
+ CalculateResourceAperture (PMem64Node);
+ CalculateResourceAperture (IoNode);
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+ResourcePaddingPolicy (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ This function is used to do the resource padding for a specific platform
+
+Arguments:
+
+ PciDev - A pointer to the PCI_IO_DEVICE structrue.
+ IoNode - A pointer to the PCI_RESOURCE_NODE structrue.
+ Mem32Node - A pointer to the PCI_RESOURCE_NODE structrue.
+ PMem32Node - A pointer to the PCI_RESOURCE_NODE structrue.
+ Mem64Node - A pointer to the PCI_RESOURCE_NODE structrue.
+ PMem64Node - A pointer to the PCI_RESOURCE_NODE structrue.
+
+Returns:
+ Status code
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ //
+ // Create padding resource node
+ //
+ if (PciDev->ResourcePaddingDescriptors != NULL) {
+ ApplyResourcePadding (
+ PciDev,
+ IoNode,
+ Mem32Node,
+ PMem32Node,
+ Mem64Node,
+ PMem64Node
+ );
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+DegradeResource (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ This function is used to degrade resource if the upstream bridge
+ doesn't support certain resource. Degradation path is
+ PMEM64 -> MEM64 -> MEM32
+ PMEM64 -> PMEM32 -> MEM32
+ IO32 -> IO16
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ //
+ // If bridge doesn't support Prefetchable
+ // memory64, degrade it to Prefetchable memory32
+ //
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
+ MergeResourceTree (
+ PMem32Node,
+ PMem64Node,
+ TRUE
+ );
+ } else {
+ //
+ // if no PMem32 request, still keep PMem64. Otherwise degrade to PMem32
+ //
+ if (PMem32Node != NULL) {
+ MergeResourceTree (
+ PMem32Node,
+ PMem64Node,
+ TRUE
+ );
+ }
+ }
+
+
+ //
+ // If bridge doesn't support Mem64
+ // degrade it to mem32
+ //
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
+ MergeResourceTree (
+ Mem32Node,
+ Mem64Node,
+ TRUE
+ );
+ }
+
+ //
+ // If bridge doesn't support Pmem32
+ // degrade it to mem32
+ //
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
+ MergeResourceTree (
+ Mem32Node,
+ PMem32Node,
+ TRUE
+ );
+ }
+
+ //
+ // if bridge supports combined Pmem Mem decoding
+ // merge these two type of resource
+ //
+ if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
+ MergeResourceTree (
+ Mem32Node,
+ PMem32Node,
+ FALSE
+ );
+
+ MergeResourceTree (
+ Mem64Node,
+ PMem64Node,
+ FALSE
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+BridgeSupportResourceDecode (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT32 Decode
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Decode - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ /*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+ if ((Bridge->Decodes) & Decode) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+ProgramResource (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ This function is used to program the resource allocated
+ for each resource node
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Base - add argument and description to function comment
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *Node;
+ EFI_STATUS Status;
+
+ if (Base == gAllOne) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ while (CurrentLink != &Bridge->ChildList) {
+
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
+
+ if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
+ ProgramP2C (Base, Node);
+ } else {
+ ProgramBar (Base, Node);
+ }
+ } else {
+ Status = ProgramResource (Base + Node->Offset, Node);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ProgramPpbApperture (Base, Node);
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProgramBar (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Base - add argument and description to function comment
+// TODO: Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Address;
+ UINT32 Address32;
+
+ Address = 0;
+ PciIo = &(Node->PciDev->PciIo);
+
+ Address = Base + Node->Offset;
+
+ //
+ // Indicate pci bus driver has allocated
+ // resource for this device
+ // It might be a temporary solution here since
+ // pci device could have multiple bar
+ //
+ Node->PciDev->Allocated = TRUE;
+
+ switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
+
+ case PciBarTypeIo16:
+ case PciBarTypeIo32:
+ case PciBarTypeMem32:
+ case PciBarTypePMem32:
+
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (Node->PciDev->PciBar[Node->Bar]).Offset,
+ 1,
+ &Address
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+
+ break;
+
+ case PciBarTypeMem64:
+ case PciBarTypePMem64:
+
+ Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
+
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (Node->PciDev->PciBar[Node->Bar]).Offset,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) RShiftU64 (Address, 32);
+
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
+ 1,
+ &Address32
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProgramPpbApperture (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Base - add argument and description to function comment
+// TODO: Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Address;
+ UINT32 Address32;
+
+ Address = 0;
+ //
+ // if no device south of this PPB, return anyway
+ // Apperture is set default in the initialization code
+ //
+ if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
+ //
+ // For padding resource node, just ignore when programming
+ //
+ return EFI_SUCCESS;
+ }
+
+ PciIo = &(Node->PciDev->PciIo);
+ Address = Base + Node->Offset;
+
+ //
+ // Indicate the PPB resource has been allocated
+ //
+ Node->PciDev->Allocated = TRUE;
+
+ switch (Node->Bar) {
+
+ case PPB_BAR_0:
+ case PPB_BAR_1:
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (Node->PciDev->PciBar[Node->Bar]).Offset,
+ 1,
+ &Address
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+
+ break;
+
+ case PPB_IO_RANGE:
+
+ Address32 = ((UINT32) (Address)) >> 8;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0x1C,
+ 1,
+ &Address32
+ );
+
+ Address32 >>= 8;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x30,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) (Address + Node->Length - 1);
+ Address32 = ((UINT32) (Address32)) >> 8;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0x1D,
+ 1,
+ &Address32
+ );
+
+ Address32 >>= 8;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x32,
+ 1,
+ &Address32
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ break;
+
+ case PPB_MEM32_RANGE:
+
+ Address32 = ((UINT32) (Address)) >> 16;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x20,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) (Address + Node->Length - 1);
+ Address32 = ((UINT32) (Address32)) >> 16;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x22,
+ 1,
+ &Address32
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ break;
+
+ case PPB_PMEM32_RANGE:
+ case PPB_PMEM64_RANGE:
+
+ Address32 = ((UINT32) (Address)) >> 16;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x24,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) (Address + Node->Length - 1);
+ Address32 = ((UINT32) (Address32)) >> 16;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x26,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) RShiftU64 (Address, 32);
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x28,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x2C,
+ 1,
+ &Address32
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProgrameUpstreamBridgeForRom (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN UINT32 OptionRomBase,
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: PciDevice - add argument and description to function comment
+// TODO: OptionRomBase - add argument and description to function comment
+// TODO: Enable - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Parent;
+ PCI_RESOURCE_NODE Node;
+ //
+ // For root bridge, just return.
+ //
+ Parent = PciDevice->Parent;
+ ZeroMem (&Node, sizeof (Node));
+ while (Parent) {
+ if (!IS_PCI_BRIDGE (&Parent->Pci)) {
+ break;
+ }
+
+ Node.PciDev = Parent;
+ Node.Length = PciDevice->RomSize;
+ Node.Alignment = 0;
+ Node.Bar = PPB_MEM32_RANGE;
+ Node.ResType = PciBarTypeMem32;
+ Node.Offset = 0;
+
+ //
+ // Program PPB to only open a single <= 16<MB apperture
+ //
+ if (Enable) {
+ ProgramPpbApperture (OptionRomBase, &Node);
+ PciEnableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
+ } else {
+ InitializePpb (Parent);
+ PciDisableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+
+ Parent = Parent->Parent;
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+ResourceRequestExisted (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ Bridge - A pointer to the PCI_RESOURCE_NODE.
+
+Returns:
+
+ None
+
+--*/
+{
+ if (Bridge != NULL) {
+ if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+InitializeResourcePool (
+ PCI_RESOURCE_NODE *ResourcePool,
+ PCI_BAR_TYPE ResourceType
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: ResourcePool - add argument and description to function comment
+// TODO: ResourceType - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
+ ResourcePool->ResType = ResourceType;
+ ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
+ InitializeListHead (&ResourcePool->ChildList);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetResourceMap (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE **IoBridge,
+ PCI_RESOURCE_NODE **Mem32Bridge,
+ PCI_RESOURCE_NODE **PMem32Bridge,
+ PCI_RESOURCE_NODE **Mem64Bridge,
+ PCI_RESOURCE_NODE **PMem64Bridge,
+ PCI_RESOURCE_NODE *IoPool,
+ PCI_RESOURCE_NODE *Mem32Pool,
+ PCI_RESOURCE_NODE *PMem32Pool,
+ PCI_RESOURCE_NODE *Mem64Pool,
+ PCI_RESOURCE_NODE *PMem64Pool
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDev - add argument and description to function comment
+// TODO: IoBridge - add argument and description to function comment
+// TODO: Mem32Bridge - add argument and description to function comment
+// TODO: PMem32Bridge - add argument and description to function comment
+// TODO: Mem64Bridge - add argument and description to function comment
+// TODO: PMem64Bridge - add argument and description to function comment
+// TODO: IoPool - add argument and description to function comment
+// TODO: Mem32Pool - add argument and description to function comment
+// TODO: PMem32Pool - add argument and description to function comment
+// TODO: Mem64Pool - add argument and description to function comment
+// TODO: PMem64Pool - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ PCI_RESOURCE_NODE *Temp;
+ LIST_ENTRY *CurrentLink;
+
+ CurrentLink = IoPool->ChildList.ForwardLink;
+
+ //
+ // Get Io resource map
+ //
+ while (CurrentLink != &IoPool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciDev == PciDev) {
+ *IoBridge = Temp;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // Get Mem32 resource map
+ //
+ CurrentLink = Mem32Pool->ChildList.ForwardLink;
+
+ while (CurrentLink != &Mem32Pool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciDev == PciDev) {
+ *Mem32Bridge = Temp;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // Get Pmem32 resource map
+ //
+ CurrentLink = PMem32Pool->ChildList.ForwardLink;
+
+ while (CurrentLink != &PMem32Pool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciDev == PciDev) {
+ *PMem32Bridge = Temp;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // Get Mem64 resource map
+ //
+ CurrentLink = Mem64Pool->ChildList.ForwardLink;
+
+ while (CurrentLink != &Mem64Pool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciDev == PciDev) {
+ *Mem64Bridge = Temp;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // Get Pmem64 resource map
+ //
+ CurrentLink = PMem64Pool->ChildList.ForwardLink;
+
+ while (CurrentLink != &PMem64Pool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciDev == PciDev) {
+ *PMem64Bridge = Temp;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DestroyResourceTree (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_RESOURCE_NODE *Temp;
+ LIST_ENTRY *CurrentLink;
+
+ while (!IsListEmpty (&Bridge->ChildList)) {
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ RemoveEntryList (CurrentLink);
+
+ if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
+ DestroyResourceTree (Temp);
+ }
+
+ gBS->FreePool (Temp);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RecordReservedResource (
+ IN UINT64 Base,
+ IN UINT64 Length,
+ IN PCI_BAR_TYPE ResType,
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Base - add argument and description to function comment
+// TODO: Length - add argument and description to function comment
+// TODO: ResType - add argument and description to function comment
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_RESERVED_RESOURCE_LIST *ReservedNode;
+
+ ReservedNode = AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST));
+ if (ReservedNode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ReservedNode->Signature = RESERVED_RESOURCE_SIGNATURE;
+ ReservedNode->Node.Base = Base;
+ ReservedNode->Node.Length = Length;
+ ReservedNode->Node.ResType = ResType;
+
+ InsertTailList (&Bridge->ReservedResourceList, &(ReservedNode->Link));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ResourcePaddingForCardBusBridge (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDev - add argument and description to function comment
+// TODO: IoNode - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_RESOURCE_NODE *Node;
+
+ Node = NULL;
+
+ //
+ // Memory Base/Limit Register 0
+ // Bar 1 denodes memory range 0
+ //
+ Node = CreateResourceNode (
+ PciDev,
+ 0x2000000,
+ 0x1ffffff,
+ 1,
+ PciBarTypeMem32,
+ PciResUsagePadding
+ );
+
+ InsertResourceNode (
+ Mem32Node,
+ Node
+ );
+
+ //
+ // Memory Base/Limit Register 1
+ // Bar 2 denodes memory range1
+ //
+ Node = CreateResourceNode (
+ PciDev,
+ 0x2000000,
+ 0x1ffffff,
+ 2,
+ PciBarTypePMem32,
+ PciResUsagePadding
+ );
+
+ InsertResourceNode (
+ PMem32Node,
+ Node
+ );
+
+ //
+ // Io Base/Limit
+ // Bar 3 denodes io range 0
+ //
+ Node = CreateResourceNode (
+ PciDev,
+ 0x100,
+ 0xff,
+ 3,
+ PciBarTypeIo16,
+ PciResUsagePadding
+ );
+
+ InsertResourceNode (
+ IoNode,
+ Node
+ );
+
+ //
+ // Io Base/Limit
+ // Bar 4 denodes io range 0
+ //
+ Node = CreateResourceNode (
+ PciDev,
+ 0x100,
+ 0xff,
+ 4,
+ PciBarTypeIo16,
+ PciResUsagePadding
+ );
+
+ InsertResourceNode (
+ IoNode,
+ Node
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProgramP2C (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Base - add argument and description to function comment
+// TODO: Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Address;
+ UINT64 TempAddress;
+ UINT16 BridgeControl;
+
+ Address = 0;
+ PciIo = &(Node->PciDev->PciIo);
+
+ Address = Base + Node->Offset;
+
+ //
+ // Indicate pci bus driver has allocated
+ // resource for this device
+ // It might be a temporary solution here since
+ // pci device could have multiple bar
+ //
+ Node->PciDev->Allocated = TRUE;
+
+ switch (Node->Bar) {
+
+ case P2C_BAR_0:
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (Node->PciDev->PciBar[Node->Bar]).Offset,
+ 1,
+ &Address
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ break;
+
+ case P2C_MEM_1:
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x1c,
+ 1,
+ &Address
+ );
+
+ TempAddress = Address + Node->Length - 1;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x20,
+ 1,
+ &TempAddress
+ );
+
+ if (Node->ResType == PciBarTypeMem32) {
+
+ //
+ // Set non-prefetchable bit
+ //
+ PciIoRead (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+
+ BridgeControl &= 0xfeff;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+
+ } else {
+
+ //
+ // Set pre-fetchable bit
+ //
+ PciIoRead (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+
+ BridgeControl |= 0x0100;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+ }
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
+
+ break;
+
+ case P2C_MEM_2:
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x24,
+ 1,
+ &Address
+ );
+
+ TempAddress = Address + Node->Length - 1;
+
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x28,
+ 1,
+ &TempAddress
+ );
+
+ if (Node->ResType == PciBarTypeMem32) {
+
+ //
+ // Set non-prefetchable bit
+ //
+ PciIoRead (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+
+ BridgeControl &= 0xfdff;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+ } else {
+
+ //
+ // Set pre-fetchable bit
+ //
+ PciIoRead (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+
+ BridgeControl |= 0x0200;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+ }
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
+ break;
+
+ case P2C_IO_1:
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x2c,
+ 1,
+ &Address
+ );
+ TempAddress = Address + Node->Length - 1;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x30,
+ 1,
+ &TempAddress
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
+
+ break;
+
+ case P2C_IO_2:
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x34,
+ 1,
+ &Address
+ );
+
+ TempAddress = Address + Node->Length - 1;
+ PciIoWrite (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x38,
+ 1,
+ &TempAddress
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ApplyResourcePadding (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDev - add argument and description to function comment
+// TODO: IoNode - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ PCI_RESOURCE_NODE *Node;
+ UINT8 DummyBarIndex;
+
+ DummyBarIndex = 0;
+ Ptr = PciDev->ResourcePaddingDescriptors;
+
+ while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
+
+ if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
+ if (Ptr->AddrLen != 0) {
+
+ Node = CreateResourceNode (
+ PciDev,
+ Ptr->AddrLen,
+ Ptr->AddrRangeMax,
+ DummyBarIndex,
+ PciBarTypeIo16,
+ PciResUsagePadding
+ );
+ InsertResourceNode (
+ IoNode,
+ Node
+ );
+ }
+
+ Ptr++;
+ continue;
+ }
+
+ if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+
+ if (Ptr->AddrSpaceGranularity == 32) {
+
+ //
+ // prefechable
+ //
+ if (Ptr->SpecificFlag == 0x6) {
+ if (Ptr->AddrLen) {
+ Node = CreateResourceNode (
+ PciDev,
+ Ptr->AddrLen,
+ Ptr->AddrRangeMax,
+ DummyBarIndex,
+ PciBarTypePMem32,
+ PciResUsagePadding
+ );
+ InsertResourceNode (
+ PMem32Node,
+ Node
+ );
+ }
+
+ Ptr++;
+ continue;
+ }
+
+ //
+ // Non-prefechable
+ //
+ if (Ptr->SpecificFlag == 0) {
+ if (Ptr->AddrLen) {
+ Node = CreateResourceNode (
+ PciDev,
+ Ptr->AddrLen,
+ Ptr->AddrRangeMax,
+ DummyBarIndex,
+ PciBarTypeMem32,
+ PciResUsagePadding
+ );
+ InsertResourceNode (
+ Mem32Node,
+ Node
+ );
+ }
+
+ Ptr++;
+ continue;
+ }
+ }
+
+ if (Ptr->AddrSpaceGranularity == 64) {
+
+ //
+ // prefechable
+ //
+ if (Ptr->SpecificFlag == 0x6) {
+ if (Ptr->AddrLen) {
+ Node = CreateResourceNode (
+ PciDev,
+ Ptr->AddrLen,
+ Ptr->AddrRangeMax,
+ DummyBarIndex,
+ PciBarTypePMem64,
+ PciResUsagePadding
+ );
+ InsertResourceNode (
+ PMem64Node,
+ Node
+ );
+ }
+
+ Ptr++;
+ continue;
+ }
+
+ //
+ // Non-prefechable
+ //
+ if (Ptr->SpecificFlag == 0) {
+ if (Ptr->AddrLen) {
+ Node = CreateResourceNode (
+ PciDev,
+ Ptr->AddrLen,
+ Ptr->AddrRangeMax,
+ DummyBarIndex,
+ PciBarTypeMem64,
+ PciResUsagePadding
+ );
+ InsertResourceNode (
+ Mem64Node,
+ Node
+ );
+ }
+
+ Ptr++;
+ continue;
+ }
+ }
+ }
+
+ Ptr++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// Light PCI bus driver woundn't support hotplug root device
+// So no need to pad resource for them
+//
+VOID
+GetResourcePaddingPpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Get resource.
+
+Arguments:
+
+ PciIoDevice A pointer to a pci device.
+
+Returns:
+
+ None
+
+--*/
+{
+ if (gPciHotPlugInit) {
+ if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
+ GetResourcePaddingForHpb (PciIoDevice);
+ }
+ }
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.h new file mode 100644 index 0000000000..61ec29f7ec --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.h @@ -0,0 +1,740 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciResourceSupport.h
+
+Abstract:
+
+
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_RESOURCE_SUPPORT_H
+#define _EFI_PCI_RESOURCE_SUPPORT_H
+
+#define RESERVED_RESOURCE_SIGNATURE EFI_SIGNATURE_32 ('r', 's', 'v', 'd')
+
+typedef struct {
+ UINT64 Base;
+ UINT64 Length;
+ PCI_BAR_TYPE ResType;
+} PCI_RESERVED_RESOURCE_NODE;
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ PCI_RESERVED_RESOURCE_NODE Node;
+} PCI_RESERVED_RESOURCE_LIST;
+
+#define RESOURCED_LIST_FROM_NODE(a) \
+ CR (a, PCI_RESERVED_RESOURCE_LIST, Node, RESERVED_RESOURCE_SIGNATURE)
+
+#define RESOURCED_LIST_FROM_LINK(a) \
+ CR (a, PCI_RESERVED_RESOURCE_LIST, Link, RESERVED_RESOURCE_SIGNATURE)
+
+typedef enum {
+ PciResUsageTypical = 0,
+ PciResUsagePadding,
+ PciResUsageOptionRomProcessing
+} PCI_RESOURCE_USAGE;
+
+#define PCI_RESOURCE_SIGNATURE EFI_SIGNATURE_32 ('p', 'c', 'r', 'c')
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ LIST_ENTRY ChildList;
+ PCI_IO_DEVICE *PciDev;
+ UINT64 Alignment;
+ UINT64 Offset;
+ UINT8 Bar;
+ PCI_BAR_TYPE ResType;
+ UINT64 Length;
+ BOOLEAN Reserved;
+ PCI_RESOURCE_USAGE ResourceUsage;
+} PCI_RESOURCE_NODE;
+
+#define RESOURCE_NODE_FROM_LINK(a) \
+ CR (a, PCI_RESOURCE_NODE, Link, PCI_RESOURCE_SIGNATURE)
+
+EFI_STATUS
+SkipVGAAperture (
+ OUT UINT64 *Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Start - TODO: add argument description
+ Length - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SkipIsaAliasAperture (
+ OUT UINT64 *Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Start - TODO: add argument description
+ Length - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InsertResourceNode (
+ PCI_RESOURCE_NODE *Bridge,
+ PCI_RESOURCE_NODE *ResNode
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ ResNode - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+MergeResourceTree (
+ PCI_RESOURCE_NODE *Dst,
+ PCI_RESOURCE_NODE *Res,
+ BOOLEAN TypeMerge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Dst - TODO: add argument description
+ Res - TODO: add argument description
+ TypeMerge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CalculateApertureIo16 (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CalculateResourceAperture (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourceFromDevice (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_RESOURCE_NODE *
+CreateResourceNode (
+ IN PCI_IO_DEVICE *PciDev,
+ IN UINT64 Length,
+ IN UINT64 Alignment,
+ IN UINT8 Bar,
+ IN PCI_BAR_TYPE ResType,
+ IN PCI_RESOURCE_USAGE ResUsage
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ Length - TODO: add argument description
+ Alignment - TODO: add argument description
+ Bar - TODO: add argument description
+ ResType - TODO: add argument description
+ ResUsage - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CreateResourceMap (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *IoNode,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ResourcePaddingPolicy (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DegradeResource (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+BridgeSupportResourceDecode (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT32 Decode
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Decode - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProgramResource (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Base - TODO: add argument description
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProgramBar (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Base - TODO: add argument description
+ Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProgramPpbApperture (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Base - TODO: add argument description
+ Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProgrameUpstreamBridgeForRom (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN UINT32 OptionRomBase,
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice - TODO: add argument description
+ OptionRomBase - TODO: add argument description
+ Enable - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+ResourceRequestExisted (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InitializeResourcePool (
+ PCI_RESOURCE_NODE *ResourcePool,
+ PCI_BAR_TYPE ResourceType
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ResourcePool - TODO: add argument description
+ ResourceType - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourceMap (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE **IoBridge,
+ PCI_RESOURCE_NODE **Mem32Bridge,
+ PCI_RESOURCE_NODE **PMem32Bridge,
+ PCI_RESOURCE_NODE **Mem64Bridge,
+ PCI_RESOURCE_NODE **PMem64Bridge,
+ PCI_RESOURCE_NODE *IoPool,
+ PCI_RESOURCE_NODE *Mem32Pool,
+ PCI_RESOURCE_NODE *PMem32Pool,
+ PCI_RESOURCE_NODE *Mem64Pool,
+ PCI_RESOURCE_NODE *PMem64Pool
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ IoBridge - TODO: add argument description
+ Mem32Bridge - TODO: add argument description
+ PMem32Bridge - TODO: add argument description
+ Mem64Bridge - TODO: add argument description
+ PMem64Bridge - TODO: add argument description
+ IoPool - TODO: add argument description
+ Mem32Pool - TODO: add argument description
+ PMem32Pool - TODO: add argument description
+ Mem64Pool - TODO: add argument description
+ PMem64Pool - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DestroyResourceTree (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RecordReservedResource (
+ IN UINT64 Base,
+ IN UINT64 Length,
+ IN PCI_BAR_TYPE ResType,
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Base - TODO: add argument description
+ Length - TODO: add argument description
+ ResType - TODO: add argument description
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ResourcePaddingForCardBusBridge (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProgramP2C (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Base - TODO: add argument description
+ Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ApplyResourcePadding (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+GetResourcePaddingPpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ResetAllPpbBusReg (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber
+ )
+/*++
+
+Routine Description:
+
+ Reset bus register
+
+Arguments:
+
+ Bridge - a pointer to the PCI_IO_DEVICE
+ StartBusNumber - the number of bus
+
+Returns:
+
+ None
+
+--*/
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c new file mode 100644 index 0000000000..01249d4a5e --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c @@ -0,0 +1,197 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciRomTable.c
+
+Abstract:
+
+ Option Rom Support for PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+#include "PciRomTable.h"
+
+typedef struct {
+ EFI_HANDLE ImageHandle;
+ UINTN Seg;
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Func;
+ UINT64 RomAddress;
+ UINT64 RomLength;
+} EFI_PCI_ROM_IMAGE_MAPPING;
+
+static UINTN mNumberOfPciRomImages = 0;
+static UINTN mMaxNumberOfPciRomImages = 0;
+static EFI_PCI_ROM_IMAGE_MAPPING *mRomImageTable = NULL;
+
+VOID
+PciRomAddImageMapping (
+ IN EFI_HANDLE ImageHandle,
+ IN UINTN Seg,
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Func,
+ IN UINT64 RomAddress,
+ IN UINT64 RomLength
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+ Seg - TODO: add argument description
+ Bus - TODO: add argument description
+ Dev - TODO: add argument description
+ Func - TODO: add argument description
+ RomAddress - TODO: add argument description
+ RomLength - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ 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;
+ mRomImageTable[mNumberOfPciRomImages].RomAddress = RomAddress;
+ mRomImageTable[mNumberOfPciRomImages].RomLength = RomLength;
+ mNumberOfPciRomImages++;
+}
+
+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:
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: PciRootBridgeIo - add argument and description to function comment
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ 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;
+}
+
+EFI_STATUS
+PciRomGetImageMapping (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ UINTN Index;
+
+ PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
+
+ 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 ) {
+
+ if (mRomImageTable[Index].ImageHandle != NULL) {
+ AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
+ } else {
+ PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) mRomImageTable[Index].RomAddress;
+ PciIoDevice->PciIo.RomSize = (UINTN) mRomImageTable[Index].RomLength;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.h new file mode 100644 index 0000000000..bb20c70156 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.h @@ -0,0 +1,107 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciRomTable.h
+
+Abstract:
+
+ Option Rom Support for PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_ROM_TABLE_H
+#define _EFI_PCI_ROM_TABLE_H
+
+VOID
+PciRomAddImageMapping (
+ IN EFI_HANDLE ImageHandle,
+ IN UINTN Seg,
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Func,
+ IN UINT64 RomAddress,
+ IN UINT64 RomLength
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+ Seg - TODO: add argument description
+ Bus - TODO: add argument description
+ Dev - TODO: add argument description
+ Func - TODO: add argument description
+ RomAddress - TODO: add argument description
+ RomLength - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+
+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
+
+--*/
+;
+
+EFI_STATUS
+PciRomGetImageMapping (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.c new file mode 100644 index 0000000000..0f9d944f94 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.c @@ -0,0 +1,347 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PciBus.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+
+//
+// PCI Bus Driver Global Variables
+//
+
+EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding = {
+ PciBusDriverBindingSupported,
+ PciBusDriverBindingStart,
+ PciBusDriverBindingStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+EFI_HANDLE gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
+UINTN gPciHostBridgeNumber;
+BOOLEAN gFullEnumeration;
+UINT64 gAllOne = 0xFFFFFFFFFFFFFFFFULL;
+UINT64 gAllZero = 0;
+
+EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;
+
+//
+// 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
+
+--*/
+// TODO: ImageHandle - add argument and description to function comment
+// TODO: SystemTable - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ InitializePciDevicePool ();
+
+ gFullEnumeration = TRUE;
+
+ gPciHostBridgeNumber = 0;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallAllDriverProtocols (
+ ImageHandle,
+ SystemTable,
+ &gPciBusDriverBinding,
+ ImageHandle,
+ &gPciBusComponentName,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ InstallHotPlugRequestProtocol (&Status);
+
+ 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
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: RemainingDevicePath - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_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:
+
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: RemainingDevicePath - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+
+ //
+ // If PCI Platform protocol is available, get it now.
+ // If the platform implements this, it must be installed before BDS phase
+ //
+ gPciPlatformProtocol = NULL;
+ gBS->LocateProtocol (
+ &gEfiPciPlatformProtocolGuid,
+ NULL,
+ (VOID **) &gPciPlatformProtocol
+ );
+
+ gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE));
+
+ //
+ // 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:
+
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: NumberOfChildren - add argument and description to function comment
+// TODO: ChildHandleBuffer - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ 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;
+}
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.h b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.h new file mode 100644 index 0000000000..b4d731ae27 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.h @@ -0,0 +1,305 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ pcibus.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_BUS_H
+#define _EFI_PCI_BUS_H
+
+//
+// The package level header files this module uses
+//
+#include <PiDxe.h>
+#include <Common/FrameworkStatusCode.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/LoadedImage.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciIo.h>
+#include <Guid/PciHotplugDevice.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciHotPlugRequest.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciPlatform.h>
+#include <Protocol/PciHotPlugInit.h>
+#include <Protocol/Decompress.h>
+#include <Guid/PciOptionRomTable.h>
+#include <Protocol/BusSpecificDriverOverride.h>
+#include <Protocol/UgaIo.h>
+//
+// The Library classes this module consumes
+//
+#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/PciIncompatibleDeviceSupportLib.h>
+
+#include <IndustryStandard/pci22.h>
+#include <IndustryStandard/Acpi.h>
+#include "ComponentName.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 PPB_BAR_0 0
+#define PPB_BAR_1 1
+#define PPB_IO_RANGE 2
+#define PPB_MEM32_RANGE 3
+#define PPB_PMEM32_RANGE 4
+#define PPB_PMEM64_RANGE 5
+#define PPB_MEM64_RANGE 0xFF
+
+#define P2C_BAR_0 0
+#define P2C_MEM_1 1
+#define P2C_MEM_2 2
+#define P2C_IO_1 3
+#define P2C_IO_2 4
+
+#define PCI_IO_DEVICE_SIGNATURE EFI_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
+
+#define PCI_MAX_HOST_BRIDGE_NUM 0x0010
+//
+// Define resource status constant
+//
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL
+
+//
+// Define option for attribute
+//
+#define EFI_SET_SUPPORTS 0
+#define EFI_SET_ATTRIBUTES 1
+
+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;
+
+ //
+ // The OptionRom Size
+ //
+ UINT64 RomBase;
+
+ //
+ // TRUE if all OpROM (in device or in platform specific position) have been processed
+ //
+ BOOLEAN AllOpRomProcessed;
+
+ //
+ // 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;
+
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ResourcePaddingDescriptors;
+ EFI_HPC_PADDING_ATTRIBUTES PaddingAttributes;
+
+ 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_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName;
+extern LIST_ENTRY gPciDevicePool;
+extern BOOLEAN gFullEnumeration;
+extern UINTN gPciHostBridgeNumber;
+extern EFI_HANDLE gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
+extern UINT64 gAllOne;
+extern UINT64 gAllZero;
+
+extern EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;
+
+#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"
+#include "PciHotPlugSupport.h"
+#include "PciLib.h"
+
+//
+// PCI Bus Support Function Prototypes
+//
+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
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc index 043d15d9c3..dc6278bdbf 100644 --- a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc +++ b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc @@ -30,6 +30,38 @@ BUILD_TARGETS = DEBUG|RELEASE
SKUID_IDENTIFIER = DEFAULT
+[LibraryClasses.common]
+ CacheMaintenanceLib|${WORKSPACE}/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ DebugLib|${WORKSPACE}/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ BaseLib|${WORKSPACE}/MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|${WORKSPACE}/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ PciCf8Lib|${WORKSPACE}/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciExpressLib|${WORKSPACE}/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ PciLib|${WORKSPACE}/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+ PeCoffGetEntryPoint|${WORKSPACE}/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ PeCoffLib|${WORKSPACE}/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PerformanceLib|${WORKSPACE}/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ PostCodeLib|${WORKSPACE}/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf
+ PostCodeLib|${WORKSPACE}/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf
+ PrintLib|${WORKSPACE}/MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ TimerLib|${WORKSPACE}/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+ UefiDecompressLib|${WORKSPACE}/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+ HobLib|${WORKSPACE}/MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|${WORKSPACE}/MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
+ PcdLib|${WORKSPACE}/MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ DxeServiceTableLib|${WORKSPACE}/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ SmbusLib|${WORKSPACE}/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf
+ UefiBootServicesTableLib|${WORKSPACE}/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ DebugLib|${WORKSPACE}/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
+ DevicePathLib|${WORKSPACE}/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ UefiDriverEntryPoint|${WORKSPACE}/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiLib|${WORKSPACE}/MdePkg/Library/UefiLib/UefiLib.inf
+ UefiRuntimeServicesTableLib|${WORKSPACE}/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ DxeServicesTableLib|${WORKSPACE}/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ FvbServiceLib|${WORKSPACE}/MdeModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.inf
+ ReportStatusCodeLib|${WORKSPACE}/IntelFrameworkPkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
################################################################################
#
@@ -88,4 +120,6 @@ $(WORKSPACE)\IntelFrameworkModulePkg\Library\OemHookStatusCodeLibNull\OemHookStatusCodeLibNull.inf
$(WORKSPACE)\IntelFrameworkModulePkg\Library\PciIncompatibleDeviceSupportLib\PciIncompatibleDeviceSupportLib.inf
#$(WORKSPACE)\IntelFrameworkModulePkg\Bus\Pci\PciBus\Dxe\PciBus.inf
- #$(WORKSPACE)\IntelFrameworkModulePkg\Bus\Pci\IdeBus\Dxe\IdeBus.inf
\ No newline at end of file + $(WORKSPACE)\IntelFrameworkModulePkg\Bus\Pci\IdeBus\Dxe\IdeBus.inf
+ $(WORKSPACE)\IntelFrameworkModulePkg\Universal\DataHub\DataHub\Dxe\DataHub.inf
+ $(WORKSPACE)\IntelFrameworkModulePkg\Universal\DataHub\DataHubStdErr\Dxe\DataHubStdErr.inf
|