From c3902377a94850795450186d9b4b2bc3007d83be Mon Sep 17 00:00:00 2001 From: yshang1 Date: Mon, 2 Jul 2007 09:09:00 +0000 Subject: Add DxeBootScriptLibNull in IntelFrameworkPkg. Add IsaBusDxe in IntelFrameworkModulePkg. Add Pcat.h in "IntelFrameworkModulePkg/IndustryStandard" git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2948 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Bus/Isa/IsaBusDxe/CommonHeader.h | 56 + .../Bus/Isa/IsaBusDxe/ComponentName.c | 141 ++ .../Bus/Isa/IsaBusDxe/ComponentName.h | 92 ++ .../Bus/Isa/IsaBusDxe/EntryPoint.c | 58 + .../Bus/Isa/IsaBusDxe/InternalIsaBus.h | 253 +++ .../Bus/Isa/IsaBusDxe/InternalIsaIo.h | 163 ++ IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c | 653 ++++++++ .../Bus/Isa/IsaBusDxe/IsaBus.inf | 145 ++ .../Bus/Isa/IsaBusDxe/IsaBus.msa | 142 ++ IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c | 1646 ++++++++++++++++++++ 10 files changed, 3349 insertions(+) create mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/CommonHeader.h create mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c create mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h create mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/EntryPoint.c create mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h create mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h create mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c create mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.inf create mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.msa create mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c (limited to 'IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe') diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/CommonHeader.h b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/CommonHeader.h new file mode 100644 index 0000000000..85e65e48c5 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/CommonHeader.h @@ -0,0 +1,56 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2006 - 2007, Intel Corporation. + All rights reserved. + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +// +// The package level header files this module uses +// +#include +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// +// Driver Binding Externs +// +extern EFI_DRIVER_BINDING_PROTOCOL gIsaBusControllerDriver; +extern EFI_COMPONENT_NAME_PROTOCOL gIsaBusComponentName; + +#endif diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c new file mode 100644 index 0000000000..186aa5fc54 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c @@ -0,0 +1,141 @@ +/*++ + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "ComponentName.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gIsaBusComponentName = { + IsaBusComponentNameGetDriverName, + IsaBusComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mIsaBusDriverNameTable[] = { + { + "eng", + L"ISA Bus Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +IsaBusComponentNameGetDriverName ( + 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, + gIsaBusComponentName.SupportedLanguages, + mIsaBusDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +IsaBusComponentNameGetControllerName ( + 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/Isa/IsaBusDxe/ComponentName.h b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h new file mode 100644 index 0000000000..bca36505a7 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h @@ -0,0 +1,92 @@ +/*++ + +Copyright (c) 2006, Intel Corporation. All rights reserved. +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + ComponentName.h + +Abstract: + + +Revision History: + +--*/ + +#ifndef _EFI_ISA_BUS_COMPONENT_NAME_H +#define _EFI_ISA_BUS_COMPONENT_NAME_H + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +extern EFI_COMPONENT_NAME_PROTOCOL gIsaBusComponentName; + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +IsaBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + Language - GC_TODO: add argument description + DriverName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IsaBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + This - GC_TODO: add argument description + ControllerHandle - GC_TODO: add argument description + ChildHandle - GC_TODO: add argument description + Language - GC_TODO: add argument description + ControllerName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +#endif diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/EntryPoint.c b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/EntryPoint.c new file mode 100644 index 0000000000..ae5146ab54 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/EntryPoint.c @@ -0,0 +1,58 @@ +/**@file + Entry Point Source file. + + This file contains the user entry point + + Copyright (c) 2006 - 2007, Intel Corporation. + All rights reserved. + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. +**/ + + +// +// Include common header file for this module. +// +#include "InternalIsaBus.h" + +/** + The user Entry Point for module IsaBus. 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 +InitializeIsaBus( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gIsaBusControllerDriver, + ImageHandle, + &gIsaBusComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h new file mode 100644 index 0000000000..27bfb7a4e0 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h @@ -0,0 +1,253 @@ +/*++ + +Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + IsaBus.h + +Abstract: + + The header file for ISA bus driver + +Revision History: + +--*/ + +#ifndef _EFI_ISA_BUS_H +#define _EFI_ISA_BUS_H + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "ComponentName.h" + +extern EFI_ISA_IO_PROTOCOL IsaIoInterface; + +typedef enum { + IsaAccessTypeUnknown, + IsaAccessTypeIo, + IsaAccessTypeMem, + IsaAccessTypeMaxType +} ISA_ACCESS_TYPE; + +// +// 16 MB Memory Range +// +#define ISA_MAX_MEMORY_ADDRESS 0x1000000 +// +// 64K I/O Range +// +#define ISA_MAX_IO_ADDRESS 0x10000 + +typedef struct { + UINT8 Address; + UINT8 Page; + UINT8 Count; +} EFI_ISA_DMA_REGISTERS; + +// +// ISA I/O Device Structure +// +#define ISA_IO_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('i', 's', 'a', 'i') + +typedef struct { + UINT32 Signature; + EFI_HANDLE Handle; + EFI_ISA_IO_PROTOCOL IsaIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; +} ISA_IO_DEVICE; + +#define ISA_IO_DEVICE_FROM_ISA_IO_THIS(a) CR (a, ISA_IO_DEVICE, IsaIo, ISA_IO_DEVICE_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gIsaBusControllerDriver; + +// +// Mapping structure for performing ISA DMA to a buffer above 16 MB +// +typedef struct { + EFI_ISA_IO_PROTOCOL_OPERATION Operation; + UINTN NumberOfBytes; + UINTN NumberOfPages; + EFI_PHYSICAL_ADDRESS HostAddress; + EFI_PHYSICAL_ADDRESS MappedHostAddress; +} ISA_MAP_INFO; + +// +// EFI Driver Binding Protocol Interface Functions +// + +EFI_STATUS +EFIAPI +IsaBusControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL + ) +/*++ + + Routine Description: + + This function checks to see if a controller can be managed by the ISA Bus + Driver. This is done by checking to see if the controller supports the + EFI_PCI_IO_PROTOCOL protocol, and then looking at the PCI Configuration + Header to see if the device is a PCI to ISA bridge. The class code of + PCI to ISA bridge: Base class 06h, Sub class 01h Interface 00h + + Arguments: + + This - The EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - The handle of the device to check. + RemainingDevicePath - A pointer to the remaining portion of a device path. + + Returns: + + EFI_SUCCESS - The device is supported by this driver. + EFI_UNSUPPORTED - The device is not supported by this driver. + +--*/ +; + +EFI_STATUS +EFIAPI +IsaBusControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL + ) +/*++ + + Routine Description: + + This function tells the ISA Bus Driver to start managing a PCI to ISA + Bridge controller. + + Arguments: + + This - The EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - A handle to the device being started. + RemainingDevicePath - A pointer to the remaining portion of a device path. + + Returns: + + EFI_SUCCESS - The device was started. + EFI_UNSUPPORTED - The device is not supported. + EFI_DEVICE_ERROR - The device could not be started due to a device error. + EFI_ALREADY_STARTED - The device has already been started. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of + resources. + +--*/ +; + +EFI_STATUS +EFIAPI +IsaBusControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * ChildHandleBuffer OPTIONAL + ) +/*++ + + Routine Description: + + This function tells the ISA Bus Driver to stop managing a PCI to ISA + Bridge controller. + + Arguments: + + This - The EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - A handle to the device being stopped. + NumberOfChindren - The number of child device handles in ChildHandleBuffer. + ChildHandleBuffer - An array of child handles to be freed. + + + Returns: + + EFI_SUCCESS - The device was stopped. + EFI_DEVICE_ERROR - The device could not be stopped due to a device error. + EFI_NOT_STARTED - The device has not been started. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of + resources. + +--*/ +; + +// +// Function Prototypes +// + +EFI_STATUS +IsaCreateDevice ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList, + OUT EFI_DEVICE_PATH_PROTOCOL **ChildDevicePath + ) +/*++ + + Routine Description: + + Create ISA device found by IsaPnpProtocol + + Arguments: + + This - The EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - The handle of ISA bus controller(PCI to ISA bridge) + PciIo - The Pointer to the PCI protocol + ParentDevicePath - Device path of the ISA bus controller + IsaDeviceResourceList - The resource list of the ISA device + ChildDevicePath - The pointer to the child device. + + Returns: + + EFI_SUCCESS - Create the child device. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of + resources. + EFI_DEVICE_ERROR - Can not create child device. + +--*/ +; + +EFI_STATUS +InitializeIsaIoInstance ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDevice + ) +/*++ + +Routine Description: + + Initializes an ISA I/O Instance + +Arguments: + + IsaIoDevice - The iso device to be initialized. + IsaDevice - The resource list. + +Returns: + + EFI_SUCCESS - Initial success. + +--*/ +; + +#endif diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h new file mode 100644 index 0000000000..d344058fb9 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h @@ -0,0 +1,163 @@ +/*++ + +Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + IsaIo.h + +Abstract: + + The header file for EFI_ISA_IO protocol implementation. + +--*/ + +#ifndef _EFI_ISA_IO_LOCAL_H +#define _EFI_ISA_IO_LOCAL_H + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "InternalIsaBus.h" + +// +// ISA I/O Support Function Prototypes +// + +EFI_STATUS +IsaIoVerifyAccess ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN ISA_ACCESS_TYPE Type, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN OUT UINT32 *Offset + ); + +EFI_STATUS +EFIAPI +IsaIoIoRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +IsaIoIoWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +IsaIoMap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +EFI_STATUS +EFIAPI +IsaIoUnmap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +EFI_STATUS +EFIAPI +IsaIoFlush ( + IN EFI_ISA_IO_PROTOCOL *This + ); + +EFI_STATUS +ReportErrorStatusCode ( + EFI_STATUS_CODE_VALUE code + ); + +EFI_STATUS +WriteDmaPort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 AddrOffset, + IN UINT32 PageOffset, + IN UINT32 CountOffset, + IN UINT32 BaseAddress, + IN UINT16 Count + ); + +EFI_STATUS +WritePort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 Offset, + IN UINT8 Value + ); + +EFI_STATUS +EFIAPI +IsaIoMemRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + + +EFI_STATUS +EFIAPI +IsaIoMemWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +IsaIoCopyMem ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ); + +EFI_STATUS +EFIAPI +IsaIoAllocateBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +EFI_STATUS +EFIAPI +IsaIoFreeBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +#endif diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c new file mode 100644 index 0000000000..daee1fb510 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c @@ -0,0 +1,653 @@ +/*++ + +Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + IsaBus.c + +Abstract: + + Discovers all the ISA Controllers and their resources by using the ISA PnP + Protocol, produces an instance of the ISA I/O Protocol for every ISA + Controller found, loads and initializes all ISA Device Drivers, matches ISA + Device Drivers with their respective ISA Controllers in a deterministic + manner, and informs a ISA Device Driver when it is to start managing an ISA + Controller. + +Revision History: + +--*/ + +#include "InternalIsaBus.h" + +// +// ISA Bus Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gIsaBusControllerDriver = { + IsaBusControllerDriverSupported, + IsaBusControllerDriverStart, + IsaBusControllerDriverStop, + 0xa, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +IsaBusControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL + ) +/*++ + + Routine Description: + + This function checks to see if a controller can be managed by the ISA Bus + Driver. This is done by checking to see if the controller supports the + EFI_PCI_IO_PROTOCOL protocol, and then looking at the PCI Configuration + Header to see if the device is a PCI to ISA bridge. The class code of + PCI to ISA bridge: Base class 06h, Sub class 01h Interface 00h + + Arguments: + + This - The EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - The handle of the device to check. + RemainingDevicePath - A pointer to the remaining portion of a device path. + + Returns: + + EFI_SUCCESS - The device is supported by this driver. + EFI_UNSUPPORTED - The device is not supported by this driver. + +--*/ +{ + EFI_STATUS Status; + EFI_ISA_ACPI_PROTOCOL *IsaAcpi; + + // + // If RemainingDevicePath is not NULL, it should verify that the first device + // path node in RemainingDevicePath is an ACPI Device path node + // + if (RemainingDevicePath != NULL) { + if (RemainingDevicePath->Type != ACPI_DEVICE_PATH) { + return EFI_UNSUPPORTED; + } else if (RemainingDevicePath->SubType == ACPI_DP) { + if (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_HID_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } else if (RemainingDevicePath->SubType == ACPI_EXTENDED_DP) { + if (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } else { + return EFI_UNSUPPORTED; + } + } + // + // Test the existence of DEVICE_PATH protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the Isa Acpi protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaAcpiProtocolGuid, + (VOID **) &IsaAcpi, + 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, + &gEfiIsaAcpiProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +IsaBusControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL + ) +/*++ + + Routine Description: + + This function tells the ISA Bus Driver to start managing a PCI to ISA + Bridge controller. + + Arguments: + + This - The EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - A handle to the device being started. + RemainingDevicePath - A pointer to the remaining portion of a device path. + + Returns: + + EFI_SUCCESS - The device was started. + EFI_UNSUPPORTED - The device is not supported. + EFI_DEVICE_ERROR - The device could not be started due to a device error. + EFI_ALREADY_STARTED - The device has already been started. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of + resources. + +--*/ +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_ISA_ACPI_PROTOCOL *IsaAcpi; + EFI_ISA_ACPI_DEVICE_ID *IsaDevice; + EFI_ISA_ACPI_RESOURCE_LIST *ResourceList; + EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; + + // + // Local variables declaration for StatusCode reporting + // + EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData; + EFI_DEVICE_PATH_PROTOCOL *DevicePathData; + + BootScriptSaveInformationAsciiString ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + "IsaBusBindingStartBegin" + ); + + // + // Initialize status code structure + // + AllocFailExtendedData.DataHeader.HeaderSize = sizeof (EFI_STATUS_CODE_DATA); + AllocFailExtendedData.DataHeader.Size = sizeof (EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA) - sizeof (EFI_STATUS_CODE_DATA); + CopyMem ( + &AllocFailExtendedData.DataHeader.Type, + &gEfiStatusCodeSpecificDataGuid, + sizeof (EFI_GUID) + ); + + // + // Open Device Path Protocol + // + 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; + } + // + // Open Pci IO Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + // + // Close opened protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + // + // Open ISA Acpi Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaAcpiProtocolGuid, + (VOID **) &IsaAcpi, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + // + // Close opened protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + // + // The IsaBus driver will use memory below 16M, which is not tested yet, + // so call CompatibleRangeTest to test them. Since memory below 1M should + // be reserved to CSM, and 15M~16M might be reserved for Isa hole, test 1M + // ~15M here + // + Status = gBS->LocateProtocol ( + &gEfiGenericMemTestProtocolGuid, + NULL, + (VOID **) &GenMemoryTest + ); + + if (!EFI_ERROR (Status)) { + Status = GenMemoryTest->CompatibleRangeTest ( + GenMemoryTest, + 0x100000, + 0xE00000 + ); + } + // + // Report Status Code here since we will initialize the host controller + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_LPC | EFI_IOB_PC_INIT), + ParentDevicePath + ); + + // + // first init ISA interface + // + IsaAcpi->InterfaceInit (IsaAcpi); + + // + // Report Status Code here since we will enable the host controller + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_LPC | EFI_IOB_PC_ENABLE), + ParentDevicePath + ); + + // + // Create each ISA device handle in this ISA bus + // + IsaDevice = NULL; + do { + Status = IsaAcpi->DeviceEnumerate (IsaAcpi, &IsaDevice); + if (EFI_ERROR (Status)) { + break; + } + // + // Get current resource of this ISA device + // + ResourceList = NULL; + Status = IsaAcpi->GetCurResource (IsaAcpi, IsaDevice, &ResourceList); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Create handle for this ISA device + // + Status = IsaCreateDevice ( + This, + Controller, + PciIo, + ParentDevicePath, + ResourceList, + &DevicePathData + //&AllocFailExtendedData.DevicePath + ); + + if (EFI_ERROR (Status)) { + continue; + } + // + // Initialize ISA device + // + IsaAcpi->InitDevice (IsaAcpi, IsaDevice); + + // + // Set resources for this ISA device + // + Status = IsaAcpi->SetResource (IsaAcpi, IsaDevice, ResourceList); + + // + // Report Status Code here when failed to resource conflicts + // + if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) { + // + // It's hard to tell which resource conflicts + // + AllocFailExtendedData.Bar = 0; + AllocFailExtendedData.ReqRes = NULL; + AllocFailExtendedData.AllocRes = NULL; + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE, + (EFI_IO_BUS_LPC | EFI_IOB_EC_RESOURCE_CONFLICT), + DevicePathData + ); + + } + // + // Set power for this ISA device + // + IsaAcpi->SetPower (IsaAcpi, IsaDevice, TRUE); + + // + // Enable this ISA device + // + IsaAcpi->EnableDevice (IsaAcpi, IsaDevice, TRUE); + + } while (TRUE); + + BootScriptSaveInformationAsciiString ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + "IsaBusBindingStartEnd" + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IsaBusControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * ChildHandleBuffer OPTIONAL + ) +/*++ + + Routine Description: + + This function tells the ISA Bus Driver to stop managing a PCI to ISA + Bridge controller. + + Arguments: + + This - The EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - A handle to the device being stopped. + NumberOfChindren - The number of child device handles in ChildHandleBuffer. + ChildHandleBuffer - An array of child handles to be freed. + + + Returns: + + EFI_SUCCESS - The device was stopped. + EFI_DEVICE_ERROR - The device could not be stopped due to a device error. + EFI_NOT_STARTED - The device has not been started. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of + resources. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + BOOLEAN AllChildrenStopped; + ISA_IO_DEVICE *IsaIoDevice; + EFI_ISA_IO_PROTOCOL *IsaIo; + + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->CloseProtocol ( + Controller, + &gEfiIsaAcpiProtocolGuid, + This->DriverBindingHandle, + Controller + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; + } + // + // Complete all outstanding transactions to Controller. + // Don't allow any new transaction to Controller to be started. + // + // + // Stop all the children + // Find all the ISA devices that were discovered on this PCI to ISA Bridge + // with the Start() function. + // + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + IsaIoDevice->DevicePath, + &gEfiIsaIoProtocolGuid, + &IsaIoDevice->IsaIo, + NULL + ); + + if (!EFI_ERROR (Status)) { + // + // Close the child handle + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + gBS->FreePool (IsaIoDevice->DevicePath); + gBS->FreePool (IsaIoDevice); + } + } + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} +// +// Internal Function +// +EFI_STATUS +IsaCreateDevice ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList, + OUT EFI_DEVICE_PATH_PROTOCOL **ChildDevicePath + ) +/*++ + + Routine Description: + + Create ISA device found by IsaPnpProtocol + + Arguments: + + This - The EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - The handle of ISA bus controller(PCI to ISA bridge) + PciIo - The Pointer to the PCI protocol + ParentDevicePath - Device path of the ISA bus controller + IsaDeviceResourceList - The resource list of the ISA device + ChildDevicePath - The pointer to the child device. + + Returns: + + EFI_SUCCESS - Create the child device. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of + resources. + EFI_DEVICE_ERROR - Can not create child device. + +--*/ +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + EFI_DEV_PATH Node; + + // + // Initialize the PCI_IO_DEVICE structure + // + IsaIoDevice = AllocateZeroPool (sizeof (ISA_IO_DEVICE)); + if (IsaIoDevice == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + IsaIoDevice->Signature = ISA_IO_DEVICE_SIGNATURE; + IsaIoDevice->Handle = NULL; + IsaIoDevice->PciIo = PciIo; + + // + // Initialize the ISA I/O instance structure + // + Status = InitializeIsaIoInstance (IsaIoDevice, IsaDeviceResourceList); + if (EFI_ERROR (Status)) { + gBS->FreePool (IsaIoDevice); + return Status; + } + // + // Build the child device path + // + Node.DevPath.Type = ACPI_DEVICE_PATH; + Node.DevPath.SubType = ACPI_DP; + SetDevicePathNodeLength (&Node.DevPath, sizeof (ACPI_HID_DEVICE_PATH)); + Node.Acpi.HID = IsaDeviceResourceList->Device.HID; + Node.Acpi.UID = IsaDeviceResourceList->Device.UID; + + IsaIoDevice->DevicePath = AppendDevicePathNode ( + ParentDevicePath, + &Node.DevPath + ); + + if (IsaIoDevice->DevicePath == NULL) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + *ChildDevicePath = IsaIoDevice->DevicePath; + + // + // Create a child handle and attach the DevicePath, + // PCI I/O, and Controller State + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &IsaIoDevice->Handle, + &gEfiDevicePathProtocolGuid, + IsaIoDevice->DevicePath, + &gEfiIsaIoProtocolGuid, + &IsaIoDevice->IsaIo, + NULL + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + IsaIoDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + gBS->UninstallMultipleProtocolInterfaces ( + IsaIoDevice->Handle, + &gEfiDevicePathProtocolGuid, + IsaIoDevice->DevicePath, + &gEfiIsaIoProtocolGuid, + &IsaIoDevice->IsaIo, + NULL + ); + } + +Done: + + if (EFI_ERROR (Status)) { + if (IsaIoDevice->DevicePath != NULL) { + gBS->FreePool (IsaIoDevice->DevicePath); + } + + gBS->FreePool (IsaIoDevice); + } + + return Status; +} diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.inf b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.inf new file mode 100644 index 0000000000..1d4c596d17 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.inf @@ -0,0 +1,145 @@ +#/** @file +# Component description file for IsaBus module. +# +# Discovers all the ISA Controllers and their resources by using the ISA PnP +# Protocol, produces an instance of the ISA I/O Protocol for every ISA +# Controller found, loads and initializes all ISA Device Drivers, matches ISA +# Device Drivers with their respective ISA Controllers in a deterministic +# manner, and informs a ISA Device Driver when it is to start managing an ISA +# Controller. +# Copyright (c) 2006 - 2007, Intel Corporation. +# +# All rights reserved. +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = IsaBus + FILE_GUID = 240612B5-A063-11d4-9A3A-0090273FC14D + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = InitializeIsaBus + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gIsaBusControllerDriver +# COMPONENT_NAME = gIsaBusComponentName +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + ComponentName.c + IsaIo.c + IsaBus.c + IsaIo.h + IsaBus.h + IsaAcpi.h + ComponentName.h + CommonHeader.h + EntryPoint.c + + +################################################################################ +# +# Includes Section - list of Include locations that are required for +# this module. +# +################################################################################ + +[Includes] + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + PcdLib + BootScriptLib + ReportStatusCodeLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + DevicePathLib + UefiLib + UefiDriverEntryPoint + DebugLib + + +################################################################################ +# +# Guid C Name Section - list of Guids that this module uses or produces. +# +################################################################################ + +[Guids] + gEfiStatusCodeSpecificDataGuid # ALWAYS_CONSUMED + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiIsaIoProtocolGuid # PROTOCOL BY_START + gEfiIsaAcpiProtocolGuid # PROTOCOL TO_START + gEfiPciIoProtocolGuid # PROTOCOL TO_START + gEfiDevicePathProtocolGuid # PROTOCOL TO_START + gEfiGenericMemTestProtocolGuid # PROTOCOL TO_START + + +################################################################################ +# +# Pcd FEATURE_FLAG - list of PCDs that this module is coded for. +# +################################################################################ + +[PcdsFeatureFlag.common] + PcdIsaBusOnlySupportSlaveDma|gEfiIntelFrameworkModulePkgTokenSpaceGuid + PcdIsaBusSupportDma|gEfiIntelFrameworkModulePkgTokenSpaceGuid + PcdIsaBusSupportIsaMemory|gEfiIntelFrameworkModulePkgTokenSpaceGuid + diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.msa b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.msa new file mode 100644 index 0000000000..cc2cf6a33a --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.msa @@ -0,0 +1,142 @@ + + + + IsaBus + DXE_DRIVER + 240612B5-A063-11d4-9A3A-0090273FC14D + 1.0 + Component description file for IsaBus module. + Discovers all the ISA Controllers and their resources by using the ISA PnP + Protocol, produces an instance of the ISA I/O Protocol for every ISA + Controller found, loads and initializes all ISA Device Drivers, matches ISA + Device Drivers with their respective ISA Controllers in a deterministic + manner, and informs a ISA Device Driver when it is to start managing an ISA + Controller. + Copyright (c) 2006 - 2007, Intel Corporation. + All rights reserved. + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + IsaBus + + + + DebugLib + + + UefiDriverModelLib + + + UefiDriverEntryPoint + + + UefiLib + + + DevicePathLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + ReportStatusCodeLib + + + BootScriptLib + + + PcdLib + + + + ComponentName.h + IsaAcpi.h + IsaBus.h + IsaIo.h + IsaBus.c + IsaIo.c + ComponentName.c + + + + + + + + + gEfiGenericMemTestProtocolGuid + + + gEfiDevicePathProtocolGuid + + + gEfiPciIoProtocolGuid + + + gEfiIsaAcpiProtocolGuid + + + gEfiIsaIoProtocolGuid + + + + + gEfiStatusCodeSpecificDataGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + gIsaBusControllerDriver + gIsaBusComponentName + + + + + PcdIsaBusSupportIsaMemory + gEfiGenericPlatformTokenSpaceGuid + TRUE + This feature flag is used to enable the implementation for interface + _EFI_ISA_IO_PROTOCOL.Mem.Read, _EFI_ISA_IO_PROTOCOL.Mem.Write and _EFI_ISA_IO_PROTOCOL.CopyMem. + If it is unset, these interfaces will return EFI_UNSUPPORTED. When it is disabled, + it is will save code size if a platform does not have ISA device with ISA memory. + + + PcdIsaBusSupportDma + gEfiGenericPlatformTokenSpaceGuid + TRUE + This feature flag is used to enable the implementation for interface + _EFI_ISA_IO_PROTOCOL.AllocateBuffer, _EFI_ISA_IO_PROTOCOL.FreeBuffer, _EFI_ISA_IO_PROTOCOL.Map + and _EFI_ISA_IO_PROTOCOL.UnMap. If it is unset, these interfaces will return EFI_UNSUPPORTED. + It is useful to save code size if a platform does not have ISA device which did DMA transfer. + + + PcdIsaBusOnlySupportSlaveDma + gEfiGenericPlatformTokenSpaceGuid + FALSE + This feature flag is used to enable the implementation for interface + _EFI_ISA_IO_PROTOCOL.Map and _EFI_ISA_IO_PROTOCOL.UnMap to only support Slave DMA + transfers. In addition, unsetting this feature flag also make AllocateBuffer() and + FreeBuffer() to return EFI_UNSUPPORTED. It is useful to save code size if a platform have only + ISA device to do slave DMA R/W transfer. This flag is only effective when PcdIsaBusSupportDma + is set to TRUE. If PcdIsaBusSupportDma is set to FALSE, Map() and UnMap() will simply + return EFI_UNSUPPORTED. Please check description for PcdIsaBusSupportDma for details. + + + \ No newline at end of file diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c new file mode 100644 index 0000000000..1a3497dfda --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c @@ -0,0 +1,1646 @@ +/*++ + +Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + + +Module Name: + + IsaIo.c + +Abstract: + + The implementation for EFI_ISA_IO_PROTOCOL. + +--*/ + +// +// Include common header file for this module. +// +#include "InternalIsaIo.h" + +#include + +// +// Driver Support Global Variables +// +EFI_ISA_IO_PROTOCOL IsaIoInterface = { + { + IsaIoMemRead, + IsaIoMemWrite + }, + { + IsaIoIoRead, + IsaIoIoWrite + }, + IsaIoCopyMem, + IsaIoMap, + IsaIoUnmap, + IsaIoAllocateBuffer, + IsaIoFreeBuffer, + IsaIoFlush, + NULL, + 0, + NULL +}; + +static EFI_ISA_DMA_REGISTERS DmaRegisters[8] = { + { + 0x00, + 0x87, + 0x01 + }, + { + 0x02, + 0x83, + 0x03 + }, + { + 0x04, + 0x81, + 0x05 + }, + { + 0x06, + 0x82, + 0x07 + }, + { + 0x00, + 0x00, + 0x00 + }, // Channel 4 is invalid + { + 0xC4, + 0x8B, + 0xC6 + }, + { + 0xC8, + 0x89, + 0xCA + }, + { + 0xCC, + 0x8A, + 0xCE + }, +}; + +EFI_STATUS +ReportErrorStatusCode ( + EFI_STATUS_CODE_VALUE Code + ) +/*++ + +Routine Description: + + report a error Status code of PCI bus driver controller + +Arguments: + + Code - The error status code. + +Returns: + + EFI_SUCCESS - Success to report status code. + + +--*/ +{ + return REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + Code + ); +} + +// +// Driver Support Functions +// + +EFI_STATUS +InitializeIsaIoInstance ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList + ) +/*++ + +Routine Description: + + Initializes an ISA I/O Instance + +Arguments: + + IsaIoDevice - The iso device to be initialized. + IsaDeviceResourceList - The resource list. + +Returns: + + EFI_SUCCESS - Initial success. + +--*/ +{ + // + // Initializes an ISA I/O Instance + // + CopyMem ( + &IsaIoDevice->IsaIo, + &IsaIoInterface, + sizeof (EFI_ISA_IO_PROTOCOL) + ); + + IsaIoDevice->IsaIo.ResourceList = IsaDeviceResourceList; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IsaIoIoRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs an ISA I/O Read Cycle + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Width - Signifies the width of the I/O operation. + Offset - The offset in ISA I/O space to start the I/O operation. + Count - The number of I/O operations to perform. + Buffer - The destination buffer to store the results + +Returns: + + EFI_SUCCESS - The data was read from the device sucessfully. + EFI_UNSUPPORTED - The Offset is not valid for this device. + EFI_INVALID_PARAMETER - Width or Count, or both, were invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. + +--*/ +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeIo, + Width, + Count, + &Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Call PciIo->Io.Read + // + Status = IsaIoDevice->PciIo->Io.Read ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +IsaIoIoWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs an ISA I/O Write Cycle + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Width - Signifies the width of the I/O operation. + Offset - The offset in ISA I/O space to start the I/O operation. + Count - The number of I/O operations to perform. + Buffer - The source buffer to write data from + +Returns: + + EFI_SUCCESS - The data was writen to the device sucessfully. + EFI_UNSUPPORTED - The Offset is not valid for this device. + EFI_INVALID_PARAMETER - Width or Count, or both, were invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. + +--*/ +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeIo, + Width, + Count, + &Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Call PciIo->Io.Write + // + Status = IsaIoDevice->PciIo->Io.Write ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +WritePort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 Offset, + IN UINT8 Value + ) +/*++ + +Routine Description: + + Writes an 8 bit I/O Port + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Offset - The offset in ISA IO space to start the IO operation. + Value - The data to write port. + +Returns: + + EFI_SUCCESS - Success. + EFI_INVALID_PARAMETER - Parameter is invalid. + EFI_UNSUPPORTED - The address range specified by Offset is not valid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. + +--*/ +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Call PciIo->Io.Write + // + Status = IsaIoDevice->PciIo->Io.Write ( + IsaIoDevice->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + 1, + &Value + ); + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR); + return Status; + } + + gBS->Stall (50); + + return EFI_SUCCESS; +} + +EFI_STATUS +WriteDmaPort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 AddrOffset, + IN UINT32 PageOffset, + IN UINT32 CountOffset, + IN UINT32 BaseAddress, + IN UINT16 Count + ) +/*++ + +Routine Description: + + Writes I/O operation base address and count number to a 8 bit I/O Port. + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + AddrOffset - The address' offset. + PageOffset - The page's offest. + CountOffset - The count's offset. + BaseAddress - The base address. + Count - The number of I/O operations to perform. + +Returns: + + EFI_SUCCESS - Success. + EFI_INVALID_PARAMETER - Parameter is invalid. + EFI_UNSUPPORTED - The address range specified by these Offsets and Count is not valid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. + +--*/ +{ + EFI_STATUS Status; + + Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IsaIoUnmap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ) +/*++ + +Routine Description: + + Unmaps a memory region for DMA + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Mapping - The mapping value returned from EFI_ISA_IO.Map(). + +Returns: + + EFI_SUCCESS - The range was unmapped. + EFI_DEVICE_ERROR - The data was not committed to the target system memory. + +--*/ +{ + ISA_MAP_INFO *IsaMapInfo; + + // + // Unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. + // + if (!FeaturePcdGet (PcdIsaBusSupportDma)) { + return EFI_UNSUPPORTED; + } + + // + // See if the Map() operation associated with this Unmap() required a mapping + // buffer.If a mapping buffer was not required, then this function simply + // returns EFI_SUCCESS. + // + if (Mapping != NULL) { + // + // Get the MAP_INFO structure from Mapping + // + IsaMapInfo = (ISA_MAP_INFO *) Mapping; + + // + // If this is a write operation from the Agent's point of view, + // then copy the contents of the mapped buffer into the real buffer + // so the processor can read the contents of the real buffer. + // + if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->HostAddress, + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // Free the mapped buffer and the MAP_INFO structure. + // + gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages); + gBS->FreePool (IsaMapInfo); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IsaIoFlush ( + IN EFI_ISA_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + Flushes a DMA buffer + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + +Returns: + + EFI_SUCCESS - The buffers were flushed. + EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error. + +--*/ +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Call PciIo->Flush + // + Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +IsaIoVerifyAccess ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN ISA_ACCESS_TYPE Type, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN OUT UINT32 *Offset + ) +/*++ + +Routine Description: + + Verifies access to an ISA device + +Arguments: + + IsaIoDevice - The ISA device to be verified. + Type - The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. + Width - Signifies the width of the memory operation. + Count - The number of memory operations to perform. + Offset - The offset in ISA memory space to start the memory operation. + +Returns: + + EFI_SUCCESS - Verify success. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + EFI_UNSUPPORTED - The device ont support the access type. + +--*/ +{ + EFI_ISA_ACPI_RESOURCE *Item; + EFI_STATUS Status; + + if (Width < EfiIsaIoWidthUint8 || + Width >= EfiIsaIoWidthMaximum || + Width == EfiIsaIoWidthReserved || + Width == EfiIsaIoWidthFifoReserved || + Width == EfiIsaIoWidthFillReserved + ) { + return EFI_INVALID_PARAMETER; + } + + // + // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX + // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX + // + if (Width >= EfiIsaIoWidthFifoUint8 && Width <= EfiIsaIoWidthFifoReserved) { + Count = 1; + } + + Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03); + + Status = EFI_UNSUPPORTED; + Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem; + while (Item->Type != EfiIsaAcpiResourceEndOfList) { + if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) || + (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo) + ) { + if (*Offset >= Item->StartRange && (*Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) { + return EFI_SUCCESS; + } + + if (*Offset >= Item->StartRange && *Offset <= Item->EndRange) { + Status = EFI_INVALID_PARAMETER; + } + } + + Item++; + } + + return Status; +} + +EFI_STATUS +EFIAPI +IsaIoMemRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs an ISA Memory Read Cycle + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Width - Signifies the width of the memory operation. + Offset - The offset in ISA memory space to start the memory operation. + Count - The number of memory operations to perform. + Buffer - The destination buffer to store the results + +Returns: + + EFI_SUCCESS - The data was read from the device successfully. + EFI_UNSUPPORTED - The Offset is not valid for this device. + EFI_INVALID_PARAMETER - Width or Count, or both, were invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. + +--*/ +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for + // ISA Bus Master. + // + // So we just return EFI_UNSUPPORTED for these functions. + // + if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory)) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify the Isa Io Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + &Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Call PciIo->Mem.Read + // + Status = IsaIoDevice->PciIo->Mem.Read ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +IsaIoMemWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs an ISA Memory Write Cycle + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Width - Signifies the width of the memory operation. + Offset - The offset in ISA memory space to start the memory operation. + Count - The number of memory operations to perform. + Buffer - The source buffer to write data from + +Returns: + + EFI_SUCCESS - The data was written to the device sucessfully. + EFI_UNSUPPORTED - The Offset is not valid for this device. + EFI_INVALID_PARAMETER - Width or Count, or both, were invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. + +--*/ +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for + // ISA Bus Master. + // + // So we just return EFI_UNSUPPORTED for these functions. + // + if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory)) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + &Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Call PciIo->Mem.Write + // + Status = IsaIoDevice->PciIo->Mem.Write ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +IsaIoCopyMem ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ) +/*++ + +Routine Description: + + Performs an ISA I/O Copy Memory + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Width - Signifies the width of the memory copy operation. + DestOffset - The offset of the destination + SrcOffset - The offset of the source + Count - The number of memory copy operations to perform + +Returns: + + EFI_SUCCESS - The data was copied sucessfully. + EFI_UNSUPPORTED - The DestOffset or SrcOffset is not valid for this device. + EFI_INVALID_PARAMETER - Width or Count, or both, were invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. + +--*/ +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for + // ISA Bus Master. + // + // So we just return EFI_UNSUPPORTED for these functions. + // + if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory)) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access for destination and source + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + &DestOffset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + &SrcOffset + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Call PciIo->CopyMem + // + Status = IsaIoDevice->PciIo->CopyMem ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + DestOffset, + EFI_PCI_IO_PASS_THROUGH_BAR, + SrcOffset, + Count + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +STATIC +EFI_STATUS +IsaIoMap_OnlySupportSlaveReadWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +/*++ + +Routine Description: + + Maps a memory region for DMA, note this implementation + only supports slave read/write operation to save code size. + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Operation - Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + ChannelNumber - The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + ChannelAttributes - The attributes of the DMA channel to use for this DMA operation + HostAddress - The system memory address to map to the device. + NumberOfBytes - On input the number of bytes to map. On output the number + of bytes that were mapped. + DeviceAddress - The resulting map address for the bus master device to use + to access the hosts HostAddress. + Mapping - A resulting value to pass to EFI_ISA_IO.Unmap(). + +Returns: + + EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. + EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. + EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer. + EFI_DEVICE_ERROR - The system hardware could not map the requested address. + EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + ISA_MAP_INFO *IsaMapInfo; + UINT8 DmaMode; + UINTN MaxNumberOfBytes; + UINT32 BaseAddress; + UINT16 Count; + + UINT8 DmaMask; + UINT8 DmaClear; + UINT8 DmaChannelMode; + + if ((NULL == This) || + (NULL == HostAddress) || + (NULL == NumberOfBytes) || + (NULL == DeviceAddress) || + (NULL == Mapping) + ) { + return EFI_INVALID_PARAMETER; + } + + + // + // Initialize the return values to their defaults + // + *Mapping = NULL; + + // + // Make sure the Operation parameter is valid. + // Light IsaIo only supports two operations. + // + if (!(Operation == EfiIsaIoOperationSlaveRead || + Operation == EfiIsaIoOperationSlaveWrite)) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber >= 4) { + // + // The Light IsaIo doesn't support channelNumber larger than 4. + // + return EFI_INVALID_PARAMETER; + } + + // + // Map the HostAddress to a DeviceAddress. + // + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + if ((PhysicalAddress +*NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) { + // + // Common Buffer operations can not be remapped. If the common buffer + // is above 16MB, then it is not possible to generate a mapping, so return + // an error. + // + if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { + return EFI_UNSUPPORTED; + } + // + // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() + // is called later. + // + IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); + if (IsaMapInfo == NULL) { + *NumberOfBytes = 0; + return EFI_OUT_OF_RESOURCES; + } + // + // Return a pointer to the MAP_INFO structure in Mapping + // + *Mapping = IsaMapInfo; + + // + // Initialize the MAP_INFO structure + // + IsaMapInfo->Operation = Operation; + IsaMapInfo->NumberOfBytes = *NumberOfBytes; + IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); + IsaMapInfo->HostAddress = PhysicalAddress; + IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1; + + // + // Allocate a buffer below 16MB to map the transfer to. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + IsaMapInfo->NumberOfPages, + &IsaMapInfo->MappedHostAddress + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (IsaMapInfo); + *NumberOfBytes = 0; + *Mapping = NULL; + return Status; + } + // + // If this is a read operation from the DMA agents's point of view, + // then copy the contents of the real buffer into the mapped buffer + // so the DMA agent can read the contents of the real buffer. + // + if (Operation == EfiIsaIoOperationSlaveRead) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + (VOID *) (UINTN) IsaMapInfo->HostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // The DeviceAddress is the address of the maped buffer below 16 MB + // + *DeviceAddress = IsaMapInfo->MappedHostAddress; + } else { + // + // The transfer is below 16 MB, so the DeviceAddress is simply the + // HostAddress + // + *DeviceAddress = PhysicalAddress; + } + + // + // Figure out what to program into the DMA Channel Mode Register + // + DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); + if (Operation == EfiIsaIoOperationSlaveRead) { + DmaMode |= V_8237_DMA_CHMODE_MEM2IO; + } else { + DmaMode |= V_8237_DMA_CHMODE_IO2MEM; + } + // + // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo + // + DmaMode |= V_8237_DMA_CHMODE_SINGLE; + + // + // A Slave DMA transfer can not cross a 64K boundary. + // Compute *NumberOfBytes based on this restriction. + // + MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); + if (*NumberOfBytes > MaxNumberOfBytes) { + *NumberOfBytes = MaxNumberOfBytes; + } + // + // Compute the values to program into the BaseAddress and Count registers + // of the Slave DMA controller + // + BaseAddress = (UINT32) (*DeviceAddress); + Count = (UINT16) (*NumberOfBytes - 1); + // + // Program the DMA Write Single Mask Register for ChannelNumber + // Clear the DMA Byte Pointer Register + // + DmaMask = R_8237_DMA_WRSMSK_CH0_3; + DmaClear = R_8237_DMA_CBPR_CH0_3; + DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; + + Status = WritePort ( + This, + DmaMask, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaClear, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, DmaChannelMode, DmaMode); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WriteDmaPort ( + This, + DmaRegisters[ChannelNumber].Address, + DmaRegisters[ChannelNumber].Page, + DmaRegisters[ChannelNumber].Count, + BaseAddress, + Count + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (ChannelNumber & 0x03) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +IsaIoMap_FullSupport ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +/*++ + +Routine Description: + + Maps a memory region for DMA. This implementation implement the + the full mapping support. + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Operation - Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + ChannelNumber - The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + ChannelAttributes - The attributes of the DMA channel to use for this DMA operation + HostAddress - The system memory address to map to the device. + NumberOfBytes - On input the number of bytes to map. On output the number + of bytes that were mapped. + DeviceAddress - The resulting map address for the bus master device to use + - to access the hosts HostAddress. + Mapping - A resulting value to pass to EFI_ISA_IO.Unmap(). + +Returns: + + EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. + EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. + EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer. + EFI_DEVICE_ERROR - The system hardware could not map the requested address. + EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. + +--*/ +{ + EFI_STATUS Status; + BOOLEAN Master; + BOOLEAN Read; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + ISA_MAP_INFO *IsaMapInfo; + UINT8 DmaMode; + UINTN MaxNumberOfBytes; + UINT32 BaseAddress; + UINT16 Count; + + UINT8 DmaMask; + UINT8 DmaClear; + UINT8 DmaChannelMode; + + if ((NULL == This) || + (NULL == HostAddress) || + (NULL == NumberOfBytes) || + (NULL == DeviceAddress) || + (NULL == Mapping) + ) { + return EFI_INVALID_PARAMETER; + } + + + // + // Initialize the return values to their defaults + // + *Mapping = NULL; + + // + // Make sure the Operation parameter is valid + // + if (Operation < 0 || Operation >= EfiIsaIoOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + // + // See if this is a Slave DMA Operation + // + Master = TRUE; + Read = FALSE; + if (Operation == EfiIsaIoOperationSlaveRead) { + Operation = EfiIsaIoOperationBusMasterRead; + Master = FALSE; + Read = TRUE; + } + + if (Operation == EfiIsaIoOperationSlaveWrite) { + Operation = EfiIsaIoOperationBusMasterWrite; + Master = FALSE; + Read = FALSE; + } + + if (!Master) { + // + // Make sure that ChannelNumber is a valid channel number + // Channel 4 is used to cascade, so it is illegal. + // + if (ChannelNumber == 4 || ChannelNumber > 7) { + return EFI_INVALID_PARAMETER; + } + // + // This implementation only support COMPATIBLE DMA Transfers + // + if (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE)) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelAttributes & + ( + EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A | + EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B | + EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C + ) + ) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber < 4) { + // + // If this is Channel 0..3, then the width must be 8 bit + // + if (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) || + (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) + ) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // If this is Channel 4..7, then the width must be 16 bit + // + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) || + (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16)) + ) { + return EFI_INVALID_PARAMETER; + } + } + // + // Either Demand Mode or Single Mode must be selected, but not both + // + if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) { + if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) { + return EFI_INVALID_PARAMETER; + } + } else { + if (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE)) { + return EFI_INVALID_PARAMETER; + } + } + } + // + // Map the HostAddress to a DeviceAddress. + // + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + if ((PhysicalAddress +*NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) { + // + // Common Buffer operations can not be remapped. If the common buffer + // is above 16MB, then it is not possible to generate a mapping, so return + // an error. + // + if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { + return EFI_UNSUPPORTED; + } + // + // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() + // is called later. + // + IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); + if (IsaMapInfo == NULL) { + *NumberOfBytes = 0; + return EFI_OUT_OF_RESOURCES; + } + // + // Return a pointer to the MAP_INFO structure in Mapping + // + *Mapping = IsaMapInfo; + + // + // Initialize the MAP_INFO structure + // + IsaMapInfo->Operation = Operation; + IsaMapInfo->NumberOfBytes = *NumberOfBytes; + IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); + IsaMapInfo->HostAddress = PhysicalAddress; + IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1; + + // + // Allocate a buffer below 16MB to map the transfer to. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + IsaMapInfo->NumberOfPages, + &IsaMapInfo->MappedHostAddress + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (IsaMapInfo); + *NumberOfBytes = 0; + *Mapping = NULL; + return Status; + } + // + // If this is a read operation from the DMA agents's point of view, + // then copy the contents of the real buffer into the mapped buffer + // so the DMA agent can read the contents of the real buffer. + // + if (Operation == EfiIsaIoOperationBusMasterRead) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + (VOID *) (UINTN) IsaMapInfo->HostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // The DeviceAddress is the address of the maped buffer below 16 MB + // + *DeviceAddress = IsaMapInfo->MappedHostAddress; + } else { + // + // The transfer is below 16 MB, so the DeviceAddress is simply the + // HostAddress + // + *DeviceAddress = PhysicalAddress; + } + // + // If this is a Bus Master operation then return + // + if (Master) { + return EFI_SUCCESS; + } + // + // Figure out what to program into the DMA Channel Mode Register + // + DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); + if (Read) { + DmaMode |= V_8237_DMA_CHMODE_MEM2IO; + } else { + DmaMode |= V_8237_DMA_CHMODE_IO2MEM; + } + + if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) { + DmaMode |= B_8237_DMA_CHMODE_AE; + } + + if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) { + DmaMode |= V_8237_DMA_CHMODE_DEMAND; + } + + if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) { + DmaMode |= V_8237_DMA_CHMODE_SINGLE; + } + // + // A Slave DMA transfer can not cross a 64K boundary. + // Compute *NumberOfBytes based on this restriction. + // + MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); + if (*NumberOfBytes > MaxNumberOfBytes) { + *NumberOfBytes = MaxNumberOfBytes; + } + // + // Compute the values to program into the BaseAddress and Count registers + // of the Slave DMA controller + // + if (ChannelNumber < 4) { + BaseAddress = (UINT32) (*DeviceAddress); + Count = (UINT16) (*NumberOfBytes - 1); + } else { + BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1)); + Count = (UINT16) ((*NumberOfBytes - 1) >> 1); + } + // + // Program the DMA Write Single Mask Register for ChannelNumber + // Clear the DMA Byte Pointer Register + // + if (ChannelNumber < 4) { + DmaMask = R_8237_DMA_WRSMSK_CH0_3; + DmaClear = R_8237_DMA_CBPR_CH0_3; + DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; + } else { + DmaMask = R_8237_DMA_WRSMSK_CH4_7; + DmaClear = R_8237_DMA_CBPR_CH4_7; + DmaChannelMode = R_8237_DMA_CHMODE_CH4_7; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaClear, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, DmaChannelMode, DmaMode); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WriteDmaPort ( + This, + DmaRegisters[ChannelNumber].Address, + DmaRegisters[ChannelNumber].Page, + DmaRegisters[ChannelNumber].Count, + BaseAddress, + Count + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (ChannelNumber & 0x03) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IsaIoMap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +/*++ + +Routine Description: + + Maps a memory region for DMA + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Operation - Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + ChannelNumber - The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + ChannelAttributes - The attributes of the DMA channel to use for this DMA operation + HostAddress - The system memory address to map to the device. + NumberOfBytes - On input the number of bytes to map. On output the number + of bytes that were mapped. + DeviceAddress - The resulting map address for the bus master device to use + - to access the hosts HostAddress. + Mapping - A resulting value to pass to EFI_ISA_IO.Unmap(). + +Returns: + + EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. + EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. + EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer. + EFI_DEVICE_ERROR - The system hardware could not map the requested address. + EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. + +--*/ +{ + // + // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. + // + if (!FeaturePcdGet (PcdIsaBusSupportDma)) { + return EFI_UNSUPPORTED; + } + // + // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for + // ISA Bus Master. + // + // So we just return EFI_UNSUPPORTED for these functions. + // + if (FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma)) { + return IsaIoMap_OnlySupportSlaveReadWrite ( + This, + Operation, + ChannelNumber, + ChannelAttributes, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + + } else { + return IsaIoMap_FullSupport ( + This, + Operation, + ChannelNumber, + ChannelAttributes, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + } +} +EFI_STATUS +EFIAPI +IsaIoAllocateBuffer ( + IN EFI_ISA_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: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Type - The type allocation to perform. + MemoryType - The type of memory to allocate. + Pages - The number of pages to allocate. + HostAddress - A pointer to store the base address of the allocated range. + Attributes - The requested bit mask of attributes for the allocated range. + +Returns: + + EFI_SUCCESS - The requested memory pages were allocated. + EFI_INVALID_PARAMETER - Type is invalid or MemoryType is invalid or HostAddress is NULL + EFI_UNSUPPORTED - Attributes is unsupported or the memory range specified + by HostAddress, Pages, and Type is not available for common buffer use. + EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + // + // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for + // ISA Bus Master. + // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. + // + if (!FeaturePcdGet (PcdIsaBusSupportDma) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma)) { + return EFI_UNSUPPORTED; + } + + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Type < AllocateAnyPages || Type >= MaxAllocateType) { + return EFI_INVALID_PARAMETER; + } + // + // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData + // + if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { + return EFI_INVALID_PARAMETER; + } + + if (Attributes &~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) { + return EFI_UNSUPPORTED; + } + + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (ISA_MAX_MEMORY_ADDRESS - 1); + if (Type == AllocateAddress) { + if ((UINTN) (*HostAddress) >= ISA_MAX_MEMORY_ADDRESS) { + return EFI_UNSUPPORTED; + } else { + PhysicalAddress = (UINTN) (*HostAddress); + } + } + + if (Type == AllocateAnyPages) { + Type = AllocateMaxAddress; + } + + Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress); + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR); + return Status; + } + + *HostAddress = (VOID *) (UINTN) PhysicalAddress; + return Status; +} + +EFI_STATUS +EFIAPI +IsaIoFreeBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +/*++ + +Routine Description: + + Frees a common buffer + +Arguments: + + This - A pointer to the EFI_ISA_IO_PROTOCOL instance. + Pages - The number of pages to free. + HostAddress - The base address of the allocated range. + +Returns: + + EFI_SUCCESS - The requested memory pages were freed. + EFI_INVALID_PARAMETER - The memory was not allocated with EFI_ISA_IO.AllocateBufer(). + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + // + // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for + // ISA Bus Master. + // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. + // + if (!FeaturePcdGet (PcdIsaBusSupportDma) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma)) { + return EFI_UNSUPPORTED; + } + + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + Status = gBS->FreePages ( + PhysicalAddress, + Pages + ); + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + -- cgit v1.2.3