1558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/** @file
2558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  The implementation for EFI_ISA_IO_PROTOCOL.
3558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
43d78c020d22023d35d27b48817d73ff31a361ac7rsunCopyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
5558be4559ac1fba1a81b483c90d00680a18640ffniruiyuThis program and the accompanying materials
6558be4559ac1fba1a81b483c90d00680a18640ffniruiyuare licensed and made available under the terms and conditions of the BSD License
7558be4559ac1fba1a81b483c90d00680a18640ffniruiyuwhich accompanies this distribution.  The full text of the license may be found at
8558be4559ac1fba1a81b483c90d00680a18640ffniruiyuhttp://opensource.org/licenses/bsd-license.php
9558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
10558be4559ac1fba1a81b483c90d00680a18640ffniruiyuTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11558be4559ac1fba1a81b483c90d00680a18640ffniruiyuWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
13558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
14558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
15558be4559ac1fba1a81b483c90d00680a18640ffniruiyu#include "IsaIo.h"
16558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
17558be4559ac1fba1a81b483c90d00680a18640ffniruiyu//
18558be4559ac1fba1a81b483c90d00680a18640ffniruiyu// Module Variables
19558be4559ac1fba1a81b483c90d00680a18640ffniruiyu//
20558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_ISA_IO_PROTOCOL mIsaIoInterface = {
21558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  {
22558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaIoMemRead,
23558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaIoMemWrite
24558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  },
25558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  {
26558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaIoIoRead,
27558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaIoIoWrite
28558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  },
29558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoCopyMem,
30558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoMap,
31558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoUnmap,
32558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoAllocateBuffer,
33558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoFreeBuffer,
34558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoFlush,
35558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  NULL,
36558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  0,
37558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  NULL
38558be4559ac1fba1a81b483c90d00680a18640ffniruiyu};
39558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
40558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_ISA_DMA_REGISTERS  mDmaRegisters[8] = {
41558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  {
42558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x00,
43558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x87,
44558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x01
45558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  },
46558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  {
47558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x02,
48558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x83,
49558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x03
50558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  },
51558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  {
52558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x04,
53558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x81,
54558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x05
55558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  },
56558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  {
57558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x06,
58558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x82,
59558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x07
60558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  },
61558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  {
62558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x00,
63558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x00,
64558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x00
65558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  },  // Channel 4 is invalid
66558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  {
67558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0xC4,
68558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x8B,
69558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0xC6
70558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  },
71558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  {
72558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0xC8,
73558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x89,
74558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0xCA
75558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  },
76558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  {
77558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0xCC,
78558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0x8A,
79558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    0xCE
80558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  },
81558be4559ac1fba1a81b483c90d00680a18640ffniruiyu};
82558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
83558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
84558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Verifies access to an ISA device
85558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
86558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] IsaIoDevice         The ISA device to be verified.
87558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Type                The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo.
88558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Width               The width of the memory operation.
89558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Count               The number of memory operations to perform.
90558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Offset              The offset in ISA memory space to start the memory operation.
91558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
92558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            Verify success.
93558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value.
94558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED        The device ont support the access type.
95558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
96558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
97558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoVerifyAccess (
98558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN ISA_IO_DEVICE              *IsaIoDevice,
99558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN ISA_ACCESS_TYPE            Type,
100558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL_WIDTH  Width,
101558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINTN                      Count,
102558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT32                     Offset
103558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
104558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
105558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_ISA_ACPI_RESOURCE *Item;
106558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS            Status;
107558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1083d78c020d22023d35d27b48817d73ff31a361ac7rsun  if ((UINT32)Width >= EfiIsaIoWidthMaximum ||
109558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Width == EfiIsaIoWidthReserved ||
110558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Width == EfiIsaIoWidthFifoReserved ||
111558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Width == EfiIsaIoWidthFillReserved
112558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      ) {
113558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_INVALID_PARAMETER;
114558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
115558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
116558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
117558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
118558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
119558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
120558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) {
121558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Count = 1;
122558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
123558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
124558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03);
125558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
126558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status  = EFI_UNSUPPORTED;
127558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Item    = IsaIoDevice->IsaIo.ResourceList->ResourceItem;
128558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  while (Item->Type != EfiIsaAcpiResourceEndOfList) {
129558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) ||
130558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) {
131558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) {
132558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        return EFI_SUCCESS;
133558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
134558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
135558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      if (Offset >= Item->StartRange && Offset <= Item->EndRange) {
136558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        Status = EFI_INVALID_PARAMETER;
137558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
138558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
139558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
140558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Item++;
141558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
142558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
143558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Status;
144558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
145558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
146558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
147558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Convert the IO Information in ACPI descriptor to IO ISA Attribute.
148558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
149558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Information   The IO Information in ACPI descriptor
150558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
151558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @return UINT32           The IO ISA Attribute
152558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
153558be4559ac1fba1a81b483c90d00680a18640ffniruiyuUINT32
154558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoAttribute (
155558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT8                            Information
156558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
157558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
158558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT32             Attribute;
159558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
160558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Attribute = 0;
161558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
162558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  switch (Information & EFI_ACPI_IO_DECODE_MASK) {
163558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case EFI_ACPI_IO_DECODE_16_BIT:
164558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute |= EFI_ISA_ACPI_IO_DECODE_16_BITS;
165558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
166558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
167558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case EFI_ACPI_IO_DECODE_10_BIT:
168558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute |= EFI_ISA_ACPI_IO_DECODE_10_BITS;
169558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
170558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
171558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
172558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Attribute;
173558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
174558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
175558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
176558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Convert the IRQ Information in ACPI descriptor to IRQ ISA Attribute.
177558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
178558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Information   The IRQ Information in ACPI descriptor
179558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
180558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @return UINT32           The IRQ ISA Attribute
181558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
182558be4559ac1fba1a81b483c90d00680a18640ffniruiyuUINT32
183558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIrqAttribute (
184558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT8                            Information
185558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
186558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
187558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT32             Attribute;
188558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
189558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Attribute = 0;
190558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
191558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((Information & EFI_ACPI_IRQ_POLARITY_MASK) == EFI_ACPI_IRQ_HIGH_TRUE) {
192558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) {
193558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE;
194558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    } else {
195558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE;
196558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
197558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  } else {
198558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) {
199558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE;
200558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    } else {
201558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE;
202558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
203558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
204558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Attribute;
205558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
206558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
207558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
208558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Convert the Memory Information in ACPI descriptor to Memory ISA Attribute.
209558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
210558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Information   The Memory Information in ACPI descriptor
211558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
212558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @return UINT32           The Memory ISA Attribute
213558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
214558be4559ac1fba1a81b483c90d00680a18640ffniruiyuUINT32
215558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaMemoryAttribute (
216558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT8                            Information
217558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
218558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
219558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT32             Attribute;
220558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
221558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Attribute = 0;
222558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
223558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  switch (Information & EFI_ACPI_MEMORY_WRITE_STATUS_MASK) {
224558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case EFI_ACPI_MEMORY_WRITABLE:
225558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute |= EFI_ISA_ACPI_MEMORY_WRITEABLE;
226558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
227558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
228558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
229558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Attribute;
230558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
231558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
232558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
233558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Convert the DMA Information in ACPI descriptor to DMA ISA Attribute.
234558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
235558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Information   The DMA Information in ACPI descriptor
236558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
237558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @return UINT32           The DMA ISA Attribute
238558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
239558be4559ac1fba1a81b483c90d00680a18640ffniruiyuUINT32
240558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaDmaAttribute (
241558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT8                            Information
242558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
243558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
244558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT32             Attribute;
245558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
246558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Attribute = EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE;
247558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
248558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  switch (Information & EFI_ACPI_DMA_SPEED_TYPE_MASK) {
249558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case EFI_ACPI_DMA_SPEED_TYPE_COMPATIBILITY:
250558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE;
251558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
252558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case EFI_ACPI_DMA_SPEED_TYPE_A:
253558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A;
254558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
255558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case EFI_ACPI_DMA_SPEED_TYPE_B:
256558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B;
257558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
258558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case EFI_ACPI_DMA_SPEED_TYPE_F:
259558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C;
260558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
261558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
262558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
263558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  switch (Information & EFI_ACPI_DMA_TRANSFER_TYPE_MASK) {
264558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT:
265558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8;
266558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
267558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT:
268558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16;
269558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
270558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
271558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
272558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Attribute;
273558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
274558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
275558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
276558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Convert the ACPI resource descriptor to ISA resource descriptor.
277558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
278558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  AcpiResource          Pointer to the ACPI resource descriptor
279558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[out] IsaResource           The optional pointer to the buffer to
280558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    store the converted ISA resource descriptor
281558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
282558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @return     UINTN                 Number of ISA resource descriptor needed
283558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
284558be4559ac1fba1a81b483c90d00680a18640ffniruiyuUINTN
285558be4559ac1fba1a81b483c90d00680a18640ffniruiyuAcpiResourceToIsaResource (
286558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  ACPI_RESOURCE_HEADER_PTR        AcpiResource,
287558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  OUT EFI_ISA_ACPI_RESOURCE           *IsaResource   OPTIONAL
288558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
289558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
290558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT32                                        Index;
291558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINTN                                         Count;
292558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT32                                        LastIndex;
293558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_ACPI_IO_PORT_DESCRIPTOR                   *Io;
294558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR    *FixedIo;
295558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_ACPI_IRQ_DESCRIPTOR                       *Irq;
296558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_ACPI_DMA_DESCRIPTOR                       *Dma;
297558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR       *Memory;
298558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *FixedMemory;
299558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
300558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Count     = 0;
301558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  LastIndex = 0;
302558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
303558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  switch (AcpiResource.SmallHeader->Byte) {
304558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case ACPI_DMA_DESCRIPTOR:
305558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Dma = (EFI_ACPI_DMA_DESCRIPTOR *) AcpiResource.SmallHeader;
306558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      for (Index = 0; Index < sizeof (Dma->ChannelMask) * 8; Index++) {
307558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        if (Dma->ChannelMask & (1 << Index)) {
308558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          if ((Count > 0) && (LastIndex + 1 == Index)) {
309558be4559ac1fba1a81b483c90d00680a18640ffniruiyu            if (IsaResource != NULL) {
310558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              IsaResource[Count - 1].EndRange ++;
311558be4559ac1fba1a81b483c90d00680a18640ffniruiyu            }
312558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          } else {
313558be4559ac1fba1a81b483c90d00680a18640ffniruiyu            if (IsaResource != NULL) {
314558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              IsaResource[Count].Type       = EfiIsaAcpiResourceDma;
315558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              IsaResource[Count].Attribute  = IsaDmaAttribute (Dma->Information);
316558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              IsaResource[Count].StartRange = Index;
317558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              IsaResource[Count].EndRange   = Index;
318558be4559ac1fba1a81b483c90d00680a18640ffniruiyu            }
319558be4559ac1fba1a81b483c90d00680a18640ffniruiyu            Count ++;
320558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          }
321558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
322558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          LastIndex = Index;
323558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        }
324558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
325558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
326558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
327558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case ACPI_IO_PORT_DESCRIPTOR:
328558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Io = (EFI_ACPI_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader;
3293a0e054598963d0dedcda04612fe759513e8f75cniruiyu      if (Io->Length != 0) {
3303a0e054598963d0dedcda04612fe759513e8f75cniruiyu        if (IsaResource != NULL) {
3313a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].Type       = EfiIsaAcpiResourceIo;
3323a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].Attribute  = IsaIoAttribute (Io->Information);
3333a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].StartRange = Io->BaseAddressMin;
3343a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].EndRange   = Io->BaseAddressMin + Io->Length - 1;
3353a0e054598963d0dedcda04612fe759513e8f75cniruiyu        }
3363a0e054598963d0dedcda04612fe759513e8f75cniruiyu        Count ++;
337558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
338558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
339558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
340558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR:
341558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      FixedIo = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader;
3423a0e054598963d0dedcda04612fe759513e8f75cniruiyu      if (FixedIo->Length != 0) {
3433a0e054598963d0dedcda04612fe759513e8f75cniruiyu        if (IsaResource != NULL) {
3443a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].Type       = EfiIsaAcpiResourceIo;
3453a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].Attribute  = EFI_ISA_ACPI_IO_DECODE_10_BITS;
3463a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].StartRange = FixedIo->BaseAddress;
3473a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].EndRange   = FixedIo->BaseAddress + FixedIo->Length - 1;
3483a0e054598963d0dedcda04612fe759513e8f75cniruiyu        }
3493a0e054598963d0dedcda04612fe759513e8f75cniruiyu        Count ++;
350558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
351558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
352558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
353558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case ACPI_IRQ_DESCRIPTOR:
354558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case ACPI_IRQ_NOFLAG_DESCRIPTOR:
355558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Irq = (EFI_ACPI_IRQ_DESCRIPTOR *) AcpiResource.SmallHeader;
356558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      for (Index = 0; Index < sizeof (Irq->Mask) * 8; Index++) {
357558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        if (Irq->Mask & (1 << Index)) {
358558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          if ((Count > 0) && (LastIndex + 1 == Index)) {
359558be4559ac1fba1a81b483c90d00680a18640ffniruiyu            if (IsaResource != NULL) {
360558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              IsaResource[Count - 1].EndRange ++;
361558be4559ac1fba1a81b483c90d00680a18640ffniruiyu            }
362558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          } else {
363558be4559ac1fba1a81b483c90d00680a18640ffniruiyu            if (IsaResource != NULL) {
364558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              IsaResource[Count].Type       = EfiIsaAcpiResourceInterrupt;
365558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              if (AcpiResource.SmallHeader->Byte == ACPI_IRQ_DESCRIPTOR) {
366558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                IsaResource[Count].Attribute = IsaIrqAttribute (Irq->Information);
367558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              } else {
368558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                IsaResource[Count].Attribute  = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE;
369558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              }
370558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              IsaResource[Count].StartRange = Index;
371558be4559ac1fba1a81b483c90d00680a18640ffniruiyu              IsaResource[Count].EndRange   = Index;
372558be4559ac1fba1a81b483c90d00680a18640ffniruiyu            }
373558be4559ac1fba1a81b483c90d00680a18640ffniruiyu            Count++;
374558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          }
375558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
376558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          LastIndex = Index;
377558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        }
378558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
379558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
380558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
381558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR:
382558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Memory = (EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader;
3833a0e054598963d0dedcda04612fe759513e8f75cniruiyu      if (Memory->Length != 0) {
3843a0e054598963d0dedcda04612fe759513e8f75cniruiyu        if (IsaResource != NULL) {
3853a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].Type       = EfiIsaAcpiResourceMemory;
3863a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].Attribute  = IsaMemoryAttribute (Memory->Information);
3873a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].StartRange = Memory->BaseAddressMin;
3883a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].EndRange   = Memory->BaseAddressMin + Memory->Length - 1;
3893a0e054598963d0dedcda04612fe759513e8f75cniruiyu        }
3903a0e054598963d0dedcda04612fe759513e8f75cniruiyu        Count ++;
391558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
392558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
393558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
394558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR:
395558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      FixedMemory = (EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader;
3963a0e054598963d0dedcda04612fe759513e8f75cniruiyu      if (FixedMemory->Length != 0) {
3973a0e054598963d0dedcda04612fe759513e8f75cniruiyu        if (IsaResource != NULL) {
3983a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].Type       = EfiIsaAcpiResourceMemory;
3993a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].Attribute  = IsaMemoryAttribute (FixedMemory->Information);
4003a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].StartRange = FixedMemory->BaseAddress;
4013a0e054598963d0dedcda04612fe759513e8f75cniruiyu          IsaResource[Count].EndRange   = FixedMemory->BaseAddress + FixedMemory->Length - 1;
4023a0e054598963d0dedcda04612fe759513e8f75cniruiyu        }
4033a0e054598963d0dedcda04612fe759513e8f75cniruiyu        Count ++;
404558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
405558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
406558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
407558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    case ACPI_END_TAG_DESCRIPTOR:
408558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      if (IsaResource != NULL) {
409558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        IsaResource[Count].Type       = EfiIsaAcpiResourceEndOfList;
410558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        IsaResource[Count].Attribute  = 0;
411558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        IsaResource[Count].StartRange = 0;
412558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        IsaResource[Count].EndRange   = 0;
413558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
414558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      Count ++;
415558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      break;
416558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
417558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
418558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Count;
419558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
420558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
421558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
422558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Initializes an ISA I/O Instance
423558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
424558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] IsaIoDevice            The isa device to be initialized.
425558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] DevicePath             The device path of the isa device.
426558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Resources              The ACPI resource list.
427558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
428558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
429558be4559ac1fba1a81b483c90d00680a18640ffniruiyuVOID
430558be4559ac1fba1a81b483c90d00680a18640ffniruiyuInitializeIsaIoInstance (
431558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN ISA_IO_DEVICE               *IsaIoDevice,
432558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
433558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN ACPI_RESOURCE_HEADER_PTR    Resources
434558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
435558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
436558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINTN                                       Index;
437558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ACPI_HID_DEVICE_PATH                        *AcpiNode;
438558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ACPI_RESOURCE_HEADER_PTR                    ResourcePtr;
439558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
440558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
441558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Use the ISA IO Protocol structure template to initialize the ISA IO instance
442558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
443558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  CopyMem (
444558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    &IsaIoDevice->IsaIo,
445558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    &mIsaIoInterface,
446558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    sizeof (EFI_ISA_IO_PROTOCOL)
447558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    );
448558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
449558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
450558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Count the resources including the ACPI End Tag
451558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
452558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ResourcePtr = Resources;
453558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Index       = 0;
454558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {
455558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
456558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Index += AcpiResourceToIsaResource (ResourcePtr, NULL);
457558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
458558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (ResourcePtr.SmallHeader->Bits.Type == 0) {
459558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader
460558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                              + ResourcePtr.SmallHeader->Bits.Length
461558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                              + sizeof (*ResourcePtr.SmallHeader));
462558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    } else {
463558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader
464558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                              + ResourcePtr.LargeHeader->Length
465558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                              + sizeof (*ResourcePtr.LargeHeader));
466558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
467558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
468558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
469558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
470558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Get the Isa Resource count for ACPI End Tag
471558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
472558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Index += AcpiResourceToIsaResource (ResourcePtr, NULL);
473558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
474558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
475558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Initialize the ResourceList
476558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
477558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice->IsaIo.ResourceList = AllocatePool (sizeof (EFI_ISA_ACPI_RESOURCE_LIST) + Index * sizeof (EFI_ISA_ACPI_RESOURCE));
478558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ASSERT (IsaIoDevice->IsaIo.ResourceList != NULL);
479558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice->IsaIo.ResourceList->ResourceItem = (EFI_ISA_ACPI_RESOURCE *) (IsaIoDevice->IsaIo.ResourceList + 1);
480558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
481558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  AcpiNode = (ACPI_HID_DEVICE_PATH *) ((UINT8 *) DevicePath + GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH - sizeof (ACPI_HID_DEVICE_PATH));
482558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice->IsaIo.ResourceList->Device.HID = AcpiNode->HID;
483558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice->IsaIo.ResourceList->Device.UID = AcpiNode->UID;
484558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
485558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ResourcePtr = Resources;
486558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Index       = 0;
487558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {
488558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
489558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Index += AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]);
490558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
491558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (ResourcePtr.SmallHeader->Bits.Type == 0) {
492558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader
493558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                              + ResourcePtr.SmallHeader->Bits.Length
494558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                              + sizeof (*ResourcePtr.SmallHeader));
495558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    } else {
496558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader
497558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                              + ResourcePtr.LargeHeader->Length
498558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                              + sizeof (*ResourcePtr.LargeHeader));
499558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
500558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
501558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
502558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
503558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Convert the ACPI End Tag
504558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
505558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]);
506558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
507558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
508558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
509558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Performs an ISA I/O Read Cycle
510558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
511558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  This              A pointer to the EFI_ISA_IO_PROTOCOL instance.
512558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Width             Specifies the width of the I/O operation.
513558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Offset            The offset in ISA I/O space to start the I/O operation.
514558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Count             The number of I/O operations to perform.
515558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[out] Buffer            The destination buffer to store the results
516558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
517558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS           The data was read from the device sucessfully.
518558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED       The Offset is not valid for this device.
519558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
520558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
521558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
522558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
523558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFIAPI
524558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoIoRead (
525558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  EFI_ISA_IO_PROTOCOL        *This,
526558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  EFI_ISA_IO_PROTOCOL_WIDTH  Width,
527558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  UINT32                     Offset,
528558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  UINTN                      Count,
529558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  OUT VOID                       *Buffer
530558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
531558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
532558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS    Status;
533558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ISA_IO_DEVICE *IsaIoDevice;
534558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
535558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
536558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
537558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
538558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Verify Isa IO Access
539558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
540558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoVerifyAccess (
541558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaIoDevice,
542558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaAccessTypeIo,
543558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Width,
544558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Count,
545558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Offset
546558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
547558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
548558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
549558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
550558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
551558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoDevice->PciIo->Io.Read (
552558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    IsaIoDevice->PciIo,
553558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
554558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    EFI_PCI_IO_PASS_THROUGH_BAR,
555558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    Offset,
556558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    Count,
557558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    Buffer
558558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    );
559558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
560558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
561558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    REPORT_STATUS_CODE (
562558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_ERROR_CODE | EFI_ERROR_MINOR,
563558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
564558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      );
565558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
566558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
567558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Status;
568558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
569558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
570558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
571558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Performs an ISA I/O Write Cycle
572558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
573558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
574558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Width               Specifies the width of the I/O operation.
575558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Offset              The offset in ISA I/O space to start the I/O operation.
576558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Count               The number of I/O operations to perform.
577558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Buffer              The source buffer to write data from
578558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
579558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            The data was writen to the device sucessfully.
580558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED        The Offset is not valid for this device.
581558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
582558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
583558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
584558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
585558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFIAPI
586558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoIoWrite (
587558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL        *This,
588558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL_WIDTH  Width,
589558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT32                     Offset,
590558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINTN                      Count,
591558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN VOID                       *Buffer
592558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
593558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
594558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS    Status;
595558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ISA_IO_DEVICE *IsaIoDevice;
596558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
597558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
598558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
599558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
600558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Verify Isa IO Access
601558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
602558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoVerifyAccess (
603558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaIoDevice,
604558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaAccessTypeIo,
605558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Width,
606558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Count,
607558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Offset
608558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
609558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
610558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
611558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
612558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
613558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoDevice->PciIo->Io.Write (
614558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    IsaIoDevice->PciIo,
615558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
616558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    EFI_PCI_IO_PASS_THROUGH_BAR,
617558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    Offset,
618558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    Count,
619558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    Buffer
620558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    );
621558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
622558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
623558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    REPORT_STATUS_CODE (
624558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_ERROR_CODE | EFI_ERROR_MINOR,
625558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
626558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      );
627558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
628558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
629558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Status;
630558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
631558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
632558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
633558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Writes an 8-bit I/O Port
634558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
635558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
636558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Offset              The offset in ISA IO space to start the IO operation.
637558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Value               The data to write port.
638558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
639558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            Success.
640558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  Parameter is invalid.
641558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED        The address range specified by Offset is not valid.
642558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
643558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
644558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
645558be4559ac1fba1a81b483c90d00680a18640ffniruiyuWritePort (
646558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL  *This,
647558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT32               Offset,
648558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT8                Value
649558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
650558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
651558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS    Status;
652558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ISA_IO_DEVICE *IsaIoDevice;
653558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
654558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
655558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
656558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoDevice->PciIo->Io.Write (
657558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    IsaIoDevice->PciIo,
658558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    EfiPciIoWidthUint8,
659558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    EFI_PCI_IO_PASS_THROUGH_BAR,
660558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    Offset,
661558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    1,
662558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    &Value
663558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                    );
664558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
665558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    REPORT_STATUS_CODE (
666558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_ERROR_CODE | EFI_ERROR_MINOR,
667558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
668558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      );
669558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
670558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
671558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
672558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
673558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Wait for 50 microseconds to take affect.
674558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
675558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  gBS->Stall (50);
676558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
677558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return EFI_SUCCESS;
678558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
679558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
680558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
681558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Writes I/O operation base address and count number to a 8 bit I/O Port.
682558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
683558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
684558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] AddrOffset          The address' offset.
685558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] PageOffset          The page's offest.
686558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] CountOffset         The count's offset.
687558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] BaseAddress         The base address.
688558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Count               The number of I/O operations to perform.
689558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
690558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            Success.
691558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  Parameter is invalid.
692558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED        The address range specified by these Offsets and Count is not valid.
693558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
694558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
695558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
696558be4559ac1fba1a81b483c90d00680a18640ffniruiyuWriteDmaPort (
697558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL  *This,
698558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT32               AddrOffset,
699558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT32               PageOffset,
700558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT32               CountOffset,
701558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT32               BaseAddress,
702558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT16               Count
703558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
704558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
705558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS  Status;
706558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
707558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff));
708558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
709558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
710558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
711558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
712558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff));
713558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
714558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
715558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
716558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
717558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff));
718558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
719558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
720558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
721558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
722558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff));
723558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
724558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
725558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
726558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
727558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff));
728558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Status;
729558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
730558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
731558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
732558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Unmaps a memory region for DMA
733558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
734558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] This           A pointer to the EFI_ISA_IO_PROTOCOL instance.
735558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Mapping        The mapping value returned from EFI_ISA_IO.Map().
736558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
737558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS       The range was unmapped.
738558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_DEVICE_ERROR  The data was not committed to the target system memory.
739558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
740558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
741558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFIAPI
742558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoUnmap (
743558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL  *This,
744558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN VOID                 *Mapping
745558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
746558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
747558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ISA_MAP_INFO  *IsaMapInfo;
748558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
749558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
750558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Check if DMA is supported.
751558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
752558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) {
753558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_UNSUPPORTED;
754558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
755558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
756558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
757558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // See if the Map() operation associated with this Unmap() required a mapping
758558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // buffer.If a mapping buffer was not required, then this function simply
759558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // returns EFI_SUCCESS.
760558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
761558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (Mapping != NULL) {
762558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
763558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Get the MAP_INFO structure from Mapping
764558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
765558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo = (ISA_MAP_INFO *) Mapping;
766558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
767558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
768558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // If this is a write operation from the Agent's point of view,
769558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // then copy the contents of the mapped buffer into the real buffer
770558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // so the processor can read the contents of the real buffer.
771558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
772558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) {
773558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      CopyMem (
774558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        (VOID *) (UINTN) IsaMapInfo->HostAddress,
775558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
776558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        IsaMapInfo->NumberOfBytes
777558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        );
778558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
779558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
780558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Free the mapped buffer and the MAP_INFO structure.
781558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
782558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages);
783558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    FreePool (IsaMapInfo);
784558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
785558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
786558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return EFI_SUCCESS;
787558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
788558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
789558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
790558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Flushes any posted write data to the system memory.
791558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
792558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] This             A pointer to the EFI_ISA_IO_PROTOCOL instance.
793558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
794558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval  EFI_SUCCESS        The buffers were flushed.
795558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval  EFI_DEVICE_ERROR   The buffers were not flushed due to a hardware error.
796558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
797558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
798558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFIAPI
799558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoFlush (
800558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL  *This
801558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
802558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
803558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS    Status;
804558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ISA_IO_DEVICE *IsaIoDevice;
805558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
806558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
807558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
808558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo);
809558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
810558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
811558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    REPORT_STATUS_CODE (
812558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_ERROR_CODE | EFI_ERROR_MINOR,
813558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
814558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      );
815558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
816558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
817558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Status;
818558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
819558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
820558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
821558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Performs an ISA Memory Read Cycle
822558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
823558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  This               A pointer to the EFI_ISA_IO_PROTOCOL instance.
824558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Width              Specifies the width of the memory operation.
825558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Offset             The offset in ISA memory space to start the memory operation.
826558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Count              The number of memory operations to perform.
827558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[out] Buffer             The destination buffer to store the results
828558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
829558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            The data was read from the device successfully.
830558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED        The Offset is not valid for this device.
831558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
832558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
833558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
834558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
835558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFIAPI
836558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoMemRead (
837558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  EFI_ISA_IO_PROTOCOL        *This,
838558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  EFI_ISA_IO_PROTOCOL_WIDTH  Width,
839558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  UINT32                     Offset,
840558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  UINTN                      Count,
841558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  OUT VOID                       *Buffer
842558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
843558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
844558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS    Status;
845558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ISA_IO_DEVICE *IsaIoDevice;
846558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
847558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
848558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Check if ISA memory is supported.
849558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
850558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
851558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_UNSUPPORTED;
852558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
853558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
854558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
855558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
856558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
857558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Verify the Isa Io Access
858558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
859558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoVerifyAccess (
860558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaIoDevice,
861558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaAccessTypeMem,
862558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Width,
863558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Count,
864558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Offset
865558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
866558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
867558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
868558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
869558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
870558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoDevice->PciIo->Mem.Read (
871558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     IsaIoDevice->PciIo,
872558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
873558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     EFI_PCI_IO_PASS_THROUGH_BAR,
874558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     Offset,
875558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     Count,
876558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     Buffer
877558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     );
878558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
879558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
880558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    REPORT_STATUS_CODE (
881558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_ERROR_CODE | EFI_ERROR_MINOR,
882558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
883558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      );
884558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
885558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
886558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Status;
887558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
888558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
889558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
890558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Performs an ISA Memory Write Cycle
891558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
892558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
893558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Width               Specifies the width of the memory operation.
894558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Offset              The offset in ISA memory space to start the memory operation.
895558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Count               The number of memory operations to perform.
896558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Buffer              The source buffer to write data from
897558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
898558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            The data was written to the device sucessfully.
899558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED        The Offset is not valid for this device.
900558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
901558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
902558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
903558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
904558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFIAPI
905558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoMemWrite (
906558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL        *This,
907558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL_WIDTH  Width,
908558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT32                     Offset,
909558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINTN                      Count,
910558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN VOID                       *Buffer
911558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
912558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
913558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS    Status;
914558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ISA_IO_DEVICE *IsaIoDevice;
915558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
916558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
917558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Check if ISA memory is supported.
918558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
919558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
920558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_UNSUPPORTED;
921558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
922558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
923558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
924558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
925558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
926558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Verify Isa IO Access
927558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
928558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoVerifyAccess (
929558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaIoDevice,
930558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaAccessTypeMem,
931558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Width,
932558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Count,
933558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Offset
934558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
935558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
936558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
937558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
938558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
939558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoDevice->PciIo->Mem.Write (
940558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     IsaIoDevice->PciIo,
941558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
942558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     EFI_PCI_IO_PASS_THROUGH_BAR,
943558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     Offset,
944558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     Count,
945558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     Buffer
946558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                     );
947558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
948558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
949558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    REPORT_STATUS_CODE (
950558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_ERROR_CODE | EFI_ERROR_MINOR,
951558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
952558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      );
953558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
954558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
955558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Status;
956558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
957558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
958558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
959558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Copy one region of ISA memory space to another region of ISA memory space on the ISA controller.
960558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
961558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  This               A pointer to the EFI_ISA_IO_PROTOCOL instance.
962558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Width              Specifies the width of the memory copy operation.
963558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  DestOffset         The offset of the destination
964558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  SrcOffset          The offset of the source
965558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Count              The number of memory copy  operations to perform
966558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
967558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            The data was copied sucessfully.
968558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED        The DestOffset or SrcOffset is not valid for this device.
969558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
970558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
971558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
972558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
973558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFIAPI
974558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoCopyMem (
975558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL        *This,
976558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL_WIDTH  Width,
977558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT32                     DestOffset,
978558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINT32                     SrcOffset,
979558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINTN                      Count
980558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
981558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
982558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS    Status;
983558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ISA_IO_DEVICE *IsaIoDevice;
984558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
985558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
986558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Check if ISA memory is supported.
987558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
988558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
989558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_UNSUPPORTED;
990558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
991558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
992558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
993558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
994558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
995558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Verify Isa IO Access for destination and source
996558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
997558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoVerifyAccess (
998558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaIoDevice,
999558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaAccessTypeMem,
1000558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Width,
1001558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Count,
1002558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             DestOffset
1003558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1004558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1005558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1006558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1007558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1008558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoVerifyAccess (
1009558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaIoDevice,
1010558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             IsaAccessTypeMem,
1011558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Width,
1012558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Count,
1013558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             SrcOffset
1014558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1015558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1016558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1017558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1018558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1019558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = IsaIoDevice->PciIo->CopyMem (
1020558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 IsaIoDevice->PciIo,
1021558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
1022558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 EFI_PCI_IO_PASS_THROUGH_BAR,
1023558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 DestOffset,
1024558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 EFI_PCI_IO_PASS_THROUGH_BAR,
1025558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 SrcOffset,
1026558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 Count
1027558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 );
1028558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1029558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1030558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    REPORT_STATUS_CODE (
1031558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_ERROR_CODE | EFI_ERROR_MINOR,
1032558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
1033558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      );
1034558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1035558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1036558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Status;
1037558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
1038558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1039558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
1040558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Maps a memory region for DMA, note this implementation
1041558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  only supports slave read/write operation to save code size.
1042558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1043558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param This                    A pointer to the EFI_ISA_IO_PROTOCOL instance.
1044558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param Operation               Indicates the type of DMA (slave or bus master), and if
1045558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 the DMA operation is going to read or write to system memory.
1046558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param ChannelNumber           The slave channel number to use for this DMA operation.
1047558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 If Operation and ChannelAttributes shows that this device
1048558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 performs bus mastering DMA, then this field is ignored.
1049558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 The legal range for this field is 0..7.
1050558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param ChannelAttributes       The attributes of the DMA channel to use for this DMA operation
1051558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param HostAddress             The system memory address to map to the device.
1052558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param NumberOfBytes           On input the number of bytes to map.  On output the number
1053558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 of bytes that were mapped.
1054558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param DeviceAddress           The resulting map address for the bus master device to use
1055558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 to access the hosts HostAddress.
1056558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param Mapping                 A resulting value to pass to EFI_ISA_IO.Unmap().
1057558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1058558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            The range was mapped for the returned NumberOfBytes.
1059558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  The Operation or HostAddress is undefined.
1060558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED        The HostAddress can not be mapped as a common buffer.
1061558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_DEVICE_ERROR       The system hardware could not map the requested address.
1062558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
1063558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
1064558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
1065558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoMapOnlySupportSlaveReadWrite (
1066558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     EFI_ISA_IO_PROTOCOL            *This,
1067558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     EFI_ISA_IO_PROTOCOL_OPERATION  Operation,
1068558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     UINT8                          ChannelNumber  OPTIONAL,
1069558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     UINT32                         ChannelAttributes,
1070558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     VOID                           *HostAddress,
1071558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN OUT UINTN                          *NumberOfBytes,
1072558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
1073558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  OUT    VOID                           **Mapping
1074558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
1075558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
1076558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS            Status;
1077558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
1078558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ISA_MAP_INFO          *IsaMapInfo;
1079558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT8                 DmaMode;
1080558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINTN                 MaxNumberOfBytes;
1081558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT32                BaseAddress;
1082558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT16                Count;
1083558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT8                 DmaMask;
1084558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT8                 DmaClear;
1085558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT8                 DmaChannelMode;
1086558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1087558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((NULL == This) ||
1088558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      (NULL == HostAddress) ||
1089558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      (NULL == NumberOfBytes) ||
1090558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      (NULL == DeviceAddress) ||
1091558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      (NULL == Mapping)
1092558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      ) {
1093558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_INVALID_PARAMETER;
1094558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1095558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1096558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1097558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Initialize the return values to their defaults
1098558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1099558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  *Mapping = NULL;
1100558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1101558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1102558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Make sure the Operation parameter is valid.
1103558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Light IsaIo only supports two operations.
1104558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1105558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (!(Operation == EfiIsaIoOperationSlaveRead ||
1106558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        Operation == EfiIsaIoOperationSlaveWrite)) {
1107558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_INVALID_PARAMETER;
1108558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1109558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1110558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (ChannelNumber >= 4) {
1111558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1112558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // The Light IsaIo doesn't support channelNumber larger than 4.
1113558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1114558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_INVALID_PARAMETER;
1115558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1116558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1117558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1118558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Map the HostAddress to a DeviceAddress.
1119558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1120558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1121558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((PhysicalAddress + *NumberOfBytes) > BASE_16MB) {
1122558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1123558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Common Buffer operations can not be remapped.  If the common buffer
1124558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // is above 16MB, then it is not possible to generate a mapping, so return
1125558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // an error.
1126558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1127558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {
1128558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      return EFI_UNSUPPORTED;
1129558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1130558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1131558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1132558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // is called later.
1133558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1134558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));
1135558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (IsaMapInfo == NULL) {
1136558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      *NumberOfBytes = 0;
1137558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      return EFI_OUT_OF_RESOURCES;
1138558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1139558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1140558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Return a pointer to the MAP_INFO structure in Mapping
1141558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1142558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    *Mapping = IsaMapInfo;
1143558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1144558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1145558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Initialize the MAP_INFO structure
1146558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1147558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo->Operation         = Operation;
1148558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo->NumberOfBytes     = *NumberOfBytes;
1149558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES (*NumberOfBytes);
1150558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo->HostAddress       = PhysicalAddress;
1151558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo->MappedHostAddress = BASE_16MB - 1;
1152558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1153558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1154558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Allocate a buffer below 16MB to map the transfer to.
1155558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1156558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Status = gBS->AllocatePages (
1157558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                    AllocateMaxAddress,
1158558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                    EfiBootServicesData,
1159558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                    IsaMapInfo->NumberOfPages,
1160558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                    &IsaMapInfo->MappedHostAddress
1161558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                    );
1162558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (EFI_ERROR (Status)) {
1163558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      FreePool (IsaMapInfo);
1164558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      *NumberOfBytes  = 0;
1165558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      *Mapping        = NULL;
1166558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      return Status;
1167558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1168558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1169558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // If this is a read operation from the DMA agents's point of view,
1170558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // then copy the contents of the real buffer into the mapped buffer
1171558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // so the DMA agent can read the contents of the real buffer.
1172558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1173558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (Operation == EfiIsaIoOperationSlaveRead) {
1174558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      CopyMem (
1175558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
1176558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        (VOID *) (UINTN) IsaMapInfo->HostAddress,
1177558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        IsaMapInfo->NumberOfBytes
1178558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        );
1179558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1180558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1181558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // The DeviceAddress is the address of the maped buffer below 16 MB
1182558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1183558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    *DeviceAddress = IsaMapInfo->MappedHostAddress;
1184558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  } else {
1185558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1186558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // The transfer is below 16 MB, so the DeviceAddress is simply the
1187558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // HostAddress
1188558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1189558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    *DeviceAddress = PhysicalAddress;
1190558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1191558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1192558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1193558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Figure out what to program into the DMA Channel Mode Register
1194558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1195558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));
1196558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (Operation == EfiIsaIoOperationSlaveRead) {
1197558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaMode |= V_8237_DMA_CHMODE_MEM2IO;
1198558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  } else {
1199558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaMode |= V_8237_DMA_CHMODE_IO2MEM;
1200558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1201558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1202558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
1203558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1204558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  DmaMode |= V_8237_DMA_CHMODE_SINGLE;
1205558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1206558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1207558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // A Slave DMA transfer can not cross a 64K boundary.
1208558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Compute *NumberOfBytes based on this restriction.
1209558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1210558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);
1211558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (*NumberOfBytes > MaxNumberOfBytes) {
1212558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    *NumberOfBytes = MaxNumberOfBytes;
1213558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1214558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1215558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Compute the values to program into the BaseAddress and Count registers
1216558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // of the Slave DMA controller
1217558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1218558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  BaseAddress = (UINT32) (*DeviceAddress);
1219558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Count       = (UINT16) (*NumberOfBytes - 1);
1220558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1221558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Program the DMA Write Single Mask Register for ChannelNumber
1222558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Clear the DMA Byte Pointer Register
1223558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1224558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  DmaMask         = R_8237_DMA_WRSMSK_CH0_3;
1225558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  DmaClear        = R_8237_DMA_CBPR_CH0_3;
1226558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  DmaChannelMode  = R_8237_DMA_CHMODE_CH0_3;
1227558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1228558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (
1229558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             This,
1230558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             DmaMask,
1231558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1232558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1233558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1234558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1235558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1236558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1237558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (
1238558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             This,
1239558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             DmaClear,
1240558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1241558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1242558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1243558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1244558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1245558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1246558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (This, DmaChannelMode, DmaMode);
1247558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1248558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1249558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1250558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1251558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WriteDmaPort (
1252558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             This,
1253558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             mDmaRegisters[ChannelNumber].Address,
1254558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             mDmaRegisters[ChannelNumber].Page,
1255558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             mDmaRegisters[ChannelNumber].Count,
1256558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             BaseAddress,
1257558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Count
1258558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1259558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1260558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1261558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1262558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1263558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (
1264558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             This,
1265558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             DmaMask,
1266558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             (UINT8) (ChannelNumber & 0x03)
1267558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1268558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1269558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1270558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1271558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1272558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return EFI_SUCCESS;
1273558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
1274558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1275558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
1276558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Maps a memory region for DMA. This implementation implement the
1277558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  the full mapping support.
1278558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1279558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param This                    A pointer to the EFI_ISA_IO_PROTOCOL instance.
1280558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param Operation               Indicates the type of DMA (slave or bus master), and if
1281558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 the DMA operation is going to read or write to system memory.
1282558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param ChannelNumber           The slave channel number to use for this DMA operation.
1283558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 If Operation and ChannelAttributes shows that this device
1284558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 performs bus mastering DMA, then this field is ignored.
1285558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 The legal range for this field is 0..7.
1286558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param ChannelAttributes       The attributes of the DMA channel to use for this DMA operation
1287558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param HostAddress             The system memory address to map to the device.
1288558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param NumberOfBytes           On input the number of bytes to map.  On output the number
1289558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 of bytes that were mapped.
1290558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param DeviceAddress           The resulting map address for the bus master device to use
1291558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 to access the hosts HostAddress.
1292558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param Mapping                 A resulting value to pass to EFI_ISA_IO.Unmap().
1293558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1294558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS           - The range was mapped for the returned NumberOfBytes.
1295558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1296558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED       - The HostAddress can not be mapped as a common buffer.
1297558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_DEVICE_ERROR      - The system hardware could not map the requested address.
1298558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES  - The memory pages could not be allocated.
1299558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
1300558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
1301558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoMapFullSupport (
1302558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     EFI_ISA_IO_PROTOCOL                                  *This,
1303558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     EFI_ISA_IO_PROTOCOL_OPERATION                        Operation,
1304558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     UINT8                                                ChannelNumber         OPTIONAL,
1305558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     UINT32                                               ChannelAttributes,
1306558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     VOID                                                 *HostAddress,
1307558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN OUT UINTN                                                *NumberOfBytes,
1308558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  OUT    EFI_PHYSICAL_ADDRESS                                 *DeviceAddress,
1309558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  OUT    VOID                                                 **Mapping
1310558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
1311558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
1312558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS            Status;
1313558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  BOOLEAN               Master;
1314558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  BOOLEAN               Read;
1315558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
1316558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  ISA_MAP_INFO          *IsaMapInfo;
1317558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT8                 DmaMode;
1318558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINTN                 MaxNumberOfBytes;
1319558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT32                BaseAddress;
1320558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT16                Count;
1321558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT8                 DmaMask;
1322558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT8                 DmaClear;
1323558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  UINT8                 DmaChannelMode;
1324558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1325558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((NULL == This) ||
1326558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      (NULL == HostAddress) ||
1327558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      (NULL == NumberOfBytes) ||
1328558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      (NULL == DeviceAddress) ||
1329558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      (NULL == Mapping)
1330558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      ) {
1331558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_INVALID_PARAMETER;
1332558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1333558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1334558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1335558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Initialize the return values to their defaults
1336558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1337558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  *Mapping = NULL;
1338558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1339558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1340558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Make sure the Operation parameter is valid
1341558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
13423d78c020d22023d35d27b48817d73ff31a361ac7rsun  if ((UINT32)Operation >= EfiIsaIoOperationMaximum) {
1343558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_INVALID_PARAMETER;
1344558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1345558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1346558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (ChannelNumber >= 8) {
1347558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_INVALID_PARAMETER;
1348558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1349558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1350558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1351558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // See if this is a Slave DMA Operation
1352558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1353558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Master  = TRUE;
1354558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Read    = FALSE;
1355558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (Operation == EfiIsaIoOperationSlaveRead) {
1356558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Operation = EfiIsaIoOperationBusMasterRead;
1357558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Master    = FALSE;
1358558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Read      = TRUE;
1359558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1360558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1361558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (Operation == EfiIsaIoOperationSlaveWrite) {
1362558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Operation = EfiIsaIoOperationBusMasterWrite;
1363558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Master    = FALSE;
1364558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Read      = FALSE;
1365558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1366558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1367558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (!Master) {
1368558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1369558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Make sure that ChannelNumber is a valid channel number
1370558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Channel 4 is used to cascade, so it is illegal.
1371558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1372558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (ChannelNumber == 4 || ChannelNumber > 7) {
1373558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      return EFI_INVALID_PARAMETER;
1374558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1375558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1376558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // This implementation only support COMPATIBLE DMA Transfers
1377558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1378558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE) == 0) {
1379558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      return EFI_INVALID_PARAMETER;
1380558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1381558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1382558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if ((ChannelAttributes &
1383558be4559ac1fba1a81b483c90d00680a18640ffniruiyu         (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A |
1384558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B |
1385558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C)) != 0) {
1386558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      return EFI_INVALID_PARAMETER;
1387558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1388558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1389558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (ChannelNumber < 4) {
1390558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      //
1391558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      // If this is Channel 0..3, then the width must be 8 bit
1392558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      //
1393558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) == 0) ||
1394558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) != 0)
1395558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          ) {
1396558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        return EFI_INVALID_PARAMETER;
1397558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
1398558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    } else {
1399558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      //
1400558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      // If this is Channel 4..7, then the width must be 16 bit
1401558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      //
1402558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) != 0) ||
1403558be4559ac1fba1a81b483c90d00680a18640ffniruiyu          ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) == 0)) {
1404558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        return EFI_INVALID_PARAMETER;
1405558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
1406558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1407558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1408558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Either Demand Mode or Single Mode must be selected, but not both
1409558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1410558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) {
1411558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) {
1412558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        return EFI_INVALID_PARAMETER;
1413558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
1414558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    } else {
1415558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) == 0) {
1416558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        return EFI_INVALID_PARAMETER;
1417558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      }
1418558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1419558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1420558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1421558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Map the HostAddress to a DeviceAddress.
1422558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1423558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1424558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((PhysicalAddress +*NumberOfBytes) > BASE_16MB) {
1425558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1426558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Common Buffer operations can not be remapped.  If the common buffer
1427558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // is above 16MB, then it is not possible to generate a mapping, so return
1428558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // an error.
1429558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1430558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {
1431558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      return EFI_UNSUPPORTED;
1432558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1433558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1434558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1435558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // is called later.
1436558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1437558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));
1438558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (IsaMapInfo == NULL) {
1439558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      *NumberOfBytes = 0;
1440558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      return EFI_OUT_OF_RESOURCES;
1441558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1442558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1443558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Return a pointer to the MAP_INFO structure in Mapping
1444558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1445558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    *Mapping = IsaMapInfo;
1446558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1447558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1448558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Initialize the MAP_INFO structure
1449558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1450558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo->Operation         = Operation;
1451558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo->NumberOfBytes     = *NumberOfBytes;
1452558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES (*NumberOfBytes);
1453558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo->HostAddress       = PhysicalAddress;
1454558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    IsaMapInfo->MappedHostAddress = BASE_16MB - 1;
1455558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1456558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1457558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // Allocate a buffer below 16MB to map the transfer to.
1458558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1459558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Status = gBS->AllocatePages (
1460558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                    AllocateMaxAddress,
1461558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                    EfiBootServicesData,
1462558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                    IsaMapInfo->NumberOfPages,
1463558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                    &IsaMapInfo->MappedHostAddress
1464558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                    );
1465558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (EFI_ERROR (Status)) {
1466558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      FreePool (IsaMapInfo);
1467558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      *NumberOfBytes  = 0;
1468558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      *Mapping        = NULL;
1469558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      return Status;
1470558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1471558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1472558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // If this is a read operation from the DMA agents's point of view,
1473558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // then copy the contents of the real buffer into the mapped buffer
1474558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // so the DMA agent can read the contents of the real buffer.
1475558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1476558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if (Operation == EfiIsaIoOperationBusMasterRead) {
1477558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      CopyMem (
1478558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
1479558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        (VOID *) (UINTN) IsaMapInfo->HostAddress,
1480558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        IsaMapInfo->NumberOfBytes
1481558be4559ac1fba1a81b483c90d00680a18640ffniruiyu        );
1482558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1483558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1484558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // The DeviceAddress is the address of the maped buffer below 16 MB
1485558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1486558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    *DeviceAddress = IsaMapInfo->MappedHostAddress;
1487558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  } else {
1488558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1489558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // The transfer is below 16 MB, so the DeviceAddress is simply the
1490558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    // HostAddress
1491558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    //
1492558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    *DeviceAddress = PhysicalAddress;
1493558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1494558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1495558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // If this is a Bus Master operation then return
1496558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1497558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (Master) {
1498558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_SUCCESS;
1499558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1500558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1501558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Figure out what to program into the DMA Channel Mode Register
1502558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1503558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));
1504558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (Read) {
1505558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaMode |= V_8237_DMA_CHMODE_MEM2IO;
1506558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  } else {
1507558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaMode |= V_8237_DMA_CHMODE_IO2MEM;
1508558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1509558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1510558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) != 0) {
1511558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaMode |= B_8237_DMA_CHMODE_AE;
1512558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1513558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1514558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) {
1515558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaMode |= V_8237_DMA_CHMODE_DEMAND;
1516558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1517558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1518558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) {
1519558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaMode |= V_8237_DMA_CHMODE_SINGLE;
1520558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1521558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1522558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // A Slave DMA transfer can not cross a 64K boundary.
1523558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Compute *NumberOfBytes based on this restriction.
1524558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1525558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);
1526558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (*NumberOfBytes > MaxNumberOfBytes) {
1527558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    *NumberOfBytes = MaxNumberOfBytes;
1528558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1529558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1530558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Compute the values to program into the BaseAddress and Count registers
1531558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // of the Slave DMA controller
1532558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1533558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (ChannelNumber < 4) {
1534558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    BaseAddress = (UINT32) (*DeviceAddress);
1535558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Count       = (UINT16) (*NumberOfBytes - 1);
1536558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  } else {
1537558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1));
1538558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Count       = (UINT16) ((*NumberOfBytes - 1) >> 1);
1539558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1540558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1541558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Program the DMA Write Single Mask Register for ChannelNumber
1542558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Clear the DMA Byte Pointer Register
1543558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1544558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (ChannelNumber < 4) {
1545558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaMask         = R_8237_DMA_WRSMSK_CH0_3;
1546558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaClear        = R_8237_DMA_CBPR_CH0_3;
1547558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaChannelMode  = R_8237_DMA_CHMODE_CH0_3;
1548558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  } else {
1549558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaMask         = R_8237_DMA_WRSMSK_CH4_7;
1550558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaClear        = R_8237_DMA_CBPR_CH4_7;
1551558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    DmaChannelMode  = R_8237_DMA_CHMODE_CH4_7;
1552558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1553558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1554558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (
1555558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             This,
1556558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             DmaMask,
1557558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1558558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1559558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1560558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1561558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1562558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1563558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (
1564558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             This,
1565558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             DmaClear,
1566558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1567558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1568558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1569558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1570558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1571558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1572558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (This, DmaChannelMode, DmaMode);
1573558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1574558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1575558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1576558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1577558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WriteDmaPort (
1578558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             This,
1579558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             mDmaRegisters[ChannelNumber].Address,
1580558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             mDmaRegisters[ChannelNumber].Page,
1581558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             mDmaRegisters[ChannelNumber].Count,
1582558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             BaseAddress,
1583558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Count
1584558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1585558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1586558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1587558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1588558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1589558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = WritePort (
1590558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             This,
1591558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             DmaMask,
1592558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             (UINT8) (ChannelNumber & 0x03)
1593558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1594558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1595558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1596558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1597558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1598558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return EFI_SUCCESS;
1599558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
1600558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1601558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
1602558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Maps a memory region for DMA
1603558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1604558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param This                    A pointer to the EFI_ISA_IO_PROTOCOL instance.
1605558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param Operation               Indicates the type of DMA (slave or bus master), and if
1606558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 the DMA operation is going to read or write to system memory.
1607558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param ChannelNumber           The slave channel number to use for this DMA operation.
1608558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 If Operation and ChannelAttributes shows that this device
1609558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 performs bus mastering DMA, then this field is ignored.
1610558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 The legal range for this field is 0..7.
1611558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param ChannelAttributes       The attributes of the DMA channel to use for this DMA operation
1612558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param HostAddress             The system memory address to map to the device.
1613558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param NumberOfBytes           On input the number of bytes to map.  On output the number
1614558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 of bytes that were mapped.
1615558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param DeviceAddress           The resulting map address for the bus master device to use
1616558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 to access the hosts HostAddress.
1617558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param Mapping                 A resulting value to pass to EFI_ISA_IO.Unmap().
1618558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1619558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            The range was mapped for the returned NumberOfBytes.
1620558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  The Operation or HostAddress is undefined.
1621558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED        The HostAddress can not be mapped as a common buffer.
1622558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_DEVICE_ERROR       The system hardware could not map the requested address.
1623558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
1624558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
1625558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
1626558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFIAPI
1627558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoMap (
1628558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     EFI_ISA_IO_PROTOCOL            *This,
1629558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     EFI_ISA_IO_PROTOCOL_OPERATION  Operation,
1630558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     UINT8                          ChannelNumber  OPTIONAL,
1631558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     UINT32                         ChannelAttributes,
1632558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN     VOID                           *HostAddress,
1633558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN OUT UINTN                          *NumberOfBytes,
1634558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
1635558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  OUT    VOID                           **Mapping
1636558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
1637558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
1638558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1639558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Check if DMA is supported.
1640558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1641558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) {
1642558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_UNSUPPORTED;
1643558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1644558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1645558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1646558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // ISA Bus Master.
1647558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1648558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // So we just return EFI_UNSUPPORTED for these functions.
1649558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1650558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) {
1651558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return IsaIoMapOnlySupportSlaveReadWrite (
1652558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             This,
1653558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Operation,
1654558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             ChannelNumber,
1655558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             ChannelAttributes,
1656558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             HostAddress,
1657558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             NumberOfBytes,
1658558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             DeviceAddress,
1659558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Mapping
1660558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1661558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1662558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  } else {
1663558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return IsaIoMapFullSupport (
1664558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             This,
1665558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Operation,
1666558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             ChannelNumber,
1667558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             ChannelAttributes,
1668558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             HostAddress,
1669558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             NumberOfBytes,
1670558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             DeviceAddress,
1671558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             Mapping
1672558be4559ac1fba1a81b483c90d00680a18640ffniruiyu             );
1673558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1674558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
1675558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1676558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
1677558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping.
1678558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1679558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  This               A pointer to the EFI_ISA_IO_PROTOCOL instance.
1680558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Type               The type allocation to perform.
1681558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  MemoryType         The type of memory to allocate.
1682558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Pages              The number of pages to allocate.
1683558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[out] HostAddress        A pointer to store the base address of the allocated range.
1684558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in]  Attributes         The requested bit mask of attributes for the allocated range.
1685558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1686558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            The requested memory pages were allocated.
1687558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  Type is invalid or MemoryType is invalid or HostAddress is NULL
1688558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_UNSUPPORTED        Attributes is unsupported or the memory range specified
1689558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                                 by HostAddress, Pages, and Type is not available for common buffer use.
1690558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
1691558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
1692558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
1693558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFIAPI
1694558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoAllocateBuffer (
1695558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  EFI_ISA_IO_PROTOCOL  *This,
1696558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  EFI_ALLOCATE_TYPE    Type,
1697558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  EFI_MEMORY_TYPE      MemoryType,
1698558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  UINTN                Pages,
1699558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  OUT VOID                 **HostAddress,
1700558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN  UINT64               Attributes
1701558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
1702558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
1703558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS            Status;
1704558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
1705558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1706558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1707558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1708558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // ISA Bus Master.
1709558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1710558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1711558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) ||
1712558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) {
1713558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_UNSUPPORTED;
1714558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1715558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1716558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (HostAddress == NULL) {
1717558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_INVALID_PARAMETER;
1718558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1719558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
17203d78c020d22023d35d27b48817d73ff31a361ac7rsun  if ((UINT32)Type >= MaxAllocateType) {
1721558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_INVALID_PARAMETER;
1722558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1723558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1724558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1725558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1726558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
1727558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_INVALID_PARAMETER;
1728558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1729558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1730558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if ((Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) != 0) {
1731558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_UNSUPPORTED;
1732558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1733558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1734558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (BASE_16MB - 1);
1735558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (Type == AllocateAddress) {
1736558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    if ((UINTN) (*HostAddress) >= BASE_16MB) {
1737558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      return EFI_UNSUPPORTED;
1738558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    } else {
1739558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      PhysicalAddress = (UINTN) (*HostAddress);
1740558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    }
1741558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1742558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1743558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (Type == AllocateAnyPages) {
1744558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    Type = AllocateMaxAddress;
1745558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1746558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1747558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress);
1748558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1749558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    REPORT_STATUS_CODE (
1750558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_ERROR_CODE | EFI_ERROR_MINOR,
1751558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
1752558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      );
1753558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return Status;
1754558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1755558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1756558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  *HostAddress = (VOID *) (UINTN) PhysicalAddress;
1757558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Status;
1758558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
1759558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1760558be4559ac1fba1a81b483c90d00680a18640ffniruiyu/**
1761558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer().
1762558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1763558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
1764558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] Pages               The number of pages to free.
1765558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @param[in] HostAddress         The base address of the allocated range.
1766558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1767558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_SUCCESS            The requested memory pages were freed.
1768558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  @retval EFI_INVALID_PARAMETER  The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1769558be4559ac1fba1a81b483c90d00680a18640ffniruiyu**/
1770558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFI_STATUS
1771558be4559ac1fba1a81b483c90d00680a18640ffniruiyuEFIAPI
1772558be4559ac1fba1a81b483c90d00680a18640ffniruiyuIsaIoFreeBuffer (
1773558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN EFI_ISA_IO_PROTOCOL  *This,
1774558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN UINTN                Pages,
1775558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  IN VOID                 *HostAddress
1776558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  )
1777558be4559ac1fba1a81b483c90d00680a18640ffniruiyu{
1778558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  EFI_STATUS  Status;
1779558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1780558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1781558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1782558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // ISA Bus Master.
1783558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1784558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  //
1785558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) ||
1786558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) {
1787558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    return EFI_UNSUPPORTED;
1788558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1789558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1790558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  Status = gBS->FreePages (
1791558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                  (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,
1792558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                  Pages
1793558be4559ac1fba1a81b483c90d00680a18640ffniruiyu                  );
1794558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  if (EFI_ERROR (Status)) {
1795558be4559ac1fba1a81b483c90d00680a18640ffniruiyu    REPORT_STATUS_CODE (
1796558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_ERROR_CODE | EFI_ERROR_MINOR,
1797558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
1798558be4559ac1fba1a81b483c90d00680a18640ffniruiyu      );
1799558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  }
1800558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1801558be4559ac1fba1a81b483c90d00680a18640ffniruiyu  return Status;
1802558be4559ac1fba1a81b483c90d00680a18640ffniruiyu}
1803558be4559ac1fba1a81b483c90d00680a18640ffniruiyu
1804