• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   The implementation for EFI_ISA_IO_PROTOCOL.
3 
4 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "IsaIo.h"
16 
17 //
18 // Module Variables
19 //
20 EFI_ISA_IO_PROTOCOL mIsaIoInterface = {
21   {
22     IsaIoMemRead,
23     IsaIoMemWrite
24   },
25   {
26     IsaIoIoRead,
27     IsaIoIoWrite
28   },
29   IsaIoCopyMem,
30   IsaIoMap,
31   IsaIoUnmap,
32   IsaIoAllocateBuffer,
33   IsaIoFreeBuffer,
34   IsaIoFlush,
35   NULL,
36   0,
37   NULL
38 };
39 
40 EFI_ISA_DMA_REGISTERS  mDmaRegisters[8] = {
41   {
42     0x00,
43     0x87,
44     0x01
45   },
46   {
47     0x02,
48     0x83,
49     0x03
50   },
51   {
52     0x04,
53     0x81,
54     0x05
55   },
56   {
57     0x06,
58     0x82,
59     0x07
60   },
61   {
62     0x00,
63     0x00,
64     0x00
65   },  // Channel 4 is invalid
66   {
67     0xC4,
68     0x8B,
69     0xC6
70   },
71   {
72     0xC8,
73     0x89,
74     0xCA
75   },
76   {
77     0xCC,
78     0x8A,
79     0xCE
80   },
81 };
82 
83 /**
84   Verifies access to an ISA device
85 
86   @param[in] IsaIoDevice         The ISA device to be verified.
87   @param[in] Type                The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo.
88   @param[in] Width               The width of the memory operation.
89   @param[in] Count               The number of memory operations to perform.
90   @param[in] Offset              The offset in ISA memory space to start the memory operation.
91 
92   @retval EFI_SUCCESS            Verify success.
93   @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value.
94   @retval EFI_UNSUPPORTED        The device ont support the access type.
95 **/
96 EFI_STATUS
IsaIoVerifyAccess(IN ISA_IO_DEVICE * IsaIoDevice,IN ISA_ACCESS_TYPE Type,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINTN Count,IN UINT32 Offset)97 IsaIoVerifyAccess (
98   IN ISA_IO_DEVICE              *IsaIoDevice,
99   IN ISA_ACCESS_TYPE            Type,
100   IN EFI_ISA_IO_PROTOCOL_WIDTH  Width,
101   IN UINTN                      Count,
102   IN UINT32                     Offset
103   )
104 {
105   EFI_ISA_ACPI_RESOURCE *Item;
106   EFI_STATUS            Status;
107 
108   if ((UINT32)Width >= EfiIsaIoWidthMaximum ||
109       Width == EfiIsaIoWidthReserved ||
110       Width == EfiIsaIoWidthFifoReserved ||
111       Width == EfiIsaIoWidthFillReserved
112       ) {
113     return EFI_INVALID_PARAMETER;
114   }
115 
116   //
117   // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
118   // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
119   //
120   if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) {
121     Count = 1;
122   }
123 
124   Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03);
125 
126   Status  = EFI_UNSUPPORTED;
127   Item    = IsaIoDevice->IsaIo.ResourceList->ResourceItem;
128   while (Item->Type != EfiIsaAcpiResourceEndOfList) {
129     if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) ||
130         (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) {
131       if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) {
132         return EFI_SUCCESS;
133       }
134 
135       if (Offset >= Item->StartRange && Offset <= Item->EndRange) {
136         Status = EFI_INVALID_PARAMETER;
137       }
138     }
139 
140     Item++;
141   }
142 
143   return Status;
144 }
145 
146 /**
147   Convert the IO Information in ACPI descriptor to IO ISA Attribute.
148 
149   @param[in] Information   The IO Information in ACPI descriptor
150 
151   @return UINT32           The IO ISA Attribute
152 **/
153 UINT32
IsaIoAttribute(IN UINT8 Information)154 IsaIoAttribute (
155   IN UINT8                            Information
156   )
157 {
158   UINT32             Attribute;
159 
160   Attribute = 0;
161 
162   switch (Information & EFI_ACPI_IO_DECODE_MASK) {
163     case EFI_ACPI_IO_DECODE_16_BIT:
164       Attribute |= EFI_ISA_ACPI_IO_DECODE_16_BITS;
165       break;
166 
167     case EFI_ACPI_IO_DECODE_10_BIT:
168       Attribute |= EFI_ISA_ACPI_IO_DECODE_10_BITS;
169       break;
170   }
171 
172   return Attribute;
173 }
174 
175 /**
176   Convert the IRQ Information in ACPI descriptor to IRQ ISA Attribute.
177 
178   @param[in] Information   The IRQ Information in ACPI descriptor
179 
180   @return UINT32           The IRQ ISA Attribute
181 **/
182 UINT32
IsaIrqAttribute(IN UINT8 Information)183 IsaIrqAttribute (
184   IN UINT8                            Information
185   )
186 {
187   UINT32             Attribute;
188 
189   Attribute = 0;
190 
191   if ((Information & EFI_ACPI_IRQ_POLARITY_MASK) == EFI_ACPI_IRQ_HIGH_TRUE) {
192     if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) {
193       Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE;
194     } else {
195       Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE;
196     }
197   } else {
198     if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) {
199       Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE;
200     } else {
201       Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE;
202     }
203   }
204   return Attribute;
205 }
206 
207 /**
208   Convert the Memory Information in ACPI descriptor to Memory ISA Attribute.
209 
210   @param[in] Information   The Memory Information in ACPI descriptor
211 
212   @return UINT32           The Memory ISA Attribute
213 **/
214 UINT32
IsaMemoryAttribute(IN UINT8 Information)215 IsaMemoryAttribute (
216   IN UINT8                            Information
217   )
218 {
219   UINT32             Attribute;
220 
221   Attribute = 0;
222 
223   switch (Information & EFI_ACPI_MEMORY_WRITE_STATUS_MASK) {
224     case EFI_ACPI_MEMORY_WRITABLE:
225       Attribute |= EFI_ISA_ACPI_MEMORY_WRITEABLE;
226       break;
227   }
228 
229   return Attribute;
230 }
231 
232 /**
233   Convert the DMA Information in ACPI descriptor to DMA ISA Attribute.
234 
235   @param[in] Information   The DMA Information in ACPI descriptor
236 
237   @return UINT32           The DMA ISA Attribute
238 **/
239 UINT32
IsaDmaAttribute(IN UINT8 Information)240 IsaDmaAttribute (
241   IN UINT8                            Information
242   )
243 {
244   UINT32             Attribute;
245 
246   Attribute = EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE;
247 
248   switch (Information & EFI_ACPI_DMA_SPEED_TYPE_MASK) {
249     case EFI_ACPI_DMA_SPEED_TYPE_COMPATIBILITY:
250       Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE;
251       break;
252     case EFI_ACPI_DMA_SPEED_TYPE_A:
253       Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A;
254       break;
255     case EFI_ACPI_DMA_SPEED_TYPE_B:
256       Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B;
257       break;
258     case EFI_ACPI_DMA_SPEED_TYPE_F:
259       Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C;
260       break;
261   }
262 
263   switch (Information & EFI_ACPI_DMA_TRANSFER_TYPE_MASK) {
264     case EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT:
265       Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8;
266       break;
267     case EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT:
268       Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16;
269       break;
270   }
271 
272   return Attribute;
273 }
274 
275 /**
276   Convert the ACPI resource descriptor to ISA resource descriptor.
277 
278   @param[in]  AcpiResource          Pointer to the ACPI resource descriptor
279   @param[out] IsaResource           The optional pointer to the buffer to
280                                     store the converted ISA resource descriptor
281 
282   @return     UINTN                 Number of ISA resource descriptor needed
283 **/
284 UINTN
AcpiResourceToIsaResource(IN ACPI_RESOURCE_HEADER_PTR AcpiResource,OUT EFI_ISA_ACPI_RESOURCE * IsaResource OPTIONAL)285 AcpiResourceToIsaResource (
286   IN  ACPI_RESOURCE_HEADER_PTR        AcpiResource,
287   OUT EFI_ISA_ACPI_RESOURCE           *IsaResource   OPTIONAL
288   )
289 {
290   UINT32                                        Index;
291   UINTN                                         Count;
292   UINT32                                        LastIndex;
293   EFI_ACPI_IO_PORT_DESCRIPTOR                   *Io;
294   EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR    *FixedIo;
295   EFI_ACPI_IRQ_DESCRIPTOR                       *Irq;
296   EFI_ACPI_DMA_DESCRIPTOR                       *Dma;
297   EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR       *Memory;
298   EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *FixedMemory;
299 
300   Count     = 0;
301   LastIndex = 0;
302 
303   switch (AcpiResource.SmallHeader->Byte) {
304     case ACPI_DMA_DESCRIPTOR:
305       Dma = (EFI_ACPI_DMA_DESCRIPTOR *) AcpiResource.SmallHeader;
306       for (Index = 0; Index < sizeof (Dma->ChannelMask) * 8; Index++) {
307         if (Dma->ChannelMask & (1 << Index)) {
308           if ((Count > 0) && (LastIndex + 1 == Index)) {
309             if (IsaResource != NULL) {
310               IsaResource[Count - 1].EndRange ++;
311             }
312           } else {
313             if (IsaResource != NULL) {
314               IsaResource[Count].Type       = EfiIsaAcpiResourceDma;
315               IsaResource[Count].Attribute  = IsaDmaAttribute (Dma->Information);
316               IsaResource[Count].StartRange = Index;
317               IsaResource[Count].EndRange   = Index;
318             }
319             Count ++;
320           }
321 
322           LastIndex = Index;
323         }
324       }
325       break;
326 
327     case ACPI_IO_PORT_DESCRIPTOR:
328       Io = (EFI_ACPI_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader;
329       if (Io->Length != 0) {
330         if (IsaResource != NULL) {
331           IsaResource[Count].Type       = EfiIsaAcpiResourceIo;
332           IsaResource[Count].Attribute  = IsaIoAttribute (Io->Information);
333           IsaResource[Count].StartRange = Io->BaseAddressMin;
334           IsaResource[Count].EndRange   = Io->BaseAddressMin + Io->Length - 1;
335         }
336         Count ++;
337       }
338       break;
339 
340     case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR:
341       FixedIo = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader;
342       if (FixedIo->Length != 0) {
343         if (IsaResource != NULL) {
344           IsaResource[Count].Type       = EfiIsaAcpiResourceIo;
345           IsaResource[Count].Attribute  = EFI_ISA_ACPI_IO_DECODE_10_BITS;
346           IsaResource[Count].StartRange = FixedIo->BaseAddress;
347           IsaResource[Count].EndRange   = FixedIo->BaseAddress + FixedIo->Length - 1;
348         }
349         Count ++;
350       }
351       break;
352 
353     case ACPI_IRQ_DESCRIPTOR:
354     case ACPI_IRQ_NOFLAG_DESCRIPTOR:
355       Irq = (EFI_ACPI_IRQ_DESCRIPTOR *) AcpiResource.SmallHeader;
356       for (Index = 0; Index < sizeof (Irq->Mask) * 8; Index++) {
357         if (Irq->Mask & (1 << Index)) {
358           if ((Count > 0) && (LastIndex + 1 == Index)) {
359             if (IsaResource != NULL) {
360               IsaResource[Count - 1].EndRange ++;
361             }
362           } else {
363             if (IsaResource != NULL) {
364               IsaResource[Count].Type       = EfiIsaAcpiResourceInterrupt;
365               if (AcpiResource.SmallHeader->Byte == ACPI_IRQ_DESCRIPTOR) {
366                 IsaResource[Count].Attribute = IsaIrqAttribute (Irq->Information);
367               } else {
368                 IsaResource[Count].Attribute  = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE;
369               }
370               IsaResource[Count].StartRange = Index;
371               IsaResource[Count].EndRange   = Index;
372             }
373             Count++;
374           }
375 
376           LastIndex = Index;
377         }
378       }
379       break;
380 
381     case ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR:
382       Memory = (EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader;
383       if (Memory->Length != 0) {
384         if (IsaResource != NULL) {
385           IsaResource[Count].Type       = EfiIsaAcpiResourceMemory;
386           IsaResource[Count].Attribute  = IsaMemoryAttribute (Memory->Information);
387           IsaResource[Count].StartRange = Memory->BaseAddressMin;
388           IsaResource[Count].EndRange   = Memory->BaseAddressMin + Memory->Length - 1;
389         }
390         Count ++;
391       }
392       break;
393 
394     case ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR:
395       FixedMemory = (EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader;
396       if (FixedMemory->Length != 0) {
397         if (IsaResource != NULL) {
398           IsaResource[Count].Type       = EfiIsaAcpiResourceMemory;
399           IsaResource[Count].Attribute  = IsaMemoryAttribute (FixedMemory->Information);
400           IsaResource[Count].StartRange = FixedMemory->BaseAddress;
401           IsaResource[Count].EndRange   = FixedMemory->BaseAddress + FixedMemory->Length - 1;
402         }
403         Count ++;
404       }
405       break;
406 
407     case ACPI_END_TAG_DESCRIPTOR:
408       if (IsaResource != NULL) {
409         IsaResource[Count].Type       = EfiIsaAcpiResourceEndOfList;
410         IsaResource[Count].Attribute  = 0;
411         IsaResource[Count].StartRange = 0;
412         IsaResource[Count].EndRange   = 0;
413       }
414       Count ++;
415       break;
416   }
417 
418   return Count;
419 }
420 
421 /**
422   Initializes an ISA I/O Instance
423 
424   @param[in] IsaIoDevice            The isa device to be initialized.
425   @param[in] DevicePath             The device path of the isa device.
426   @param[in] Resources              The ACPI resource list.
427 
428 **/
429 VOID
InitializeIsaIoInstance(IN ISA_IO_DEVICE * IsaIoDevice,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,IN ACPI_RESOURCE_HEADER_PTR Resources)430 InitializeIsaIoInstance (
431   IN ISA_IO_DEVICE               *IsaIoDevice,
432   IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
433   IN ACPI_RESOURCE_HEADER_PTR    Resources
434   )
435 {
436   UINTN                                       Index;
437   ACPI_HID_DEVICE_PATH                        *AcpiNode;
438   ACPI_RESOURCE_HEADER_PTR                    ResourcePtr;
439 
440   //
441   // Use the ISA IO Protocol structure template to initialize the ISA IO instance
442   //
443   CopyMem (
444     &IsaIoDevice->IsaIo,
445     &mIsaIoInterface,
446     sizeof (EFI_ISA_IO_PROTOCOL)
447     );
448 
449   //
450   // Count the resources including the ACPI End Tag
451   //
452   ResourcePtr = Resources;
453   Index       = 0;
454   while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {
455 
456     Index += AcpiResourceToIsaResource (ResourcePtr, NULL);
457 
458     if (ResourcePtr.SmallHeader->Bits.Type == 0) {
459       ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader
460                               + ResourcePtr.SmallHeader->Bits.Length
461                               + sizeof (*ResourcePtr.SmallHeader));
462     } else {
463       ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader
464                               + ResourcePtr.LargeHeader->Length
465                               + sizeof (*ResourcePtr.LargeHeader));
466     }
467 
468   }
469   //
470   // Get the Isa Resource count for ACPI End Tag
471   //
472   Index += AcpiResourceToIsaResource (ResourcePtr, NULL);
473 
474   //
475   // Initialize the ResourceList
476   //
477   IsaIoDevice->IsaIo.ResourceList = AllocatePool (sizeof (EFI_ISA_ACPI_RESOURCE_LIST) + Index * sizeof (EFI_ISA_ACPI_RESOURCE));
478   ASSERT (IsaIoDevice->IsaIo.ResourceList != NULL);
479   IsaIoDevice->IsaIo.ResourceList->ResourceItem = (EFI_ISA_ACPI_RESOURCE *) (IsaIoDevice->IsaIo.ResourceList + 1);
480 
481   AcpiNode = (ACPI_HID_DEVICE_PATH *) ((UINT8 *) DevicePath + GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH - sizeof (ACPI_HID_DEVICE_PATH));
482   IsaIoDevice->IsaIo.ResourceList->Device.HID = AcpiNode->HID;
483   IsaIoDevice->IsaIo.ResourceList->Device.UID = AcpiNode->UID;
484 
485   ResourcePtr = Resources;
486   Index       = 0;
487   while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {
488 
489     Index += AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]);
490 
491     if (ResourcePtr.SmallHeader->Bits.Type == 0) {
492       ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader
493                               + ResourcePtr.SmallHeader->Bits.Length
494                               + sizeof (*ResourcePtr.SmallHeader));
495     } else {
496       ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader
497                               + ResourcePtr.LargeHeader->Length
498                               + sizeof (*ResourcePtr.LargeHeader));
499     }
500   }
501 
502   //
503   // Convert the ACPI End Tag
504   //
505   AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]);
506 }
507 
508 /**
509   Performs an ISA I/O Read Cycle
510 
511   @param[in]  This              A pointer to the EFI_ISA_IO_PROTOCOL instance.
512   @param[in]  Width             Specifies the width of the I/O operation.
513   @param[in]  Offset            The offset in ISA I/O space to start the I/O operation.
514   @param[in]  Count             The number of I/O operations to perform.
515   @param[out] Buffer            The destination buffer to store the results
516 
517   @retval EFI_SUCCESS           The data was read from the device sucessfully.
518   @retval EFI_UNSUPPORTED       The Offset is not valid for this device.
519   @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
520   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
521 **/
522 EFI_STATUS
523 EFIAPI
IsaIoIoRead(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINT32 Offset,IN UINTN Count,OUT VOID * Buffer)524 IsaIoIoRead (
525   IN  EFI_ISA_IO_PROTOCOL        *This,
526   IN  EFI_ISA_IO_PROTOCOL_WIDTH  Width,
527   IN  UINT32                     Offset,
528   IN  UINTN                      Count,
529   OUT VOID                       *Buffer
530   )
531 {
532   EFI_STATUS    Status;
533   ISA_IO_DEVICE *IsaIoDevice;
534 
535   IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
536 
537   //
538   // Verify Isa IO Access
539   //
540   Status = IsaIoVerifyAccess (
541              IsaIoDevice,
542              IsaAccessTypeIo,
543              Width,
544              Count,
545              Offset
546              );
547   if (EFI_ERROR (Status)) {
548     return Status;
549   }
550 
551   Status = IsaIoDevice->PciIo->Io.Read (
552                                     IsaIoDevice->PciIo,
553                                     (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
554                                     EFI_PCI_IO_PASS_THROUGH_BAR,
555                                     Offset,
556                                     Count,
557                                     Buffer
558                                     );
559 
560   if (EFI_ERROR (Status)) {
561     REPORT_STATUS_CODE (
562       EFI_ERROR_CODE | EFI_ERROR_MINOR,
563       EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
564       );
565   }
566 
567   return Status;
568 }
569 
570 /**
571   Performs an ISA I/O Write Cycle
572 
573   @param[in] This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
574   @param[in] Width               Specifies the width of the I/O operation.
575   @param[in] Offset              The offset in ISA I/O space to start the I/O operation.
576   @param[in] Count               The number of I/O operations to perform.
577   @param[in] Buffer              The source buffer to write data from
578 
579   @retval EFI_SUCCESS            The data was writen to the device sucessfully.
580   @retval EFI_UNSUPPORTED        The Offset is not valid for this device.
581   @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
582   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
583 **/
584 EFI_STATUS
585 EFIAPI
IsaIoIoWrite(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINT32 Offset,IN UINTN Count,IN VOID * Buffer)586 IsaIoIoWrite (
587   IN EFI_ISA_IO_PROTOCOL        *This,
588   IN EFI_ISA_IO_PROTOCOL_WIDTH  Width,
589   IN UINT32                     Offset,
590   IN UINTN                      Count,
591   IN VOID                       *Buffer
592   )
593 {
594   EFI_STATUS    Status;
595   ISA_IO_DEVICE *IsaIoDevice;
596 
597   IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
598 
599   //
600   // Verify Isa IO Access
601   //
602   Status = IsaIoVerifyAccess (
603              IsaIoDevice,
604              IsaAccessTypeIo,
605              Width,
606              Count,
607              Offset
608              );
609   if (EFI_ERROR (Status)) {
610     return Status;
611   }
612 
613   Status = IsaIoDevice->PciIo->Io.Write (
614                                     IsaIoDevice->PciIo,
615                                     (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
616                                     EFI_PCI_IO_PASS_THROUGH_BAR,
617                                     Offset,
618                                     Count,
619                                     Buffer
620                                     );
621 
622   if (EFI_ERROR (Status)) {
623     REPORT_STATUS_CODE (
624       EFI_ERROR_CODE | EFI_ERROR_MINOR,
625       EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
626       );
627   }
628 
629   return Status;
630 }
631 
632 /**
633   Writes an 8-bit I/O Port
634 
635   @param[in] This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
636   @param[in] Offset              The offset in ISA IO space to start the IO operation.
637   @param[in] Value               The data to write port.
638 
639   @retval EFI_SUCCESS            Success.
640   @retval EFI_INVALID_PARAMETER  Parameter is invalid.
641   @retval EFI_UNSUPPORTED        The address range specified by Offset is not valid.
642   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
643 **/
644 EFI_STATUS
WritePort(IN EFI_ISA_IO_PROTOCOL * This,IN UINT32 Offset,IN UINT8 Value)645 WritePort (
646   IN EFI_ISA_IO_PROTOCOL  *This,
647   IN UINT32               Offset,
648   IN UINT8                Value
649   )
650 {
651   EFI_STATUS    Status;
652   ISA_IO_DEVICE *IsaIoDevice;
653 
654   IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
655 
656   Status = IsaIoDevice->PciIo->Io.Write (
657                                     IsaIoDevice->PciIo,
658                                     EfiPciIoWidthUint8,
659                                     EFI_PCI_IO_PASS_THROUGH_BAR,
660                                     Offset,
661                                     1,
662                                     &Value
663                                     );
664   if (EFI_ERROR (Status)) {
665     REPORT_STATUS_CODE (
666       EFI_ERROR_CODE | EFI_ERROR_MINOR,
667       EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
668       );
669     return Status;
670   }
671 
672   //
673   // Wait for 50 microseconds to take affect.
674   //
675   gBS->Stall (50);
676 
677   return EFI_SUCCESS;
678 }
679 
680 /**
681   Writes I/O operation base address and count number to a 8 bit I/O Port.
682 
683   @param[in] This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
684   @param[in] AddrOffset          The address' offset.
685   @param[in] PageOffset          The page's offest.
686   @param[in] CountOffset         The count's offset.
687   @param[in] BaseAddress         The base address.
688   @param[in] Count               The number of I/O operations to perform.
689 
690   @retval EFI_SUCCESS            Success.
691   @retval EFI_INVALID_PARAMETER  Parameter is invalid.
692   @retval EFI_UNSUPPORTED        The address range specified by these Offsets and Count is not valid.
693   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
694 **/
695 EFI_STATUS
WriteDmaPort(IN EFI_ISA_IO_PROTOCOL * This,IN UINT32 AddrOffset,IN UINT32 PageOffset,IN UINT32 CountOffset,IN UINT32 BaseAddress,IN UINT16 Count)696 WriteDmaPort (
697   IN EFI_ISA_IO_PROTOCOL  *This,
698   IN UINT32               AddrOffset,
699   IN UINT32               PageOffset,
700   IN UINT32               CountOffset,
701   IN UINT32               BaseAddress,
702   IN UINT16               Count
703   )
704 {
705   EFI_STATUS  Status;
706 
707   Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff));
708   if (EFI_ERROR (Status)) {
709     return Status;
710   }
711 
712   Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff));
713   if (EFI_ERROR (Status)) {
714     return Status;
715   }
716 
717   Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff));
718   if (EFI_ERROR (Status)) {
719     return Status;
720   }
721 
722   Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff));
723   if (EFI_ERROR (Status)) {
724     return Status;
725   }
726 
727   Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff));
728   return Status;
729 }
730 
731 /**
732   Unmaps a memory region for DMA
733 
734   @param[in] This           A pointer to the EFI_ISA_IO_PROTOCOL instance.
735   @param[in] Mapping        The mapping value returned from EFI_ISA_IO.Map().
736 
737   @retval EFI_SUCCESS       The range was unmapped.
738   @retval EFI_DEVICE_ERROR  The data was not committed to the target system memory.
739 **/
740 EFI_STATUS
741 EFIAPI
IsaIoUnmap(IN EFI_ISA_IO_PROTOCOL * This,IN VOID * Mapping)742 IsaIoUnmap (
743   IN EFI_ISA_IO_PROTOCOL  *This,
744   IN VOID                 *Mapping
745   )
746 {
747   ISA_MAP_INFO  *IsaMapInfo;
748 
749   //
750   // Check if DMA is supported.
751   //
752   if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) {
753     return EFI_UNSUPPORTED;
754   }
755 
756   //
757   // See if the Map() operation associated with this Unmap() required a mapping
758   // buffer.If a mapping buffer was not required, then this function simply
759   // returns EFI_SUCCESS.
760   //
761   if (Mapping != NULL) {
762     //
763     // Get the MAP_INFO structure from Mapping
764     //
765     IsaMapInfo = (ISA_MAP_INFO *) Mapping;
766 
767     //
768     // If this is a write operation from the Agent's point of view,
769     // then copy the contents of the mapped buffer into the real buffer
770     // so the processor can read the contents of the real buffer.
771     //
772     if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) {
773       CopyMem (
774         (VOID *) (UINTN) IsaMapInfo->HostAddress,
775         (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
776         IsaMapInfo->NumberOfBytes
777         );
778     }
779     //
780     // Free the mapped buffer and the MAP_INFO structure.
781     //
782     gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages);
783     FreePool (IsaMapInfo);
784   }
785 
786   return EFI_SUCCESS;
787 }
788 
789 /**
790   Flushes any posted write data to the system memory.
791 
792   @param[in] This             A pointer to the EFI_ISA_IO_PROTOCOL instance.
793 
794   @retval  EFI_SUCCESS        The buffers were flushed.
795   @retval  EFI_DEVICE_ERROR   The buffers were not flushed due to a hardware error.
796 **/
797 EFI_STATUS
798 EFIAPI
IsaIoFlush(IN EFI_ISA_IO_PROTOCOL * This)799 IsaIoFlush (
800   IN EFI_ISA_IO_PROTOCOL  *This
801   )
802 {
803   EFI_STATUS    Status;
804   ISA_IO_DEVICE *IsaIoDevice;
805 
806   IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
807 
808   Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo);
809 
810   if (EFI_ERROR (Status)) {
811     REPORT_STATUS_CODE (
812       EFI_ERROR_CODE | EFI_ERROR_MINOR,
813       EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
814       );
815   }
816 
817   return Status;
818 }
819 
820 /**
821   Performs an ISA Memory Read Cycle
822 
823   @param[in]  This               A pointer to the EFI_ISA_IO_PROTOCOL instance.
824   @param[in]  Width              Specifies the width of the memory operation.
825   @param[in]  Offset             The offset in ISA memory space to start the memory operation.
826   @param[in]  Count              The number of memory operations to perform.
827   @param[out] Buffer             The destination buffer to store the results
828 
829   @retval EFI_SUCCESS            The data was read from the device successfully.
830   @retval EFI_UNSUPPORTED        The Offset is not valid for this device.
831   @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
832   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
833 **/
834 EFI_STATUS
835 EFIAPI
IsaIoMemRead(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINT32 Offset,IN UINTN Count,OUT VOID * Buffer)836 IsaIoMemRead (
837   IN  EFI_ISA_IO_PROTOCOL        *This,
838   IN  EFI_ISA_IO_PROTOCOL_WIDTH  Width,
839   IN  UINT32                     Offset,
840   IN  UINTN                      Count,
841   OUT VOID                       *Buffer
842   )
843 {
844   EFI_STATUS    Status;
845   ISA_IO_DEVICE *IsaIoDevice;
846 
847   //
848   // Check if ISA memory is supported.
849   //
850   if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
851     return EFI_UNSUPPORTED;
852   }
853 
854   IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
855 
856   //
857   // Verify the Isa Io Access
858   //
859   Status = IsaIoVerifyAccess (
860              IsaIoDevice,
861              IsaAccessTypeMem,
862              Width,
863              Count,
864              Offset
865              );
866   if (EFI_ERROR (Status)) {
867     return Status;
868   }
869 
870   Status = IsaIoDevice->PciIo->Mem.Read (
871                                      IsaIoDevice->PciIo,
872                                      (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
873                                      EFI_PCI_IO_PASS_THROUGH_BAR,
874                                      Offset,
875                                      Count,
876                                      Buffer
877                                      );
878 
879   if (EFI_ERROR (Status)) {
880     REPORT_STATUS_CODE (
881       EFI_ERROR_CODE | EFI_ERROR_MINOR,
882       EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
883       );
884   }
885 
886   return Status;
887 }
888 
889 /**
890   Performs an ISA Memory Write Cycle
891 
892   @param[in] This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
893   @param[in] Width               Specifies the width of the memory operation.
894   @param[in] Offset              The offset in ISA memory space to start the memory operation.
895   @param[in] Count               The number of memory operations to perform.
896   @param[in] Buffer              The source buffer to write data from
897 
898   @retval EFI_SUCCESS            The data was written to the device sucessfully.
899   @retval EFI_UNSUPPORTED        The Offset is not valid for this device.
900   @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
901   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
902 **/
903 EFI_STATUS
904 EFIAPI
IsaIoMemWrite(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINT32 Offset,IN UINTN Count,IN VOID * Buffer)905 IsaIoMemWrite (
906   IN EFI_ISA_IO_PROTOCOL        *This,
907   IN EFI_ISA_IO_PROTOCOL_WIDTH  Width,
908   IN UINT32                     Offset,
909   IN UINTN                      Count,
910   IN VOID                       *Buffer
911   )
912 {
913   EFI_STATUS    Status;
914   ISA_IO_DEVICE *IsaIoDevice;
915 
916   //
917   // Check if ISA memory is supported.
918   //
919   if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
920     return EFI_UNSUPPORTED;
921   }
922 
923   IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
924 
925   //
926   // Verify Isa IO Access
927   //
928   Status = IsaIoVerifyAccess (
929              IsaIoDevice,
930              IsaAccessTypeMem,
931              Width,
932              Count,
933              Offset
934              );
935   if (EFI_ERROR (Status)) {
936     return Status;
937   }
938 
939   Status = IsaIoDevice->PciIo->Mem.Write (
940                                      IsaIoDevice->PciIo,
941                                      (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
942                                      EFI_PCI_IO_PASS_THROUGH_BAR,
943                                      Offset,
944                                      Count,
945                                      Buffer
946                                      );
947 
948   if (EFI_ERROR (Status)) {
949     REPORT_STATUS_CODE (
950       EFI_ERROR_CODE | EFI_ERROR_MINOR,
951       EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
952       );
953   }
954 
955   return Status;
956 }
957 
958 /**
959   Copy one region of ISA memory space to another region of ISA memory space on the ISA controller.
960 
961   @param[in]  This               A pointer to the EFI_ISA_IO_PROTOCOL instance.
962   @param[in]  Width              Specifies the width of the memory copy operation.
963   @param[in]  DestOffset         The offset of the destination
964   @param[in]  SrcOffset          The offset of the source
965   @param[in]  Count              The number of memory copy  operations to perform
966 
967   @retval EFI_SUCCESS            The data was copied sucessfully.
968   @retval EFI_UNSUPPORTED        The DestOffset or SrcOffset is not valid for this device.
969   @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
970   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
971 **/
972 EFI_STATUS
973 EFIAPI
IsaIoCopyMem(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINT32 DestOffset,IN UINT32 SrcOffset,IN UINTN Count)974 IsaIoCopyMem (
975   IN EFI_ISA_IO_PROTOCOL        *This,
976   IN EFI_ISA_IO_PROTOCOL_WIDTH  Width,
977   IN UINT32                     DestOffset,
978   IN UINT32                     SrcOffset,
979   IN UINTN                      Count
980   )
981 {
982   EFI_STATUS    Status;
983   ISA_IO_DEVICE *IsaIoDevice;
984 
985   //
986   // Check if ISA memory is supported.
987   //
988   if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
989     return EFI_UNSUPPORTED;
990   }
991 
992   IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
993 
994   //
995   // Verify Isa IO Access for destination and source
996   //
997   Status = IsaIoVerifyAccess (
998              IsaIoDevice,
999              IsaAccessTypeMem,
1000              Width,
1001              Count,
1002              DestOffset
1003              );
1004   if (EFI_ERROR (Status)) {
1005     return Status;
1006   }
1007 
1008   Status = IsaIoVerifyAccess (
1009              IsaIoDevice,
1010              IsaAccessTypeMem,
1011              Width,
1012              Count,
1013              SrcOffset
1014              );
1015   if (EFI_ERROR (Status)) {
1016     return Status;
1017   }
1018 
1019   Status = IsaIoDevice->PciIo->CopyMem (
1020                                  IsaIoDevice->PciIo,
1021                                  (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
1022                                  EFI_PCI_IO_PASS_THROUGH_BAR,
1023                                  DestOffset,
1024                                  EFI_PCI_IO_PASS_THROUGH_BAR,
1025                                  SrcOffset,
1026                                  Count
1027                                  );
1028 
1029   if (EFI_ERROR (Status)) {
1030     REPORT_STATUS_CODE (
1031       EFI_ERROR_CODE | EFI_ERROR_MINOR,
1032       EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
1033       );
1034   }
1035 
1036   return Status;
1037 }
1038 
1039 /**
1040   Maps a memory region for DMA, note this implementation
1041   only supports slave read/write operation to save code size.
1042 
1043   @param This                    A pointer to the EFI_ISA_IO_PROTOCOL instance.
1044   @param Operation               Indicates the type of DMA (slave or bus master), and if
1045                                  the DMA operation is going to read or write to system memory.
1046   @param ChannelNumber           The slave channel number to use for this DMA operation.
1047                                  If Operation and ChannelAttributes shows that this device
1048                                  performs bus mastering DMA, then this field is ignored.
1049                                  The legal range for this field is 0..7.
1050   @param ChannelAttributes       The attributes of the DMA channel to use for this DMA operation
1051   @param HostAddress             The system memory address to map to the device.
1052   @param NumberOfBytes           On input the number of bytes to map.  On output the number
1053                                  of bytes that were mapped.
1054   @param DeviceAddress           The resulting map address for the bus master device to use
1055                                  to access the hosts HostAddress.
1056   @param Mapping                 A resulting value to pass to EFI_ISA_IO.Unmap().
1057 
1058   @retval EFI_SUCCESS            The range was mapped for the returned NumberOfBytes.
1059   @retval EFI_INVALID_PARAMETER  The Operation or HostAddress is undefined.
1060   @retval EFI_UNSUPPORTED        The HostAddress can not be mapped as a common buffer.
1061   @retval EFI_DEVICE_ERROR       The system hardware could not map the requested address.
1062   @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
1063 **/
1064 EFI_STATUS
IsaIoMapOnlySupportSlaveReadWrite(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,IN UINT8 ChannelNumber OPTIONAL,IN UINT32 ChannelAttributes,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)1065 IsaIoMapOnlySupportSlaveReadWrite (
1066   IN     EFI_ISA_IO_PROTOCOL            *This,
1067   IN     EFI_ISA_IO_PROTOCOL_OPERATION  Operation,
1068   IN     UINT8                          ChannelNumber  OPTIONAL,
1069   IN     UINT32                         ChannelAttributes,
1070   IN     VOID                           *HostAddress,
1071   IN OUT UINTN                          *NumberOfBytes,
1072   OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
1073   OUT    VOID                           **Mapping
1074   )
1075 {
1076   EFI_STATUS            Status;
1077   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
1078   ISA_MAP_INFO          *IsaMapInfo;
1079   UINT8                 DmaMode;
1080   UINTN                 MaxNumberOfBytes;
1081   UINT32                BaseAddress;
1082   UINT16                Count;
1083   UINT8                 DmaMask;
1084   UINT8                 DmaClear;
1085   UINT8                 DmaChannelMode;
1086 
1087   if ((NULL == This) ||
1088       (NULL == HostAddress) ||
1089       (NULL == NumberOfBytes) ||
1090       (NULL == DeviceAddress) ||
1091       (NULL == Mapping)
1092       ) {
1093     return EFI_INVALID_PARAMETER;
1094   }
1095 
1096   //
1097   // Initialize the return values to their defaults
1098   //
1099   *Mapping = NULL;
1100 
1101   //
1102   // Make sure the Operation parameter is valid.
1103   // Light IsaIo only supports two operations.
1104   //
1105   if (!(Operation == EfiIsaIoOperationSlaveRead ||
1106         Operation == EfiIsaIoOperationSlaveWrite)) {
1107     return EFI_INVALID_PARAMETER;
1108   }
1109 
1110   if (ChannelNumber >= 4) {
1111     //
1112     // The Light IsaIo doesn't support channelNumber larger than 4.
1113     //
1114     return EFI_INVALID_PARAMETER;
1115   }
1116 
1117   //
1118   // Map the HostAddress to a DeviceAddress.
1119   //
1120   PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1121   if ((PhysicalAddress + *NumberOfBytes) > BASE_16MB) {
1122     //
1123     // Common Buffer operations can not be remapped.  If the common buffer
1124     // is above 16MB, then it is not possible to generate a mapping, so return
1125     // an error.
1126     //
1127     if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {
1128       return EFI_UNSUPPORTED;
1129     }
1130     //
1131     // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1132     // is called later.
1133     //
1134     IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));
1135     if (IsaMapInfo == NULL) {
1136       *NumberOfBytes = 0;
1137       return EFI_OUT_OF_RESOURCES;
1138     }
1139     //
1140     // Return a pointer to the MAP_INFO structure in Mapping
1141     //
1142     *Mapping = IsaMapInfo;
1143 
1144     //
1145     // Initialize the MAP_INFO structure
1146     //
1147     IsaMapInfo->Operation         = Operation;
1148     IsaMapInfo->NumberOfBytes     = *NumberOfBytes;
1149     IsaMapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES (*NumberOfBytes);
1150     IsaMapInfo->HostAddress       = PhysicalAddress;
1151     IsaMapInfo->MappedHostAddress = BASE_16MB - 1;
1152 
1153     //
1154     // Allocate a buffer below 16MB to map the transfer to.
1155     //
1156     Status = gBS->AllocatePages (
1157                     AllocateMaxAddress,
1158                     EfiBootServicesData,
1159                     IsaMapInfo->NumberOfPages,
1160                     &IsaMapInfo->MappedHostAddress
1161                     );
1162     if (EFI_ERROR (Status)) {
1163       FreePool (IsaMapInfo);
1164       *NumberOfBytes  = 0;
1165       *Mapping        = NULL;
1166       return Status;
1167     }
1168     //
1169     // If this is a read operation from the DMA agents's point of view,
1170     // then copy the contents of the real buffer into the mapped buffer
1171     // so the DMA agent can read the contents of the real buffer.
1172     //
1173     if (Operation == EfiIsaIoOperationSlaveRead) {
1174       CopyMem (
1175         (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
1176         (VOID *) (UINTN) IsaMapInfo->HostAddress,
1177         IsaMapInfo->NumberOfBytes
1178         );
1179     }
1180     //
1181     // The DeviceAddress is the address of the maped buffer below 16 MB
1182     //
1183     *DeviceAddress = IsaMapInfo->MappedHostAddress;
1184   } else {
1185     //
1186     // The transfer is below 16 MB, so the DeviceAddress is simply the
1187     // HostAddress
1188     //
1189     *DeviceAddress = PhysicalAddress;
1190   }
1191 
1192   //
1193   // Figure out what to program into the DMA Channel Mode Register
1194   //
1195   DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));
1196   if (Operation == EfiIsaIoOperationSlaveRead) {
1197     DmaMode |= V_8237_DMA_CHMODE_MEM2IO;
1198   } else {
1199     DmaMode |= V_8237_DMA_CHMODE_IO2MEM;
1200   }
1201   //
1202   // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
1203   //
1204   DmaMode |= V_8237_DMA_CHMODE_SINGLE;
1205 
1206   //
1207   // A Slave DMA transfer can not cross a 64K boundary.
1208   // Compute *NumberOfBytes based on this restriction.
1209   //
1210   MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);
1211   if (*NumberOfBytes > MaxNumberOfBytes) {
1212     *NumberOfBytes = MaxNumberOfBytes;
1213   }
1214   //
1215   // Compute the values to program into the BaseAddress and Count registers
1216   // of the Slave DMA controller
1217   //
1218   BaseAddress = (UINT32) (*DeviceAddress);
1219   Count       = (UINT16) (*NumberOfBytes - 1);
1220   //
1221   // Program the DMA Write Single Mask Register for ChannelNumber
1222   // Clear the DMA Byte Pointer Register
1223   //
1224   DmaMask         = R_8237_DMA_WRSMSK_CH0_3;
1225   DmaClear        = R_8237_DMA_CBPR_CH0_3;
1226   DmaChannelMode  = R_8237_DMA_CHMODE_CH0_3;
1227 
1228   Status = WritePort (
1229              This,
1230              DmaMask,
1231              (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1232              );
1233   if (EFI_ERROR (Status)) {
1234     return Status;
1235   }
1236 
1237   Status = WritePort (
1238              This,
1239              DmaClear,
1240              (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1241              );
1242   if (EFI_ERROR (Status)) {
1243     return Status;
1244   }
1245 
1246   Status = WritePort (This, DmaChannelMode, DmaMode);
1247   if (EFI_ERROR (Status)) {
1248     return Status;
1249   }
1250 
1251   Status = WriteDmaPort (
1252              This,
1253              mDmaRegisters[ChannelNumber].Address,
1254              mDmaRegisters[ChannelNumber].Page,
1255              mDmaRegisters[ChannelNumber].Count,
1256              BaseAddress,
1257              Count
1258              );
1259   if (EFI_ERROR (Status)) {
1260     return Status;
1261   }
1262 
1263   Status = WritePort (
1264              This,
1265              DmaMask,
1266              (UINT8) (ChannelNumber & 0x03)
1267              );
1268   if (EFI_ERROR (Status)) {
1269     return Status;
1270   }
1271 
1272   return EFI_SUCCESS;
1273 }
1274 
1275 /**
1276   Maps a memory region for DMA. This implementation implement the
1277   the full mapping support.
1278 
1279   @param This                    A pointer to the EFI_ISA_IO_PROTOCOL instance.
1280   @param Operation               Indicates the type of DMA (slave or bus master), and if
1281                                  the DMA operation is going to read or write to system memory.
1282   @param ChannelNumber           The slave channel number to use for this DMA operation.
1283                                  If Operation and ChannelAttributes shows that this device
1284                                  performs bus mastering DMA, then this field is ignored.
1285                                  The legal range for this field is 0..7.
1286   @param ChannelAttributes       The attributes of the DMA channel to use for this DMA operation
1287   @param HostAddress             The system memory address to map to the device.
1288   @param NumberOfBytes           On input the number of bytes to map.  On output the number
1289                                  of bytes that were mapped.
1290   @param DeviceAddress           The resulting map address for the bus master device to use
1291                                  to access the hosts HostAddress.
1292   @param Mapping                 A resulting value to pass to EFI_ISA_IO.Unmap().
1293 
1294   @retval EFI_SUCCESS           - The range was mapped for the returned NumberOfBytes.
1295   @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1296   @retval EFI_UNSUPPORTED       - The HostAddress can not be mapped as a common buffer.
1297   @retval EFI_DEVICE_ERROR      - The system hardware could not map the requested address.
1298   @retval EFI_OUT_OF_RESOURCES  - The memory pages could not be allocated.
1299 **/
1300 EFI_STATUS
IsaIoMapFullSupport(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,IN UINT8 ChannelNumber OPTIONAL,IN UINT32 ChannelAttributes,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)1301 IsaIoMapFullSupport (
1302   IN     EFI_ISA_IO_PROTOCOL                                  *This,
1303   IN     EFI_ISA_IO_PROTOCOL_OPERATION                        Operation,
1304   IN     UINT8                                                ChannelNumber         OPTIONAL,
1305   IN     UINT32                                               ChannelAttributes,
1306   IN     VOID                                                 *HostAddress,
1307   IN OUT UINTN                                                *NumberOfBytes,
1308   OUT    EFI_PHYSICAL_ADDRESS                                 *DeviceAddress,
1309   OUT    VOID                                                 **Mapping
1310   )
1311 {
1312   EFI_STATUS            Status;
1313   BOOLEAN               Master;
1314   BOOLEAN               Read;
1315   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
1316   ISA_MAP_INFO          *IsaMapInfo;
1317   UINT8                 DmaMode;
1318   UINTN                 MaxNumberOfBytes;
1319   UINT32                BaseAddress;
1320   UINT16                Count;
1321   UINT8                 DmaMask;
1322   UINT8                 DmaClear;
1323   UINT8                 DmaChannelMode;
1324 
1325   if ((NULL == This) ||
1326       (NULL == HostAddress) ||
1327       (NULL == NumberOfBytes) ||
1328       (NULL == DeviceAddress) ||
1329       (NULL == Mapping)
1330       ) {
1331     return EFI_INVALID_PARAMETER;
1332   }
1333 
1334   //
1335   // Initialize the return values to their defaults
1336   //
1337   *Mapping = NULL;
1338 
1339   //
1340   // Make sure the Operation parameter is valid
1341   //
1342   if ((UINT32)Operation >= EfiIsaIoOperationMaximum) {
1343     return EFI_INVALID_PARAMETER;
1344   }
1345 
1346   if (ChannelNumber >= 8) {
1347     return EFI_INVALID_PARAMETER;
1348   }
1349 
1350   //
1351   // See if this is a Slave DMA Operation
1352   //
1353   Master  = TRUE;
1354   Read    = FALSE;
1355   if (Operation == EfiIsaIoOperationSlaveRead) {
1356     Operation = EfiIsaIoOperationBusMasterRead;
1357     Master    = FALSE;
1358     Read      = TRUE;
1359   }
1360 
1361   if (Operation == EfiIsaIoOperationSlaveWrite) {
1362     Operation = EfiIsaIoOperationBusMasterWrite;
1363     Master    = FALSE;
1364     Read      = FALSE;
1365   }
1366 
1367   if (!Master) {
1368     //
1369     // Make sure that ChannelNumber is a valid channel number
1370     // Channel 4 is used to cascade, so it is illegal.
1371     //
1372     if (ChannelNumber == 4 || ChannelNumber > 7) {
1373       return EFI_INVALID_PARAMETER;
1374     }
1375     //
1376     // This implementation only support COMPATIBLE DMA Transfers
1377     //
1378     if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE) == 0) {
1379       return EFI_INVALID_PARAMETER;
1380     }
1381 
1382     if ((ChannelAttributes &
1383          (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A |
1384           EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B |
1385           EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C)) != 0) {
1386       return EFI_INVALID_PARAMETER;
1387     }
1388 
1389     if (ChannelNumber < 4) {
1390       //
1391       // If this is Channel 0..3, then the width must be 8 bit
1392       //
1393       if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) == 0) ||
1394           ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) != 0)
1395           ) {
1396         return EFI_INVALID_PARAMETER;
1397       }
1398     } else {
1399       //
1400       // If this is Channel 4..7, then the width must be 16 bit
1401       //
1402       if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) != 0) ||
1403           ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) == 0)) {
1404         return EFI_INVALID_PARAMETER;
1405       }
1406     }
1407     //
1408     // Either Demand Mode or Single Mode must be selected, but not both
1409     //
1410     if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) {
1411       if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) {
1412         return EFI_INVALID_PARAMETER;
1413       }
1414     } else {
1415       if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) == 0) {
1416         return EFI_INVALID_PARAMETER;
1417       }
1418     }
1419   }
1420   //
1421   // Map the HostAddress to a DeviceAddress.
1422   //
1423   PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1424   if ((PhysicalAddress +*NumberOfBytes) > BASE_16MB) {
1425     //
1426     // Common Buffer operations can not be remapped.  If the common buffer
1427     // is above 16MB, then it is not possible to generate a mapping, so return
1428     // an error.
1429     //
1430     if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {
1431       return EFI_UNSUPPORTED;
1432     }
1433     //
1434     // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1435     // is called later.
1436     //
1437     IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));
1438     if (IsaMapInfo == NULL) {
1439       *NumberOfBytes = 0;
1440       return EFI_OUT_OF_RESOURCES;
1441     }
1442     //
1443     // Return a pointer to the MAP_INFO structure in Mapping
1444     //
1445     *Mapping = IsaMapInfo;
1446 
1447     //
1448     // Initialize the MAP_INFO structure
1449     //
1450     IsaMapInfo->Operation         = Operation;
1451     IsaMapInfo->NumberOfBytes     = *NumberOfBytes;
1452     IsaMapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES (*NumberOfBytes);
1453     IsaMapInfo->HostAddress       = PhysicalAddress;
1454     IsaMapInfo->MappedHostAddress = BASE_16MB - 1;
1455 
1456     //
1457     // Allocate a buffer below 16MB to map the transfer to.
1458     //
1459     Status = gBS->AllocatePages (
1460                     AllocateMaxAddress,
1461                     EfiBootServicesData,
1462                     IsaMapInfo->NumberOfPages,
1463                     &IsaMapInfo->MappedHostAddress
1464                     );
1465     if (EFI_ERROR (Status)) {
1466       FreePool (IsaMapInfo);
1467       *NumberOfBytes  = 0;
1468       *Mapping        = NULL;
1469       return Status;
1470     }
1471     //
1472     // If this is a read operation from the DMA agents's point of view,
1473     // then copy the contents of the real buffer into the mapped buffer
1474     // so the DMA agent can read the contents of the real buffer.
1475     //
1476     if (Operation == EfiIsaIoOperationBusMasterRead) {
1477       CopyMem (
1478         (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
1479         (VOID *) (UINTN) IsaMapInfo->HostAddress,
1480         IsaMapInfo->NumberOfBytes
1481         );
1482     }
1483     //
1484     // The DeviceAddress is the address of the maped buffer below 16 MB
1485     //
1486     *DeviceAddress = IsaMapInfo->MappedHostAddress;
1487   } else {
1488     //
1489     // The transfer is below 16 MB, so the DeviceAddress is simply the
1490     // HostAddress
1491     //
1492     *DeviceAddress = PhysicalAddress;
1493   }
1494   //
1495   // If this is a Bus Master operation then return
1496   //
1497   if (Master) {
1498     return EFI_SUCCESS;
1499   }
1500   //
1501   // Figure out what to program into the DMA Channel Mode Register
1502   //
1503   DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));
1504   if (Read) {
1505     DmaMode |= V_8237_DMA_CHMODE_MEM2IO;
1506   } else {
1507     DmaMode |= V_8237_DMA_CHMODE_IO2MEM;
1508   }
1509 
1510   if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) != 0) {
1511     DmaMode |= B_8237_DMA_CHMODE_AE;
1512   }
1513 
1514   if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) {
1515     DmaMode |= V_8237_DMA_CHMODE_DEMAND;
1516   }
1517 
1518   if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) {
1519     DmaMode |= V_8237_DMA_CHMODE_SINGLE;
1520   }
1521   //
1522   // A Slave DMA transfer can not cross a 64K boundary.
1523   // Compute *NumberOfBytes based on this restriction.
1524   //
1525   MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);
1526   if (*NumberOfBytes > MaxNumberOfBytes) {
1527     *NumberOfBytes = MaxNumberOfBytes;
1528   }
1529   //
1530   // Compute the values to program into the BaseAddress and Count registers
1531   // of the Slave DMA controller
1532   //
1533   if (ChannelNumber < 4) {
1534     BaseAddress = (UINT32) (*DeviceAddress);
1535     Count       = (UINT16) (*NumberOfBytes - 1);
1536   } else {
1537     BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1));
1538     Count       = (UINT16) ((*NumberOfBytes - 1) >> 1);
1539   }
1540   //
1541   // Program the DMA Write Single Mask Register for ChannelNumber
1542   // Clear the DMA Byte Pointer Register
1543   //
1544   if (ChannelNumber < 4) {
1545     DmaMask         = R_8237_DMA_WRSMSK_CH0_3;
1546     DmaClear        = R_8237_DMA_CBPR_CH0_3;
1547     DmaChannelMode  = R_8237_DMA_CHMODE_CH0_3;
1548   } else {
1549     DmaMask         = R_8237_DMA_WRSMSK_CH4_7;
1550     DmaClear        = R_8237_DMA_CBPR_CH4_7;
1551     DmaChannelMode  = R_8237_DMA_CHMODE_CH4_7;
1552   }
1553 
1554   Status = WritePort (
1555              This,
1556              DmaMask,
1557              (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1558              );
1559   if (EFI_ERROR (Status)) {
1560     return Status;
1561   }
1562 
1563   Status = WritePort (
1564              This,
1565              DmaClear,
1566              (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1567              );
1568   if (EFI_ERROR (Status)) {
1569     return Status;
1570   }
1571 
1572   Status = WritePort (This, DmaChannelMode, DmaMode);
1573   if (EFI_ERROR (Status)) {
1574     return Status;
1575   }
1576 
1577   Status = WriteDmaPort (
1578              This,
1579              mDmaRegisters[ChannelNumber].Address,
1580              mDmaRegisters[ChannelNumber].Page,
1581              mDmaRegisters[ChannelNumber].Count,
1582              BaseAddress,
1583              Count
1584              );
1585   if (EFI_ERROR (Status)) {
1586     return Status;
1587   }
1588 
1589   Status = WritePort (
1590              This,
1591              DmaMask,
1592              (UINT8) (ChannelNumber & 0x03)
1593              );
1594   if (EFI_ERROR (Status)) {
1595     return Status;
1596   }
1597 
1598   return EFI_SUCCESS;
1599 }
1600 
1601 /**
1602   Maps a memory region for DMA
1603 
1604   @param This                    A pointer to the EFI_ISA_IO_PROTOCOL instance.
1605   @param Operation               Indicates the type of DMA (slave or bus master), and if
1606                                  the DMA operation is going to read or write to system memory.
1607   @param ChannelNumber           The slave channel number to use for this DMA operation.
1608                                  If Operation and ChannelAttributes shows that this device
1609                                  performs bus mastering DMA, then this field is ignored.
1610                                  The legal range for this field is 0..7.
1611   @param ChannelAttributes       The attributes of the DMA channel to use for this DMA operation
1612   @param HostAddress             The system memory address to map to the device.
1613   @param NumberOfBytes           On input the number of bytes to map.  On output the number
1614                                  of bytes that were mapped.
1615   @param DeviceAddress           The resulting map address for the bus master device to use
1616                                  to access the hosts HostAddress.
1617   @param Mapping                 A resulting value to pass to EFI_ISA_IO.Unmap().
1618 
1619   @retval EFI_SUCCESS            The range was mapped for the returned NumberOfBytes.
1620   @retval EFI_INVALID_PARAMETER  The Operation or HostAddress is undefined.
1621   @retval EFI_UNSUPPORTED        The HostAddress can not be mapped as a common buffer.
1622   @retval EFI_DEVICE_ERROR       The system hardware could not map the requested address.
1623   @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
1624 **/
1625 EFI_STATUS
1626 EFIAPI
IsaIoMap(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,IN UINT8 ChannelNumber OPTIONAL,IN UINT32 ChannelAttributes,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)1627 IsaIoMap (
1628   IN     EFI_ISA_IO_PROTOCOL            *This,
1629   IN     EFI_ISA_IO_PROTOCOL_OPERATION  Operation,
1630   IN     UINT8                          ChannelNumber  OPTIONAL,
1631   IN     UINT32                         ChannelAttributes,
1632   IN     VOID                           *HostAddress,
1633   IN OUT UINTN                          *NumberOfBytes,
1634   OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
1635   OUT    VOID                           **Mapping
1636   )
1637 {
1638   //
1639   // Check if DMA is supported.
1640   //
1641   if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) {
1642     return EFI_UNSUPPORTED;
1643   }
1644   //
1645   // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1646   // ISA Bus Master.
1647   //
1648   // So we just return EFI_UNSUPPORTED for these functions.
1649   //
1650   if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) {
1651     return IsaIoMapOnlySupportSlaveReadWrite (
1652              This,
1653              Operation,
1654              ChannelNumber,
1655              ChannelAttributes,
1656              HostAddress,
1657              NumberOfBytes,
1658              DeviceAddress,
1659              Mapping
1660              );
1661 
1662   } else {
1663     return IsaIoMapFullSupport (
1664              This,
1665              Operation,
1666              ChannelNumber,
1667              ChannelAttributes,
1668              HostAddress,
1669              NumberOfBytes,
1670              DeviceAddress,
1671              Mapping
1672              );
1673   }
1674 }
1675 
1676 /**
1677   Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping.
1678 
1679   @param[in]  This               A pointer to the EFI_ISA_IO_PROTOCOL instance.
1680   @param[in]  Type               The type allocation to perform.
1681   @param[in]  MemoryType         The type of memory to allocate.
1682   @param[in]  Pages              The number of pages to allocate.
1683   @param[out] HostAddress        A pointer to store the base address of the allocated range.
1684   @param[in]  Attributes         The requested bit mask of attributes for the allocated range.
1685 
1686   @retval EFI_SUCCESS            The requested memory pages were allocated.
1687   @retval EFI_INVALID_PARAMETER  Type is invalid or MemoryType is invalid or HostAddress is NULL
1688   @retval EFI_UNSUPPORTED        Attributes is unsupported or the memory range specified
1689                                  by HostAddress, Pages, and Type is not available for common buffer use.
1690   @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
1691 **/
1692 EFI_STATUS
1693 EFIAPI
IsaIoAllocateBuffer(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,OUT VOID ** HostAddress,IN UINT64 Attributes)1694 IsaIoAllocateBuffer (
1695   IN  EFI_ISA_IO_PROTOCOL  *This,
1696   IN  EFI_ALLOCATE_TYPE    Type,
1697   IN  EFI_MEMORY_TYPE      MemoryType,
1698   IN  UINTN                Pages,
1699   OUT VOID                 **HostAddress,
1700   IN  UINT64               Attributes
1701   )
1702 {
1703   EFI_STATUS            Status;
1704   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
1705 
1706   //
1707   // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1708   // ISA Bus Master.
1709   // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1710   //
1711   if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) ||
1712       ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) {
1713     return EFI_UNSUPPORTED;
1714   }
1715 
1716   if (HostAddress == NULL) {
1717     return EFI_INVALID_PARAMETER;
1718   }
1719 
1720   if ((UINT32)Type >= MaxAllocateType) {
1721     return EFI_INVALID_PARAMETER;
1722   }
1723   //
1724   // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1725   //
1726   if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
1727     return EFI_INVALID_PARAMETER;
1728   }
1729 
1730   if ((Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) != 0) {
1731     return EFI_UNSUPPORTED;
1732   }
1733 
1734   PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (BASE_16MB - 1);
1735   if (Type == AllocateAddress) {
1736     if ((UINTN) (*HostAddress) >= BASE_16MB) {
1737       return EFI_UNSUPPORTED;
1738     } else {
1739       PhysicalAddress = (UINTN) (*HostAddress);
1740     }
1741   }
1742 
1743   if (Type == AllocateAnyPages) {
1744     Type = AllocateMaxAddress;
1745   }
1746 
1747   Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress);
1748   if (EFI_ERROR (Status)) {
1749     REPORT_STATUS_CODE (
1750       EFI_ERROR_CODE | EFI_ERROR_MINOR,
1751       EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
1752       );
1753     return Status;
1754   }
1755 
1756   *HostAddress = (VOID *) (UINTN) PhysicalAddress;
1757   return Status;
1758 }
1759 
1760 /**
1761   Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer().
1762 
1763   @param[in] This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
1764   @param[in] Pages               The number of pages to free.
1765   @param[in] HostAddress         The base address of the allocated range.
1766 
1767   @retval EFI_SUCCESS            The requested memory pages were freed.
1768   @retval EFI_INVALID_PARAMETER  The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1769 **/
1770 EFI_STATUS
1771 EFIAPI
IsaIoFreeBuffer(IN EFI_ISA_IO_PROTOCOL * This,IN UINTN Pages,IN VOID * HostAddress)1772 IsaIoFreeBuffer (
1773   IN EFI_ISA_IO_PROTOCOL  *This,
1774   IN UINTN                Pages,
1775   IN VOID                 *HostAddress
1776   )
1777 {
1778   EFI_STATUS  Status;
1779 
1780   //
1781   // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1782   // ISA Bus Master.
1783   // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1784   //
1785   if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) ||
1786       ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) {
1787     return EFI_UNSUPPORTED;
1788   }
1789 
1790   Status = gBS->FreePages (
1791                   (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,
1792                   Pages
1793                   );
1794   if (EFI_ERROR (Status)) {
1795     REPORT_STATUS_CODE (
1796       EFI_ERROR_CODE | EFI_ERROR_MINOR,
1797       EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
1798       );
1799   }
1800 
1801   return Status;
1802 }
1803 
1804