--- /dev/null
+/** @file\r
+ IsaIo UEFI driver.\r
+\r
+ Produce an instance of the ISA I/O Protocol for every SIO controller.\r
+ \r
+Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "IsaDriver.h"\r
+\r
+//\r
+// IsaIo Driver Global Variables\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gIsaIoDriver = {\r
+ IsaIoDriverSupported,\r
+ IsaIoDriverStart,\r
+ IsaIoDriverStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+/**\r
+ The main entry point for the IsaIo driver.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+ \r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeIsaIo (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Install driver model protocol(s).\r
+ //\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gIsaIoDriver,\r
+ ImageHandle,\r
+ &gIsaIoComponentName,\r
+ &gIsaIoComponentName2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+/** \r
+ Tests to see if a controller can be managed by the IsaIo driver.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. \r
+ @param[in] Controller The handle of the controller to test.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.\r
+ \r
+ @retval EFI_SUCCESS The device is supported by this driver.\r
+ @retval EFI_ALREADY_STARTED The device is already being managed by this driver.\r
+ @retval EFI_ACCESS_DENIED The device is already being managed by a different driver \r
+ or an application that requires exclusive access.\r
+ @retval EFI_UNSUPPORTED The device is is not supported by this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoDriverSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_SIO_PROTOCOL *Sio;\r
+ EFI_HANDLE PciHandle;\r
+\r
+ //\r
+ // Try to open EFI DEVICE PATH protocol on the controller\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Get the PciIo protocol from its parent controller.\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &DevicePath, &PciHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((DevicePathType (DevicePath) != ACPI_DEVICE_PATH) ||\r
+ ((DevicePathSubType (DevicePath) != ACPI_DP) && (DevicePathSubType (DevicePath) != ACPI_EXTENDED_DP))) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Try to open the Super IO protocol on the controller\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiSioProtocolGuid,\r
+ (VOID **) &Sio,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiSioProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Start this driver on ControllerHandle. \r
+ \r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController(). \r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, but the following calling \r
+ restrictions must be followed or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. \r
+ This parameter is ignored by device drivers, and is optional for bus drivers.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.\r
+ Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoDriverStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_HANDLE PciHandle;\r
+ EFI_SIO_PROTOCOL *Sio;\r
+ ACPI_RESOURCE_HEADER_PTR Resources;\r
+ EFI_DEVICE_PATH_PROTOCOL *AcpiNode;\r
+ ISA_IO_DEVICE *IsaIoDevice;\r
+\r
+ PciIo = NULL;\r
+ Sio = NULL;\r
+\r
+ //\r
+ // Open Device Path Protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the PciIo protocol from its parent controller.\r
+ //\r
+ AcpiNode = DevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &AcpiNode, &PciHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // AcpiNode should point to the ACPI node now.\r
+ //\r
+ ASSERT ((DevicePathType (AcpiNode) == ACPI_DEVICE_PATH) &&\r
+ ((DevicePathSubType (AcpiNode) == ACPI_DP) || (DevicePathSubType (AcpiNode) == ACPI_EXTENDED_DP))\r
+ );\r
+\r
+ Status = gBS->HandleProtocol (PciHandle, &gEfiPciIoProtocolGuid, &PciIo);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Open Super IO Protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiSioProtocolGuid,\r
+ (VOID **) &Sio,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Fail due to LocateDevicePath(...) or OpenProtocol(Sio, BY_DRIVER)\r
+ //\r
+ return Status;\r
+ }\r
+\r
+ Status = Sio->GetResources (Sio, &Resources);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ IsaIoDevice = AllocatePool (sizeof (ISA_IO_DEVICE));\r
+ ASSERT (IsaIoDevice != NULL);\r
+\r
+ IsaIoDevice->Signature = ISA_IO_DEVICE_SIGNATURE;\r
+ IsaIoDevice->PciIo = PciIo;\r
+\r
+ //\r
+ // Initialize the ISA I/O instance structure\r
+ //\r
+ InitializeIsaIoInstance (IsaIoDevice, DevicePath, Resources);\r
+\r
+ //\r
+ // Install the ISA I/O protocol on the Controller handle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Controller,\r
+ &gEfiIsaIoProtocolGuid,\r
+ &IsaIoDevice->IsaIo,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Stop this driver on ControllerHandle. \r
+ \r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoDriverStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE * ChildHandleBuffer OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ISA_IO_DEVICE *IsaIoDevice;\r
+ EFI_ISA_IO_PROTOCOL *IsaIo;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiIsaIoProtocolGuid,\r
+ (VOID **) &IsaIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo);\r
+\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ Controller,\r
+ &gEfiIsaIoProtocolGuid,\r
+ &IsaIoDevice->IsaIo,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiSioProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ FreePool (IsaIoDevice->IsaIo.ResourceList);\r
+ FreePool (IsaIoDevice);\r
+ }\r
+\r
+ return Status;\r
+}
\ No newline at end of file
--- /dev/null
+/** @file\r
+ The header file for ISA driver\r
+ \r
+Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _ISA_DRIVER_H_\r
+#define _ISA_DRIVER_H_\r
+\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/SuperIo.h>\r
+#include <Protocol/ComponentName.h>\r
+#include <Protocol/IsaIo.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/DriverBinding.h>\r
+#include <Protocol/GenericMemoryTest.h>\r
+#include <Guid/StatusCodeDataTypeId.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <IndustryStandard/Acpi.h>\r
+\r
+#include "ComponentName.h"\r
+\r
+//\r
+// 8237 DMA registers\r
+//\r
+#define R_8237_DMA_BASE_CA_CH0 0x00\r
+#define R_8237_DMA_BASE_CA_CH1 0x02\r
+#define R_8237_DMA_BASE_CA_CH2 0x04\r
+#define R_8237_DMA_BASE_CA_CH3 0xd6\r
+#define R_8237_DMA_BASE_CA_CH5 0xc4\r
+#define R_8237_DMA_BASE_CA_CH6 0xc8\r
+#define R_8237_DMA_BASE_CA_CH7 0xcc\r
+\r
+#define R_8237_DMA_BASE_CC_CH0 0x01\r
+#define R_8237_DMA_BASE_CC_CH1 0x03\r
+#define R_8237_DMA_BASE_CC_CH2 0x05\r
+#define R_8237_DMA_BASE_CC_CH3 0xd7\r
+#define R_8237_DMA_BASE_CC_CH5 0xc6\r
+#define R_8237_DMA_BASE_CC_CH6 0xca\r
+#define R_8237_DMA_BASE_CC_CH7 0xce\r
+\r
+#define R_8237_DMA_MEM_LP_CH0 0x87\r
+#define R_8237_DMA_MEM_LP_CH1 0x83\r
+#define R_8237_DMA_MEM_LP_CH2 0x81\r
+#define R_8237_DMA_MEM_LP_CH3 0x82\r
+#define R_8237_DMA_MEM_LP_CH5 0x8B\r
+#define R_8237_DMA_MEM_LP_CH6 0x89\r
+#define R_8237_DMA_MEM_LP_CH7 0x8A\r
+\r
+\r
+#define R_8237_DMA_COMMAND_CH0_3 0x08\r
+#define R_8237_DMA_COMMAND_CH4_7 0xd0\r
+#define B_8237_DMA_COMMAND_GAP 0x10\r
+#define B_8237_DMA_COMMAND_CGE 0x04\r
+\r
+\r
+#define R_8237_DMA_STA_CH0_3 0xd8\r
+#define R_8237_DMA_STA_CH4_7 0xd0\r
+\r
+#define R_8237_DMA_WRSMSK_CH0_3 0x0a\r
+#define R_8237_DMA_WRSMSK_CH4_7 0xd4\r
+#define B_8237_DMA_WRSMSK_CMS 0x04\r
+\r
+\r
+#define R_8237_DMA_CHMODE_CH0_3 0x0b\r
+#define R_8237_DMA_CHMODE_CH4_7 0xd6\r
+#define V_8237_DMA_CHMODE_DEMAND 0x00\r
+#define V_8237_DMA_CHMODE_SINGLE 0x40\r
+#define V_8237_DMA_CHMODE_CASCADE 0xc0\r
+#define B_8237_DMA_CHMODE_DECREMENT 0x20\r
+#define B_8237_DMA_CHMODE_INCREMENT 0x00\r
+#define B_8237_DMA_CHMODE_AE 0x10\r
+#define V_8237_DMA_CHMODE_VERIFY 0\r
+#define V_8237_DMA_CHMODE_IO2MEM 0x04\r
+#define V_8237_DMA_CHMODE_MEM2IO 0x08\r
+\r
+#define R_8237_DMA_CBPR_CH0_3 0x0c\r
+#define R_8237_DMA_CBPR_CH4_7 0xd8\r
+\r
+#define R_8237_DMA_MCR_CH0_3 0x0d\r
+#define R_8237_DMA_MCR_CH4_7 0xda\r
+\r
+#define R_8237_DMA_CLMSK_CH0_3 0x0e\r
+#define R_8237_DMA_CLMSK_CH4_7 0xdc\r
+\r
+#define R_8237_DMA_WRMSK_CH0_3 0x0f\r
+#define R_8237_DMA_WRMSK_CH4_7 0xde\r
+\r
+typedef enum {\r
+ IsaAccessTypeUnknown,\r
+ IsaAccessTypeIo,\r
+ IsaAccessTypeMem,\r
+ IsaAccessTypeMaxType\r
+} ISA_ACCESS_TYPE;\r
+\r
+typedef struct {\r
+ UINT8 Address;\r
+ UINT8 Page;\r
+ UINT8 Count;\r
+} EFI_ISA_DMA_REGISTERS;\r
+\r
+//\r
+// ISA I/O Device Structure\r
+//\r
+#define ISA_IO_DEVICE_SIGNATURE SIGNATURE_32 ('i', 's', 'a', 'i')\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+ EFI_HANDLE Handle;\r
+ EFI_ISA_IO_PROTOCOL IsaIo;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+} ISA_IO_DEVICE;\r
+\r
+#define ISA_IO_DEVICE_FROM_ISA_IO_THIS(a) CR (a, ISA_IO_DEVICE, IsaIo, ISA_IO_DEVICE_SIGNATURE)\r
+\r
+//\r
+// Mapping structure for performing ISA DMA to a buffer above 16 MB\r
+//\r
+typedef struct {\r
+ EFI_ISA_IO_PROTOCOL_OPERATION Operation;\r
+ UINTN NumberOfBytes;\r
+ UINTN NumberOfPages;\r
+ EFI_PHYSICAL_ADDRESS HostAddress;\r
+ EFI_PHYSICAL_ADDRESS MappedHostAddress;\r
+} ISA_MAP_INFO;\r
+\r
+//\r
+// EFI Driver Binding Protocol Interface Functions\r
+//\r
+\r
+/** \r
+ Tests to see if a controller can be managed by the ISA Driver.\r
+\r
+ How the Start() function of a driver is implemented can affect how the Supported() function is implemented.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. \r
+ @param[in] Controller The handle of the controller to test.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.\r
+ \r
+ @retval EFI_SUCCESS The device is supported by this driver.\r
+ @retval EFI_ALREADY_STARTED The device is already being managed by this driver.\r
+ @retval EFI_ACCESS_DENIED The device is already being managed by a different driver \r
+ or an application that requires exclusive access.\r
+ @retval EFI_UNSUPPORTED The device is is not supported by this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoDriverSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ );\r
+\r
+/**\r
+ Start this driver on ControllerHandle. \r
+ \r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController(). \r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, but the following calling \r
+ restrictions must be followed or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. \r
+ This parameter is ignored by device drivers, and is optional for bus drivers.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.\r
+ Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoDriverStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ );\r
+\r
+/**\r
+ Stop this driver on ControllerHandle. \r
+ \r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoDriverStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE * ChildHandleBuffer OPTIONAL\r
+ );\r
+\r
+//\r
+// Function Prototypes\r
+//\r
+\r
+/**\r
+ Initializes an ISA I/O Instance\r
+\r
+ @param[in] IsaIoDevice The isa device to be initialized.\r
+ @param[in] DevicePath The device path of the isa device.\r
+ @param[in] Resources The ACPI resource list.\r
+ \r
+**/\r
+VOID\r
+InitializeIsaIoInstance (\r
+ IN ISA_IO_DEVICE *IsaIoDevice,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN ACPI_RESOURCE_HEADER_PTR Resources\r
+ );\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ The implementation for EFI_ISA_IO_PROTOCOL. \r
+ \r
+Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "IsaIo.h"\r
+\r
+//\r
+// Module Variables\r
+//\r
+EFI_ISA_IO_PROTOCOL mIsaIoInterface = {\r
+ { \r
+ IsaIoMemRead,\r
+ IsaIoMemWrite\r
+ },\r
+ { \r
+ IsaIoIoRead,\r
+ IsaIoIoWrite\r
+ },\r
+ IsaIoCopyMem,\r
+ IsaIoMap,\r
+ IsaIoUnmap,\r
+ IsaIoAllocateBuffer,\r
+ IsaIoFreeBuffer,\r
+ IsaIoFlush,\r
+ NULL,\r
+ 0,\r
+ NULL\r
+};\r
+\r
+EFI_ISA_DMA_REGISTERS mDmaRegisters[8] = {\r
+ {\r
+ 0x00,\r
+ 0x87,\r
+ 0x01\r
+ },\r
+ {\r
+ 0x02,\r
+ 0x83,\r
+ 0x03\r
+ },\r
+ {\r
+ 0x04,\r
+ 0x81,\r
+ 0x05\r
+ },\r
+ {\r
+ 0x06,\r
+ 0x82,\r
+ 0x07\r
+ },\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }, // Channel 4 is invalid\r
+ {\r
+ 0xC4,\r
+ 0x8B,\r
+ 0xC6\r
+ },\r
+ {\r
+ 0xC8,\r
+ 0x89,\r
+ 0xCA\r
+ },\r
+ {\r
+ 0xCC,\r
+ 0x8A,\r
+ 0xCE\r
+ },\r
+};\r
+\r
+/**\r
+ Verifies access to an ISA device\r
+\r
+ @param[in] IsaIoDevice The ISA device to be verified.\r
+ @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo.\r
+ @param[in] Width The width of the memory operation.\r
+ @param[in] Count The number of memory operations to perform. \r
+ @param[in] Offset The offset in ISA memory space to start the memory operation. \r
+ \r
+ @retval EFI_SUCCESS Verify success.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_UNSUPPORTED The device ont support the access type.\r
+**/\r
+EFI_STATUS\r
+IsaIoVerifyAccess (\r
+ IN ISA_IO_DEVICE *IsaIoDevice,\r
+ IN ISA_ACCESS_TYPE Type,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN UINT32 Offset\r
+ )\r
+{\r
+ EFI_ISA_ACPI_RESOURCE *Item;\r
+ EFI_STATUS Status;\r
+\r
+ if (Width < EfiIsaIoWidthUint8 ||\r
+ Width >= EfiIsaIoWidthMaximum ||\r
+ Width == EfiIsaIoWidthReserved ||\r
+ Width == EfiIsaIoWidthFifoReserved ||\r
+ Width == EfiIsaIoWidthFillReserved\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX\r
+ // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX\r
+ //\r
+ if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) {\r
+ Count = 1;\r
+ }\r
+\r
+ Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem;\r
+ while (Item->Type != EfiIsaAcpiResourceEndOfList) {\r
+ if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) ||\r
+ (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) {\r
+ if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Offset >= Item->StartRange && Offset <= Item->EndRange) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ Item++;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Convert the IO Information in ACPI descriptor to IO ISA Attribute.\r
+\r
+ @param[in] Information The IO Information in ACPI descriptor\r
+\r
+ @return UINT32 The IO ISA Attribute\r
+**/\r
+UINT32\r
+IsaIoAttribute (\r
+ IN UINT8 Information\r
+ )\r
+{\r
+ UINT32 Attribute;\r
+\r
+ Attribute = 0;\r
+\r
+ switch (Information & EFI_ACPI_IO_DECODE_MASK) {\r
+ case EFI_ACPI_IO_DECODE_16_BIT:\r
+ Attribute |= EFI_ISA_ACPI_IO_DECODE_16_BITS;\r
+ break;\r
+ \r
+ case EFI_ACPI_IO_DECODE_10_BIT:\r
+ Attribute |= EFI_ISA_ACPI_IO_DECODE_10_BITS;\r
+ break;\r
+ }\r
+\r
+ return Attribute;\r
+}\r
+\r
+/**\r
+ Convert the IRQ Information in ACPI descriptor to IRQ ISA Attribute.\r
+\r
+ @param[in] Information The IRQ Information in ACPI descriptor\r
+\r
+ @return UINT32 The IRQ ISA Attribute\r
+**/\r
+UINT32\r
+IsaIrqAttribute (\r
+ IN UINT8 Information\r
+ )\r
+{\r
+ UINT32 Attribute;\r
+\r
+ Attribute = 0;\r
+\r
+ if ((Information & EFI_ACPI_IRQ_POLARITY_MASK) == EFI_ACPI_IRQ_HIGH_TRUE) {\r
+ if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) {\r
+ Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE;\r
+ } else {\r
+ Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE;\r
+ }\r
+ } else {\r
+ if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) {\r
+ Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE;\r
+ } else {\r
+ Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE;\r
+ }\r
+ }\r
+ return Attribute;\r
+}\r
+\r
+/**\r
+ Convert the Memory Information in ACPI descriptor to Memory ISA Attribute.\r
+\r
+ @param[in] Information The Memory Information in ACPI descriptor\r
+\r
+ @return UINT32 The Memory ISA Attribute\r
+**/\r
+UINT32\r
+IsaMemoryAttribute (\r
+ IN UINT8 Information\r
+ )\r
+{\r
+ UINT32 Attribute;\r
+\r
+ Attribute = 0;\r
+\r
+ switch (Information & EFI_ACPI_MEMORY_WRITE_STATUS_MASK) {\r
+ case EFI_ACPI_MEMORY_WRITABLE:\r
+ Attribute |= EFI_ISA_ACPI_MEMORY_WRITEABLE;\r
+ break;\r
+ }\r
+\r
+ return Attribute;\r
+}\r
+\r
+/**\r
+ Convert the DMA Information in ACPI descriptor to DMA ISA Attribute.\r
+\r
+ @param[in] Information The DMA Information in ACPI descriptor\r
+\r
+ @return UINT32 The DMA ISA Attribute\r
+**/\r
+UINT32\r
+IsaDmaAttribute (\r
+ IN UINT8 Information\r
+ )\r
+{\r
+ UINT32 Attribute;\r
+\r
+ Attribute = EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE;\r
+ \r
+ switch (Information & EFI_ACPI_DMA_SPEED_TYPE_MASK) {\r
+ case EFI_ACPI_DMA_SPEED_TYPE_COMPATIBILITY:\r
+ Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE;\r
+ break;\r
+ case EFI_ACPI_DMA_SPEED_TYPE_A:\r
+ Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A;\r
+ break;\r
+ case EFI_ACPI_DMA_SPEED_TYPE_B:\r
+ Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B;\r
+ break;\r
+ case EFI_ACPI_DMA_SPEED_TYPE_F:\r
+ Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C;\r
+ break;\r
+ }\r
+\r
+ switch (Information & EFI_ACPI_DMA_TRANSFER_TYPE_MASK) {\r
+ case EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT:\r
+ Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8;\r
+ break;\r
+ case EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT:\r
+ Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16;\r
+ break;\r
+ }\r
+\r
+ return Attribute;\r
+}\r
+\r
+/**\r
+ Convert the ACPI resource descriptor to ISA resource descriptor.\r
+\r
+ @param[in] AcpiResource Pointer to the ACPI resource descriptor\r
+ @param[out] IsaResource The optional pointer to the buffer to\r
+ store the converted ISA resource descriptor\r
+\r
+ @return UINTN Number of ISA resource descriptor needed\r
+**/\r
+UINTN\r
+AcpiResourceToIsaResource (\r
+ IN ACPI_RESOURCE_HEADER_PTR AcpiResource,\r
+ OUT EFI_ISA_ACPI_RESOURCE *IsaResource OPTIONAL\r
+ )\r
+{\r
+ UINT32 Index;\r
+ UINTN Count;\r
+ UINT32 LastIndex;\r
+ EFI_ACPI_IO_PORT_DESCRIPTOR *Io;\r
+ EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *FixedIo;\r
+ EFI_ACPI_IRQ_DESCRIPTOR *Irq;\r
+ EFI_ACPI_DMA_DESCRIPTOR *Dma;\r
+ EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR *Memory;\r
+ EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *FixedMemory;\r
+\r
+ Count = 0;\r
+ LastIndex = 0;\r
+\r
+ switch (AcpiResource.SmallHeader->Byte) {\r
+ case ACPI_DMA_DESCRIPTOR:\r
+ Dma = (EFI_ACPI_DMA_DESCRIPTOR *) AcpiResource.SmallHeader;\r
+ for (Index = 0; Index < sizeof (Dma->ChannelMask) * 8; Index++) {\r
+ if (Dma->ChannelMask & (1 << Index)) {\r
+ if ((Count > 0) && (LastIndex + 1 == Index)) {\r
+ if (IsaResource != NULL) {\r
+ IsaResource[Count - 1].EndRange ++;\r
+ }\r
+ } else {\r
+ if (IsaResource != NULL) {\r
+ IsaResource[Count].Type = EfiIsaAcpiResourceDma;\r
+ IsaResource[Count].Attribute = IsaDmaAttribute (Dma->Information);\r
+ IsaResource[Count].StartRange = Index;\r
+ IsaResource[Count].EndRange = Index;\r
+ }\r
+ Count ++;\r
+ }\r
+\r
+ LastIndex = Index;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case ACPI_IO_PORT_DESCRIPTOR:\r
+ Io = (EFI_ACPI_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader;\r
+ if (IsaResource != NULL) {\r
+ IsaResource[Count].Type = EfiIsaAcpiResourceIo;\r
+ IsaResource[Count].Attribute = IsaIoAttribute (Io->Information);\r
+ IsaResource[Count].StartRange = Io->BaseAddressMin;\r
+ IsaResource[Count].EndRange = Io->BaseAddressMin + Io->Length - 1;\r
+ }\r
+ Count ++;\r
+ break;\r
+\r
+ case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR:\r
+ FixedIo = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader;\r
+ if (IsaResource != NULL) {\r
+ IsaResource[Count].Type = EfiIsaAcpiResourceIo;\r
+ IsaResource[Count].Attribute = EFI_ISA_ACPI_IO_DECODE_10_BITS;\r
+ IsaResource[Count].StartRange = FixedIo->BaseAddress;\r
+ IsaResource[Count].EndRange = FixedIo->BaseAddress + FixedIo->Length - 1;\r
+ }\r
+ Count ++;\r
+ break;\r
+\r
+ case ACPI_IRQ_DESCRIPTOR:\r
+ case ACPI_IRQ_NOFLAG_DESCRIPTOR:\r
+ Irq = (EFI_ACPI_IRQ_DESCRIPTOR *) AcpiResource.SmallHeader;\r
+ for (Index = 0; Index < sizeof (Irq->Mask) * 8; Index++) {\r
+ if (Irq->Mask & (1 << Index)) {\r
+ if ((Count > 0) && (LastIndex + 1 == Index)) {\r
+ if (IsaResource != NULL) {\r
+ IsaResource[Count - 1].EndRange ++;\r
+ }\r
+ } else {\r
+ if (IsaResource != NULL) {\r
+ IsaResource[Count].Type = EfiIsaAcpiResourceInterrupt;\r
+ if (AcpiResource.SmallHeader->Byte == ACPI_IRQ_DESCRIPTOR) {\r
+ IsaResource[Count].Attribute = IsaIrqAttribute (Irq->Information);\r
+ } else {\r
+ IsaResource[Count].Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE;\r
+ }\r
+ IsaResource[Count].StartRange = Index;\r
+ IsaResource[Count].EndRange = Index;\r
+ }\r
+ Count++;\r
+ }\r
+\r
+ LastIndex = Index;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR:\r
+ Memory = (EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader;\r
+ if (IsaResource != NULL) {\r
+ IsaResource[Count].Type = EfiIsaAcpiResourceMemory;\r
+ IsaResource[Count].Attribute = IsaMemoryAttribute (Memory->Information);\r
+ IsaResource[Count].StartRange = Memory->BaseAddressMin;\r
+ IsaResource[Count].EndRange = Memory->BaseAddressMin + Memory->Length - 1;\r
+ }\r
+ Count ++;\r
+ break;\r
+\r
+ case ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR:\r
+ FixedMemory = (EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader;\r
+ if (IsaResource != NULL) {\r
+ IsaResource[Count].Type = EfiIsaAcpiResourceMemory;\r
+ IsaResource[Count].Attribute = IsaMemoryAttribute (FixedMemory->Information);\r
+ IsaResource[Count].StartRange = FixedMemory->BaseAddress;\r
+ IsaResource[Count].EndRange = FixedMemory->BaseAddress + FixedMemory->Length - 1;\r
+ }\r
+ Count ++;\r
+ break;\r
+\r
+ case ACPI_END_TAG_DESCRIPTOR:\r
+ if (IsaResource != NULL) {\r
+ IsaResource[Count].Type = EfiIsaAcpiResourceEndOfList;\r
+ IsaResource[Count].Attribute = 0;\r
+ IsaResource[Count].StartRange = 0;\r
+ IsaResource[Count].EndRange = 0;\r
+ }\r
+ Count ++;\r
+ break;\r
+ }\r
+\r
+ return Count;\r
+}\r
+\r
+/**\r
+ Initializes an ISA I/O Instance\r
+\r
+ @param[in] IsaIoDevice The isa device to be initialized.\r
+ @param[in] DevicePath The device path of the isa device.\r
+ @param[in] Resources The ACPI resource list.\r
+ \r
+**/\r
+VOID\r
+InitializeIsaIoInstance (\r
+ IN ISA_IO_DEVICE *IsaIoDevice,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN ACPI_RESOURCE_HEADER_PTR Resources\r
+ )\r
+{\r
+ UINTN Index;\r
+ ACPI_HID_DEVICE_PATH *AcpiNode;\r
+ ACPI_RESOURCE_HEADER_PTR ResourcePtr;\r
+\r
+ //\r
+ // Use the ISA IO Protocol structure template to initialize the ISA IO instance\r
+ //\r
+ CopyMem (\r
+ &IsaIoDevice->IsaIo,\r
+ &mIsaIoInterface,\r
+ sizeof (EFI_ISA_IO_PROTOCOL)\r
+ );\r
+\r
+ //\r
+ // Count the resources including the ACPI End Tag\r
+ //\r
+ ResourcePtr = Resources;\r
+ Index = 0;\r
+ while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {\r
+ \r
+ Index += AcpiResourceToIsaResource (ResourcePtr, NULL);\r
+\r
+ if (ResourcePtr.SmallHeader->Bits.Type == 0) {\r
+ ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader\r
+ + ResourcePtr.SmallHeader->Bits.Length\r
+ + sizeof (*ResourcePtr.SmallHeader));\r
+ } else {\r
+ ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader\r
+ + ResourcePtr.LargeHeader->Length\r
+ + sizeof (*ResourcePtr.LargeHeader));\r
+ }\r
+\r
+ }\r
+ //\r
+ // Get the Isa Resource count for ACPI End Tag\r
+ //\r
+ Index += AcpiResourceToIsaResource (ResourcePtr, NULL);\r
+\r
+ //\r
+ // Initialize the ResourceList\r
+ //\r
+ IsaIoDevice->IsaIo.ResourceList = AllocatePool (sizeof (EFI_ISA_ACPI_RESOURCE_LIST) + Index * sizeof (EFI_ISA_ACPI_RESOURCE));\r
+ ASSERT (IsaIoDevice->IsaIo.ResourceList != NULL);\r
+ IsaIoDevice->IsaIo.ResourceList->ResourceItem = (EFI_ISA_ACPI_RESOURCE *) (IsaIoDevice->IsaIo.ResourceList + 1);\r
+\r
+ AcpiNode = (ACPI_HID_DEVICE_PATH *) ((UINT8 *) DevicePath + GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH - sizeof (ACPI_HID_DEVICE_PATH));\r
+ IsaIoDevice->IsaIo.ResourceList->Device.HID = AcpiNode->HID;\r
+ IsaIoDevice->IsaIo.ResourceList->Device.UID = AcpiNode->UID;\r
+\r
+ ResourcePtr = Resources;\r
+ Index = 0;\r
+ while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {\r
+\r
+ Index += AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]);\r
+\r
+ if (ResourcePtr.SmallHeader->Bits.Type == 0) {\r
+ ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader\r
+ + ResourcePtr.SmallHeader->Bits.Length\r
+ + sizeof (*ResourcePtr.SmallHeader));\r
+ } else {\r
+ ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader\r
+ + ResourcePtr.LargeHeader->Length\r
+ + sizeof (*ResourcePtr.LargeHeader));\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Convert the ACPI End Tag\r
+ //\r
+ AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]);\r
+}\r
+\r
+/**\r
+ Performs an ISA I/O Read Cycle\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Width Specifies the width of the I/O operation.\r
+ @param[in] Offset The offset in ISA I/O space to start the I/O operation. \r
+ @param[in] Count The number of I/O operations to perform. \r
+ @param[out] Buffer The destination buffer to store the results\r
+\r
+ @retval EFI_SUCCESS The data was read from the device sucessfully.\r
+ @retval EFI_UNSUPPORTED The Offset is not valid for this device.\r
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoIoRead (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ISA_IO_DEVICE *IsaIoDevice;\r
+\r
+ IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);\r
+\r
+ //\r
+ // Verify Isa IO Access\r
+ //\r
+ Status = IsaIoVerifyAccess (\r
+ IsaIoDevice,\r
+ IsaAccessTypeIo,\r
+ Width,\r
+ Count,\r
+ Offset\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = IsaIoDevice->PciIo->Io.Read (\r
+ IsaIoDevice->PciIo,\r
+ (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Performs an ISA I/O Write Cycle\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Width Specifies the width of the I/O operation.\r
+ @param[in] Offset The offset in ISA I/O space to start the I/O operation. \r
+ @param[in] Count The number of I/O operations to perform. \r
+ @param[in] Buffer The source buffer to write data from\r
+\r
+ @retval EFI_SUCCESS The data was writen to the device sucessfully.\r
+ @retval EFI_UNSUPPORTED The Offset is not valid for this device.\r
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoIoWrite (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ISA_IO_DEVICE *IsaIoDevice;\r
+\r
+ IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);\r
+\r
+ //\r
+ // Verify Isa IO Access\r
+ //\r
+ Status = IsaIoVerifyAccess (\r
+ IsaIoDevice,\r
+ IsaAccessTypeIo,\r
+ Width,\r
+ Count,\r
+ Offset\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = IsaIoDevice->PciIo->Io.Write (\r
+ IsaIoDevice->PciIo,\r
+ (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Writes an 8-bit I/O Port\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Offset The offset in ISA IO space to start the IO operation. \r
+ @param[in] Value The data to write port.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset is not valid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+WritePort (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN UINT32 Offset,\r
+ IN UINT8 Value\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ISA_IO_DEVICE *IsaIoDevice;\r
+\r
+ IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);\r
+\r
+ Status = IsaIoDevice->PciIo->Io.Write (\r
+ IsaIoDevice->PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ Offset,\r
+ 1,\r
+ &Value\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Wait for 50 microseconds to take affect.\r
+ //\r
+ gBS->Stall (50);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Writes I/O operation base address and count number to a 8 bit I/O Port.\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] AddrOffset The address' offset.\r
+ @param[in] PageOffset The page's offest.\r
+ @param[in] CountOffset The count's offset.\r
+ @param[in] BaseAddress The base address.\r
+ @param[in] Count The number of I/O operations to perform. \r
+ \r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.\r
+ @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+WriteDmaPort (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN UINT32 AddrOffset,\r
+ IN UINT32 PageOffset,\r
+ IN UINT32 CountOffset,\r
+ IN UINT32 BaseAddress,\r
+ IN UINT16 Count\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff));\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff));\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff));\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff));\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff));\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Unmaps a memory region for DMA\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map().\r
+\r
+ @retval EFI_SUCCESS The range was unmapped.\r
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoUnmap (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ )\r
+{\r
+ ISA_MAP_INFO *IsaMapInfo;\r
+\r
+ //\r
+ // Check if DMA is supported.\r
+ //\r
+ if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // See if the Map() operation associated with this Unmap() required a mapping\r
+ // buffer.If a mapping buffer was not required, then this function simply\r
+ // returns EFI_SUCCESS.\r
+ //\r
+ if (Mapping != NULL) {\r
+ //\r
+ // Get the MAP_INFO structure from Mapping\r
+ //\r
+ IsaMapInfo = (ISA_MAP_INFO *) Mapping;\r
+\r
+ //\r
+ // If this is a write operation from the Agent's point of view,\r
+ // then copy the contents of the mapped buffer into the real buffer\r
+ // so the processor can read the contents of the real buffer.\r
+ //\r
+ if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) {\r
+ CopyMem (\r
+ (VOID *) (UINTN) IsaMapInfo->HostAddress,\r
+ (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,\r
+ IsaMapInfo->NumberOfBytes\r
+ );\r
+ }\r
+ //\r
+ // Free the mapped buffer and the MAP_INFO structure.\r
+ //\r
+ gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages);\r
+ FreePool (IsaMapInfo);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Flushes any posted write data to the system memory.\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS The buffers were flushed.\r
+ @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoFlush (\r
+ IN EFI_ISA_IO_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ISA_IO_DEVICE *IsaIoDevice;\r
+\r
+ IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);\r
+\r
+ Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Performs an ISA Memory Read Cycle\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Width Specifies the width of the memory operation.\r
+ @param[in] Offset The offset in ISA memory space to start the memory operation. \r
+ @param[in] Count The number of memory operations to perform. \r
+ @param[out] Buffer The destination buffer to store the results\r
+ \r
+ @retval EFI_SUCCESS The data was read from the device successfully.\r
+ @retval EFI_UNSUPPORTED The Offset is not valid for this device.\r
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoMemRead (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ISA_IO_DEVICE *IsaIoDevice;\r
+\r
+ //\r
+ // Check if ISA memory is supported.\r
+ //\r
+ if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);\r
+\r
+ //\r
+ // Verify the Isa Io Access\r
+ //\r
+ Status = IsaIoVerifyAccess (\r
+ IsaIoDevice,\r
+ IsaAccessTypeMem,\r
+ Width,\r
+ Count,\r
+ Offset\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = IsaIoDevice->PciIo->Mem.Read (\r
+ IsaIoDevice->PciIo,\r
+ (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Performs an ISA Memory Write Cycle\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. \r
+ @param[in] Width Specifies the width of the memory operation.\r
+ @param[in] Offset The offset in ISA memory space to start the memory operation. \r
+ @param[in] Count The number of memory operations to perform. \r
+ @param[in] Buffer The source buffer to write data from\r
+\r
+ @retval EFI_SUCCESS The data was written to the device sucessfully.\r
+ @retval EFI_UNSUPPORTED The Offset is not valid for this device.\r
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoMemWrite (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ISA_IO_DEVICE *IsaIoDevice;\r
+\r
+ //\r
+ // Check if ISA memory is supported.\r
+ //\r
+ if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);\r
+\r
+ //\r
+ // Verify Isa IO Access\r
+ //\r
+ Status = IsaIoVerifyAccess (\r
+ IsaIoDevice,\r
+ IsaAccessTypeMem,\r
+ Width,\r
+ Count,\r
+ Offset\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = IsaIoDevice->PciIo->Mem.Write (\r
+ IsaIoDevice->PciIo,\r
+ (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Copy one region of ISA memory space to another region of ISA memory space on the ISA controller.\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Width Specifies the width of the memory copy operation.\r
+ @param[in] DestOffset The offset of the destination \r
+ @param[in] SrcOffset The offset of the source\r
+ @param[in] Count The number of memory copy operations to perform\r
+\r
+ @retval EFI_SUCCESS The data was copied sucessfully.\r
+ @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device.\r
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoCopyMem (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 DestOffset,\r
+ IN UINT32 SrcOffset,\r
+ IN UINTN Count\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ISA_IO_DEVICE *IsaIoDevice;\r
+\r
+ //\r
+ // Check if ISA memory is supported.\r
+ //\r
+ if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);\r
+\r
+ //\r
+ // Verify Isa IO Access for destination and source\r
+ //\r
+ Status = IsaIoVerifyAccess (\r
+ IsaIoDevice,\r
+ IsaAccessTypeMem,\r
+ Width,\r
+ Count,\r
+ DestOffset\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = IsaIoVerifyAccess (\r
+ IsaIoDevice,\r
+ IsaAccessTypeMem,\r
+ Width,\r
+ Count,\r
+ SrcOffset\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = IsaIoDevice->PciIo->CopyMem (\r
+ IsaIoDevice->PciIo,\r
+ (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ DestOffset,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ SrcOffset,\r
+ Count\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Maps a memory region for DMA, note this implementation\r
+ only supports slave read/write operation to save code size.\r
+\r
+ @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param Operation Indicates the type of DMA (slave or bus master), and if \r
+ the DMA operation is going to read or write to system memory. \r
+ @param ChannelNumber The slave channel number to use for this DMA operation. \r
+ If Operation and ChannelAttributes shows that this device \r
+ performs bus mastering DMA, then this field is ignored. \r
+ The legal range for this field is 0..7. \r
+ @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation\r
+ @param HostAddress The system memory address to map to the device. \r
+ @param NumberOfBytes On input the number of bytes to map. On output the number \r
+ of bytes that were mapped.\r
+ @param DeviceAddress The resulting map address for the bus master device to use \r
+ to access the hosts HostAddress. \r
+ @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().\r
+\r
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.\r
+ @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.\r
+ @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.\r
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.\r
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
+**/\r
+EFI_STATUS\r
+IsaIoMapOnlySupportSlaveReadWrite (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,\r
+ IN UINT8 ChannelNumber OPTIONAL,\r
+ IN UINT32 ChannelAttributes,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+ ISA_MAP_INFO *IsaMapInfo;\r
+ UINT8 DmaMode;\r
+ UINTN MaxNumberOfBytes;\r
+ UINT32 BaseAddress;\r
+ UINT16 Count;\r
+ UINT8 DmaMask;\r
+ UINT8 DmaClear;\r
+ UINT8 DmaChannelMode;\r
+ \r
+ if ((NULL == This) ||\r
+ (NULL == HostAddress) ||\r
+ (NULL == NumberOfBytes) ||\r
+ (NULL == DeviceAddress) ||\r
+ (NULL == Mapping)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Initialize the return values to their defaults\r
+ //\r
+ *Mapping = NULL;\r
+\r
+ //\r
+ // Make sure the Operation parameter is valid.\r
+ // Light IsaIo only supports two operations.\r
+ //\r
+ if (!(Operation == EfiIsaIoOperationSlaveRead || \r
+ Operation == EfiIsaIoOperationSlaveWrite)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (ChannelNumber >= 4) {\r
+ //\r
+ // The Light IsaIo doesn't support channelNumber larger than 4.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Map the HostAddress to a DeviceAddress.\r
+ //\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
+ if ((PhysicalAddress + *NumberOfBytes) > BASE_16MB) {\r
+ //\r
+ // Common Buffer operations can not be remapped. If the common buffer\r
+ // is above 16MB, then it is not possible to generate a mapping, so return\r
+ // an error.\r
+ //\r
+ if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()\r
+ // is called later.\r
+ //\r
+ IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));\r
+ if (IsaMapInfo == NULL) {\r
+ *NumberOfBytes = 0;\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Return a pointer to the MAP_INFO structure in Mapping\r
+ //\r
+ *Mapping = IsaMapInfo;\r
+\r
+ //\r
+ // Initialize the MAP_INFO structure\r
+ //\r
+ IsaMapInfo->Operation = Operation;\r
+ IsaMapInfo->NumberOfBytes = *NumberOfBytes;\r
+ IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);\r
+ IsaMapInfo->HostAddress = PhysicalAddress;\r
+ IsaMapInfo->MappedHostAddress = BASE_16MB - 1;\r
+\r
+ //\r
+ // Allocate a buffer below 16MB to map the transfer to.\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiBootServicesData,\r
+ IsaMapInfo->NumberOfPages,\r
+ &IsaMapInfo->MappedHostAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (IsaMapInfo);\r
+ *NumberOfBytes = 0;\r
+ *Mapping = NULL;\r
+ return Status;\r
+ }\r
+ //\r
+ // If this is a read operation from the DMA agents's point of view,\r
+ // then copy the contents of the real buffer into the mapped buffer\r
+ // so the DMA agent can read the contents of the real buffer.\r
+ //\r
+ if (Operation == EfiIsaIoOperationSlaveRead) {\r
+ CopyMem (\r
+ (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,\r
+ (VOID *) (UINTN) IsaMapInfo->HostAddress,\r
+ IsaMapInfo->NumberOfBytes\r
+ );\r
+ }\r
+ //\r
+ // The DeviceAddress is the address of the maped buffer below 16 MB\r
+ //\r
+ *DeviceAddress = IsaMapInfo->MappedHostAddress;\r
+ } else {\r
+ //\r
+ // The transfer is below 16 MB, so the DeviceAddress is simply the\r
+ // HostAddress\r
+ //\r
+ *DeviceAddress = PhysicalAddress;\r
+ }\r
+ \r
+ //\r
+ // Figure out what to program into the DMA Channel Mode Register\r
+ //\r
+ DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));\r
+ if (Operation == EfiIsaIoOperationSlaveRead) {\r
+ DmaMode |= V_8237_DMA_CHMODE_MEM2IO;\r
+ } else {\r
+ DmaMode |= V_8237_DMA_CHMODE_IO2MEM;\r
+ }\r
+ //\r
+ // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo\r
+ //\r
+ DmaMode |= V_8237_DMA_CHMODE_SINGLE;\r
+\r
+ //\r
+ // A Slave DMA transfer can not cross a 64K boundary.\r
+ // Compute *NumberOfBytes based on this restriction.\r
+ //\r
+ MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);\r
+ if (*NumberOfBytes > MaxNumberOfBytes) {\r
+ *NumberOfBytes = MaxNumberOfBytes;\r
+ }\r
+ //\r
+ // Compute the values to program into the BaseAddress and Count registers\r
+ // of the Slave DMA controller\r
+ //\r
+ BaseAddress = (UINT32) (*DeviceAddress);\r
+ Count = (UINT16) (*NumberOfBytes - 1);\r
+ //\r
+ // Program the DMA Write Single Mask Register for ChannelNumber\r
+ // Clear the DMA Byte Pointer Register\r
+ //\r
+ DmaMask = R_8237_DMA_WRSMSK_CH0_3;\r
+ DmaClear = R_8237_DMA_CBPR_CH0_3;\r
+ DmaChannelMode = R_8237_DMA_CHMODE_CH0_3;\r
+\r
+ Status = WritePort (\r
+ This,\r
+ DmaMask,\r
+ (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WritePort (\r
+ This,\r
+ DmaClear,\r
+ (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WritePort (This, DmaChannelMode, DmaMode);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WriteDmaPort (\r
+ This,\r
+ mDmaRegisters[ChannelNumber].Address,\r
+ mDmaRegisters[ChannelNumber].Page,\r
+ mDmaRegisters[ChannelNumber].Count,\r
+ BaseAddress,\r
+ Count\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WritePort (\r
+ This,\r
+ DmaMask,\r
+ (UINT8) (ChannelNumber & 0x03)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Maps a memory region for DMA. This implementation implement the \r
+ the full mapping support.\r
+\r
+ @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param Operation Indicates the type of DMA (slave or bus master), and if \r
+ the DMA operation is going to read or write to system memory. \r
+ @param ChannelNumber The slave channel number to use for this DMA operation. \r
+ If Operation and ChannelAttributes shows that this device \r
+ performs bus mastering DMA, then this field is ignored. \r
+ The legal range for this field is 0..7. \r
+ @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation\r
+ @param HostAddress The system memory address to map to the device. \r
+ @param NumberOfBytes On input the number of bytes to map. On output the number \r
+ of bytes that were mapped.\r
+ @param DeviceAddress The resulting map address for the bus master device to use \r
+ to access the hosts HostAddress. \r
+ @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().\r
+\r
+ @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.\r
+ @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.\r
+ @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.\r
+ @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.\r
+ @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.\r
+**/\r
+EFI_STATUS\r
+IsaIoMapFullSupport (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,\r
+ IN UINT8 ChannelNumber OPTIONAL,\r
+ IN UINT32 ChannelAttributes,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN Master;\r
+ BOOLEAN Read;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+ ISA_MAP_INFO *IsaMapInfo;\r
+ UINT8 DmaMode;\r
+ UINTN MaxNumberOfBytes;\r
+ UINT32 BaseAddress;\r
+ UINT16 Count;\r
+ UINT8 DmaMask;\r
+ UINT8 DmaClear;\r
+ UINT8 DmaChannelMode;\r
+\r
+ if ((NULL == This) ||\r
+ (NULL == HostAddress) ||\r
+ (NULL == NumberOfBytes) ||\r
+ (NULL == DeviceAddress) ||\r
+ (NULL == Mapping)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Initialize the return values to their defaults\r
+ //\r
+ *Mapping = NULL;\r
+\r
+ //\r
+ // Make sure the Operation parameter is valid\r
+ //\r
+ if (Operation < 0 || Operation >= EfiIsaIoOperationMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (ChannelNumber >= 8) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // See if this is a Slave DMA Operation\r
+ //\r
+ Master = TRUE;\r
+ Read = FALSE;\r
+ if (Operation == EfiIsaIoOperationSlaveRead) {\r
+ Operation = EfiIsaIoOperationBusMasterRead;\r
+ Master = FALSE;\r
+ Read = TRUE;\r
+ }\r
+\r
+ if (Operation == EfiIsaIoOperationSlaveWrite) {\r
+ Operation = EfiIsaIoOperationBusMasterWrite;\r
+ Master = FALSE;\r
+ Read = FALSE;\r
+ }\r
+\r
+ if (!Master) {\r
+ //\r
+ // Make sure that ChannelNumber is a valid channel number\r
+ // Channel 4 is used to cascade, so it is illegal.\r
+ //\r
+ if (ChannelNumber == 4 || ChannelNumber > 7) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // This implementation only support COMPATIBLE DMA Transfers\r
+ //\r
+ if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE) == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((ChannelAttributes &\r
+ (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A |\r
+ EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B |\r
+ EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C)) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (ChannelNumber < 4) {\r
+ //\r
+ // If this is Channel 0..3, then the width must be 8 bit\r
+ //\r
+ if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) == 0) ||\r
+ ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) != 0)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
+ //\r
+ // If this is Channel 4..7, then the width must be 16 bit\r
+ //\r
+ if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) != 0) ||\r
+ ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) == 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ //\r
+ // Either Demand Mode or Single Mode must be selected, but not both\r
+ //\r
+ if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) {\r
+ if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
+ if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Map the HostAddress to a DeviceAddress.\r
+ //\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
+ if ((PhysicalAddress +*NumberOfBytes) > BASE_16MB) {\r
+ //\r
+ // Common Buffer operations can not be remapped. If the common buffer\r
+ // is above 16MB, then it is not possible to generate a mapping, so return\r
+ // an error.\r
+ //\r
+ if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()\r
+ // is called later.\r
+ //\r
+ IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));\r
+ if (IsaMapInfo == NULL) {\r
+ *NumberOfBytes = 0;\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Return a pointer to the MAP_INFO structure in Mapping\r
+ //\r
+ *Mapping = IsaMapInfo;\r
+\r
+ //\r
+ // Initialize the MAP_INFO structure\r
+ //\r
+ IsaMapInfo->Operation = Operation;\r
+ IsaMapInfo->NumberOfBytes = *NumberOfBytes;\r
+ IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);\r
+ IsaMapInfo->HostAddress = PhysicalAddress;\r
+ IsaMapInfo->MappedHostAddress = BASE_16MB - 1;\r
+\r
+ //\r
+ // Allocate a buffer below 16MB to map the transfer to.\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiBootServicesData,\r
+ IsaMapInfo->NumberOfPages,\r
+ &IsaMapInfo->MappedHostAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (IsaMapInfo);\r
+ *NumberOfBytes = 0;\r
+ *Mapping = NULL;\r
+ return Status;\r
+ }\r
+ //\r
+ // If this is a read operation from the DMA agents's point of view,\r
+ // then copy the contents of the real buffer into the mapped buffer\r
+ // so the DMA agent can read the contents of the real buffer.\r
+ //\r
+ if (Operation == EfiIsaIoOperationBusMasterRead) {\r
+ CopyMem (\r
+ (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,\r
+ (VOID *) (UINTN) IsaMapInfo->HostAddress,\r
+ IsaMapInfo->NumberOfBytes\r
+ );\r
+ }\r
+ //\r
+ // The DeviceAddress is the address of the maped buffer below 16 MB\r
+ //\r
+ *DeviceAddress = IsaMapInfo->MappedHostAddress;\r
+ } else {\r
+ //\r
+ // The transfer is below 16 MB, so the DeviceAddress is simply the\r
+ // HostAddress\r
+ //\r
+ *DeviceAddress = PhysicalAddress;\r
+ }\r
+ //\r
+ // If this is a Bus Master operation then return\r
+ //\r
+ if (Master) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Figure out what to program into the DMA Channel Mode Register\r
+ //\r
+ DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));\r
+ if (Read) {\r
+ DmaMode |= V_8237_DMA_CHMODE_MEM2IO;\r
+ } else {\r
+ DmaMode |= V_8237_DMA_CHMODE_IO2MEM;\r
+ }\r
+\r
+ if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) != 0) {\r
+ DmaMode |= B_8237_DMA_CHMODE_AE;\r
+ }\r
+\r
+ if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) {\r
+ DmaMode |= V_8237_DMA_CHMODE_DEMAND;\r
+ }\r
+\r
+ if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) {\r
+ DmaMode |= V_8237_DMA_CHMODE_SINGLE;\r
+ }\r
+ //\r
+ // A Slave DMA transfer can not cross a 64K boundary.\r
+ // Compute *NumberOfBytes based on this restriction.\r
+ //\r
+ MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);\r
+ if (*NumberOfBytes > MaxNumberOfBytes) {\r
+ *NumberOfBytes = MaxNumberOfBytes;\r
+ }\r
+ //\r
+ // Compute the values to program into the BaseAddress and Count registers\r
+ // of the Slave DMA controller\r
+ //\r
+ if (ChannelNumber < 4) {\r
+ BaseAddress = (UINT32) (*DeviceAddress);\r
+ Count = (UINT16) (*NumberOfBytes - 1);\r
+ } else {\r
+ BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1));\r
+ Count = (UINT16) ((*NumberOfBytes - 1) >> 1);\r
+ }\r
+ //\r
+ // Program the DMA Write Single Mask Register for ChannelNumber\r
+ // Clear the DMA Byte Pointer Register\r
+ //\r
+ if (ChannelNumber < 4) {\r
+ DmaMask = R_8237_DMA_WRSMSK_CH0_3;\r
+ DmaClear = R_8237_DMA_CBPR_CH0_3;\r
+ DmaChannelMode = R_8237_DMA_CHMODE_CH0_3;\r
+ } else {\r
+ DmaMask = R_8237_DMA_WRSMSK_CH4_7;\r
+ DmaClear = R_8237_DMA_CBPR_CH4_7;\r
+ DmaChannelMode = R_8237_DMA_CHMODE_CH4_7;\r
+ }\r
+\r
+ Status = WritePort (\r
+ This,\r
+ DmaMask,\r
+ (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WritePort (\r
+ This,\r
+ DmaClear,\r
+ (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WritePort (This, DmaChannelMode, DmaMode);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WriteDmaPort (\r
+ This,\r
+ mDmaRegisters[ChannelNumber].Address,\r
+ mDmaRegisters[ChannelNumber].Page,\r
+ mDmaRegisters[ChannelNumber].Count,\r
+ BaseAddress,\r
+ Count\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = WritePort (\r
+ This,\r
+ DmaMask,\r
+ (UINT8) (ChannelNumber & 0x03)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Maps a memory region for DMA\r
+\r
+ @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param Operation Indicates the type of DMA (slave or bus master), and if \r
+ the DMA operation is going to read or write to system memory. \r
+ @param ChannelNumber The slave channel number to use for this DMA operation. \r
+ If Operation and ChannelAttributes shows that this device \r
+ performs bus mastering DMA, then this field is ignored. \r
+ The legal range for this field is 0..7. \r
+ @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation\r
+ @param HostAddress The system memory address to map to the device. \r
+ @param NumberOfBytes On input the number of bytes to map. On output the number \r
+ of bytes that were mapped.\r
+ @param DeviceAddress The resulting map address for the bus master device to use \r
+ to access the hosts HostAddress. \r
+ @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().\r
+\r
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.\r
+ @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.\r
+ @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.\r
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.\r
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoMap (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,\r
+ IN UINT8 ChannelNumber OPTIONAL,\r
+ IN UINT32 ChannelAttributes,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ )\r
+{\r
+ //\r
+ // Check if DMA is supported.\r
+ //\r
+ if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for \r
+ // ISA Bus Master.\r
+ //\r
+ // So we just return EFI_UNSUPPORTED for these functions.\r
+ //\r
+ if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) {\r
+ return IsaIoMapOnlySupportSlaveReadWrite (\r
+ This,\r
+ Operation,\r
+ ChannelNumber,\r
+ ChannelAttributes,\r
+ HostAddress,\r
+ NumberOfBytes,\r
+ DeviceAddress,\r
+ Mapping\r
+ );\r
+\r
+ } else {\r
+ return IsaIoMapFullSupport (\r
+ This,\r
+ Operation,\r
+ ChannelNumber,\r
+ ChannelAttributes,\r
+ HostAddress,\r
+ NumberOfBytes,\r
+ DeviceAddress,\r
+ Mapping\r
+ );\r
+ }\r
+}\r
+\r
+/**\r
+ Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping.\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Type The type allocation to perform.\r
+ @param[in] MemoryType The type of memory to allocate.\r
+ @param[in] Pages The number of pages to allocate.\r
+ @param[out] HostAddress A pointer to store the base address of the allocated range.\r
+ @param[in] Attributes The requested bit mask of attributes for the allocated range.\r
+\r
+ @retval EFI_SUCCESS The requested memory pages were allocated.\r
+ @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL\r
+ @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified \r
+ by HostAddress, Pages, and Type is not available for common buffer use.\r
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoAllocateBuffer (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+\r
+ //\r
+ // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for \r
+ // ISA Bus Master.\r
+ // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.\r
+ //\r
+ if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) ||\r
+ ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (HostAddress == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Type < AllocateAnyPages || Type >= MaxAllocateType) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData\r
+ //\r
+ if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (BASE_16MB - 1);\r
+ if (Type == AllocateAddress) {\r
+ if ((UINTN) (*HostAddress) >= BASE_16MB) {\r
+ return EFI_UNSUPPORTED;\r
+ } else {\r
+ PhysicalAddress = (UINTN) (*HostAddress);\r
+ }\r
+ }\r
+\r
+ if (Type == AllocateAnyPages) {\r
+ Type = AllocateMaxAddress;\r
+ }\r
+\r
+ Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress);\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ *HostAddress = (VOID *) (UINTN) PhysicalAddress;\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). \r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Pages The number of pages to free.\r
+ @param[in] HostAddress The base address of the allocated range.\r
+\r
+ @retval EFI_SUCCESS The requested memory pages were freed.\r
+ @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer().\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoFreeBuffer (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ IN VOID *HostAddress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for \r
+ // ISA Bus Master.\r
+ // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.\r
+ //\r
+ if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) ||\r
+ ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = gBS->FreePages (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,\r
+ Pages\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ The header file for EFI_ISA_IO protocol implementation.\r
+ \r
+Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _ISA_IO_H_\r
+#define _ISA_IO_H_\r
+\r
+#include "IsaDriver.h"\r
+\r
+//\r
+// Bits definition of PcdIsaBusSupportedFeatures\r
+//\r
+#define PCD_ISA_BUS_SUPPORT_DMA BIT0\r
+#define PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA BIT1\r
+#define PCD_ISA_BUS_SUPPORT_ISA_MEMORY BIT2\r
+\r
+//\r
+// ISA I/O Support Function Prototypes\r
+//\r
+\r
+/**\r
+ Verifies access to an ISA device\r
+\r
+ @param[in] IsaIoDevice The ISA device to be verified.\r
+ @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo.\r
+ @param[in] Width The width of the memory operation.\r
+ @param[in] Count The number of memory operations to perform. \r
+ @param[in] Offset The offset in ISA memory space to start the memory operation. \r
+ \r
+ @retval EFI_SUCCESS Verify success.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_UNSUPPORTED The device ont support the access type.\r
+**/\r
+EFI_STATUS\r
+IsaIoVerifyAccess (\r
+ IN ISA_IO_DEVICE *IsaIoDevice,\r
+ IN ISA_ACCESS_TYPE Type,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN UINT32 Offset\r
+ );\r
+ \r
+/**\r
+ Performs an ISA I/O Read Cycle\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Width Specifies the width of the I/O operation.\r
+ @param[in] Offset The offset in ISA I/O space to start the I/O operation. \r
+ @param[in] Count The number of I/O operations to perform. \r
+ @param[out] Buffer The destination buffer to store the results\r
+\r
+ @retval EFI_SUCCESS The data was read from the device sucessfully.\r
+ @retval EFI_UNSUPPORTED The Offset is not valid for this device.\r
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoIoRead (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Performs an ISA I/O Write Cycle\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Width Specifies the width of the I/O operation.\r
+ @param[in] Offset The offset in ISA I/O space to start the I/O operation. \r
+ @param[in] Count The number of I/O operations to perform. \r
+ @param[in] Buffer The source buffer to write data from\r
+\r
+ @retval EFI_SUCCESS The data was writen to the device sucessfully.\r
+ @retval EFI_UNSUPPORTED The Offset is not valid for this device.\r
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoIoWrite (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Maps a memory region for DMA\r
+\r
+ @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param Operation Indicates the type of DMA (slave or bus master), and if \r
+ the DMA operation is going to read or write to system memory. \r
+ @param ChannelNumber The slave channel number to use for this DMA operation. \r
+ If Operation and ChannelAttributes shows that this device \r
+ performs bus mastering DMA, then this field is ignored. \r
+ The legal range for this field is 0..7. \r
+ @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation\r
+ @param HostAddress The system memory address to map to the device. \r
+ @param NumberOfBytes On input the number of bytes to map. On output the number \r
+ of bytes that were mapped.\r
+ @param DeviceAddress The resulting map address for the bus master device to use \r
+ to access the hosts HostAddress. \r
+ @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().\r
+\r
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.\r
+ @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.\r
+ @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.\r
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.\r
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoMap (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,\r
+ IN UINT8 ChannelNumber OPTIONAL,\r
+ IN UINT32 ChannelAttributes,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ );\r
+\r
+/**\r
+ Unmaps a memory region for DMA\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map().\r
+\r
+ @retval EFI_SUCCESS The range was unmapped.\r
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoUnmap (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ );\r
+\r
+/**\r
+ Flushes any posted write data to the system memory.\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS The buffers were flushed.\r
+ @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoFlush (\r
+ IN EFI_ISA_IO_PROTOCOL *This\r
+ );\r
+\r
+/**\r
+ Writes I/O operation base address and count number to a 8 bit I/O Port.\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] AddrOffset The address' offset.\r
+ @param[in] PageOffset The page's offest.\r
+ @param[in] CountOffset The count's offset.\r
+ @param[in] BaseAddress The base address.\r
+ @param[in] Count The number of I/O operations to perform. \r
+ \r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.\r
+ @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+WriteDmaPort (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN UINT32 AddrOffset,\r
+ IN UINT32 PageOffset,\r
+ IN UINT32 CountOffset,\r
+ IN UINT32 BaseAddress,\r
+ IN UINT16 Count\r
+ );\r
+\r
+/**\r
+ Writes an 8-bit I/O Port\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Offset The offset in ISA IO space to start the IO operation. \r
+ @param[in] Value The data to write port.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset is not valid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+WritePort (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN UINT32 Offset,\r
+ IN UINT8 Value\r
+ ); \r
+\r
+/**\r
+ Performs an ISA Memory Read Cycle\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Width Specifies the width of the memory operation.\r
+ @param[in] Offset The offset in ISA memory space to start the memory operation. \r
+ @param[in] Count The number of memory operations to perform. \r
+ @param[out] Buffer The destination buffer to store the results\r
+ \r
+ @retval EFI_SUCCESS The data was read from the device successfully.\r
+ @retval EFI_UNSUPPORTED The Offset is not valid for this device.\r
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoMemRead (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+\r
+/**\r
+ Performs an ISA Memory Write Cycle\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. \r
+ @param[in] Width Specifies the width of the memory operation.\r
+ @param[in] Offset The offset in ISA memory space to start the memory operation. \r
+ @param[in] Count The number of memory operations to perform. \r
+ @param[in] Buffer The source buffer to write data from\r
+\r
+ @retval EFI_SUCCESS The data was written to the device sucessfully.\r
+ @retval EFI_UNSUPPORTED The Offset is not valid for this device.\r
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoMemWrite (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Copy one region of ISA memory space to another region of ISA memory space on the ISA controller.\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Width Specifies the width of the memory copy operation.\r
+ @param[in] DestOffset The offset of the destination \r
+ @param[in] SrcOffset The offset of the source\r
+ @param[in] Count The number of memory copy operations to perform\r
+\r
+ @retval EFI_SUCCESS The data was copied sucessfully.\r
+ @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device.\r
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoCopyMem (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ISA_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 DestOffset,\r
+ IN UINT32 SrcOffset,\r
+ IN UINTN Count\r
+ );\r
+\r
+/**\r
+ Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping.\r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Type The type allocation to perform.\r
+ @param[in] MemoryType The type of memory to allocate.\r
+ @param[in] Pages The number of pages to allocate.\r
+ @param[out] HostAddress A pointer to store the base address of the allocated range.\r
+ @param[in] Attributes The requested bit mask of attributes for the allocated range.\r
+\r
+ @retval EFI_SUCCESS The requested memory pages were allocated.\r
+ @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL\r
+ @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified \r
+ by HostAddress, Pages, and Type is not available for common buffer use.\r
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoAllocateBuffer (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ IN UINT64 Attributes\r
+ );\r
+\r
+/**\r
+ Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). \r
+\r
+ @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
+ @param[in] Pages The number of pages to free.\r
+ @param[in] HostAddress The base address of the allocated range.\r
+\r
+ @retval EFI_SUCCESS The requested memory pages were freed.\r
+ @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer().\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IsaIoFreeBuffer (\r
+ IN EFI_ISA_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ IN VOID *HostAddress\r
+ );\r
+\r
+#endif\r
+\r