]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c
Check in the IsaIoDxe device driver that consumes EFI_SIO_PROTOCOL to produce EFI_ISA...
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaIoDxe / IsaIo.c
diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c
new file mode 100644 (file)
index 0000000..9058d78
--- /dev/null
@@ -0,0 +1,1796 @@
+/** @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