2 The implementation for EFI_ISA_IO_PROTOCOL.
4 Copyright (c) 2010, 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
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.
20 EFI_ISA_IO_PROTOCOL mIsaIoInterface
= {
40 EFI_ISA_DMA_REGISTERS mDmaRegisters
[8] = {
65 }, // Channel 4 is invalid
84 Verifies access to an ISA device
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.
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.
98 IN ISA_IO_DEVICE
*IsaIoDevice
,
99 IN ISA_ACCESS_TYPE Type
,
100 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
105 EFI_ISA_ACPI_RESOURCE
*Item
;
108 if (Width
< EfiIsaIoWidthUint8
||
109 Width
>= EfiIsaIoWidthMaximum
||
110 Width
== EfiIsaIoWidthReserved
||
111 Width
== EfiIsaIoWidthFifoReserved
||
112 Width
== EfiIsaIoWidthFillReserved
114 return EFI_INVALID_PARAMETER
;
118 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
119 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
121 if (Width
>= EfiIsaIoWidthFifoUint8
&& Width
< EfiIsaIoWidthFifoReserved
) {
125 Width
= (EFI_ISA_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
127 Status
= EFI_UNSUPPORTED
;
128 Item
= IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
;
129 while (Item
->Type
!= EfiIsaAcpiResourceEndOfList
) {
130 if ((Type
== IsaAccessTypeMem
&& Item
->Type
== EfiIsaAcpiResourceMemory
) ||
131 (Type
== IsaAccessTypeIo
&& Item
->Type
== EfiIsaAcpiResourceIo
)) {
132 if (Offset
>= Item
->StartRange
&& (Offset
+ Count
* (UINT32
)(1 << Width
)) - 1 <= Item
->EndRange
) {
136 if (Offset
>= Item
->StartRange
&& Offset
<= Item
->EndRange
) {
137 Status
= EFI_INVALID_PARAMETER
;
148 Convert the IO Information in ACPI descriptor to IO ISA Attribute.
150 @param[in] Information The IO Information in ACPI descriptor
152 @return UINT32 The IO ISA Attribute
163 switch (Information
& EFI_ACPI_IO_DECODE_MASK
) {
164 case EFI_ACPI_IO_DECODE_16_BIT
:
165 Attribute
|= EFI_ISA_ACPI_IO_DECODE_16_BITS
;
168 case EFI_ACPI_IO_DECODE_10_BIT
:
169 Attribute
|= EFI_ISA_ACPI_IO_DECODE_10_BITS
;
177 Convert the IRQ Information in ACPI descriptor to IRQ ISA Attribute.
179 @param[in] Information The IRQ Information in ACPI descriptor
181 @return UINT32 The IRQ ISA Attribute
192 if ((Information
& EFI_ACPI_IRQ_POLARITY_MASK
) == EFI_ACPI_IRQ_HIGH_TRUE
) {
193 if ((Information
& EFI_ACPI_IRQ_MODE
) == EFI_ACPI_IRQ_LEVEL_TRIGGERED
) {
194 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE
;
196 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE
;
199 if ((Information
& EFI_ACPI_IRQ_MODE
) == EFI_ACPI_IRQ_LEVEL_TRIGGERED
) {
200 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE
;
202 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE
;
209 Convert the Memory Information in ACPI descriptor to Memory ISA Attribute.
211 @param[in] Information The Memory Information in ACPI descriptor
213 @return UINT32 The Memory ISA Attribute
224 switch (Information
& EFI_ACPI_MEMORY_WRITE_STATUS_MASK
) {
225 case EFI_ACPI_MEMORY_WRITABLE
:
226 Attribute
|= EFI_ISA_ACPI_MEMORY_WRITEABLE
;
234 Convert the DMA Information in ACPI descriptor to DMA ISA Attribute.
236 @param[in] Information The DMA Information in ACPI descriptor
238 @return UINT32 The DMA ISA Attribute
247 Attribute
= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
;
249 switch (Information
& EFI_ACPI_DMA_SPEED_TYPE_MASK
) {
250 case EFI_ACPI_DMA_SPEED_TYPE_COMPATIBILITY
:
251 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE
;
253 case EFI_ACPI_DMA_SPEED_TYPE_A
:
254 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A
;
256 case EFI_ACPI_DMA_SPEED_TYPE_B
:
257 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B
;
259 case EFI_ACPI_DMA_SPEED_TYPE_F
:
260 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C
;
264 switch (Information
& EFI_ACPI_DMA_TRANSFER_TYPE_MASK
) {
265 case EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT
:
266 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
;
268 case EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT
:
269 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
;
277 Convert the ACPI resource descriptor to ISA resource descriptor.
279 @param[in] AcpiResource Pointer to the ACPI resource descriptor
280 @param[out] IsaResource The optional pointer to the buffer to
281 store the converted ISA resource descriptor
283 @return UINTN Number of ISA resource descriptor needed
286 AcpiResourceToIsaResource (
287 IN ACPI_RESOURCE_HEADER_PTR AcpiResource
,
288 OUT EFI_ISA_ACPI_RESOURCE
*IsaResource OPTIONAL
294 EFI_ACPI_IO_PORT_DESCRIPTOR
*Io
;
295 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*FixedIo
;
296 EFI_ACPI_IRQ_DESCRIPTOR
*Irq
;
297 EFI_ACPI_DMA_DESCRIPTOR
*Dma
;
298 EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR
*Memory
;
299 EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR
*FixedMemory
;
304 switch (AcpiResource
.SmallHeader
->Byte
) {
305 case ACPI_DMA_DESCRIPTOR
:
306 Dma
= (EFI_ACPI_DMA_DESCRIPTOR
*) AcpiResource
.SmallHeader
;
307 for (Index
= 0; Index
< sizeof (Dma
->ChannelMask
) * 8; Index
++) {
308 if (Dma
->ChannelMask
& (1 << Index
)) {
309 if ((Count
> 0) && (LastIndex
+ 1 == Index
)) {
310 if (IsaResource
!= NULL
) {
311 IsaResource
[Count
- 1].EndRange
++;
314 if (IsaResource
!= NULL
) {
315 IsaResource
[Count
].Type
= EfiIsaAcpiResourceDma
;
316 IsaResource
[Count
].Attribute
= IsaDmaAttribute (Dma
->Information
);
317 IsaResource
[Count
].StartRange
= Index
;
318 IsaResource
[Count
].EndRange
= Index
;
328 case ACPI_IO_PORT_DESCRIPTOR
:
329 Io
= (EFI_ACPI_IO_PORT_DESCRIPTOR
*) AcpiResource
.SmallHeader
;
330 if (Io
->Length
!= 0) {
331 if (IsaResource
!= NULL
) {
332 IsaResource
[Count
].Type
= EfiIsaAcpiResourceIo
;
333 IsaResource
[Count
].Attribute
= IsaIoAttribute (Io
->Information
);
334 IsaResource
[Count
].StartRange
= Io
->BaseAddressMin
;
335 IsaResource
[Count
].EndRange
= Io
->BaseAddressMin
+ Io
->Length
- 1;
341 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
:
342 FixedIo
= (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*) AcpiResource
.SmallHeader
;
343 if (FixedIo
->Length
!= 0) {
344 if (IsaResource
!= NULL
) {
345 IsaResource
[Count
].Type
= EfiIsaAcpiResourceIo
;
346 IsaResource
[Count
].Attribute
= EFI_ISA_ACPI_IO_DECODE_10_BITS
;
347 IsaResource
[Count
].StartRange
= FixedIo
->BaseAddress
;
348 IsaResource
[Count
].EndRange
= FixedIo
->BaseAddress
+ FixedIo
->Length
- 1;
354 case ACPI_IRQ_DESCRIPTOR
:
355 case ACPI_IRQ_NOFLAG_DESCRIPTOR
:
356 Irq
= (EFI_ACPI_IRQ_DESCRIPTOR
*) AcpiResource
.SmallHeader
;
357 for (Index
= 0; Index
< sizeof (Irq
->Mask
) * 8; Index
++) {
358 if (Irq
->Mask
& (1 << Index
)) {
359 if ((Count
> 0) && (LastIndex
+ 1 == Index
)) {
360 if (IsaResource
!= NULL
) {
361 IsaResource
[Count
- 1].EndRange
++;
364 if (IsaResource
!= NULL
) {
365 IsaResource
[Count
].Type
= EfiIsaAcpiResourceInterrupt
;
366 if (AcpiResource
.SmallHeader
->Byte
== ACPI_IRQ_DESCRIPTOR
) {
367 IsaResource
[Count
].Attribute
= IsaIrqAttribute (Irq
->Information
);
369 IsaResource
[Count
].Attribute
= EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE
;
371 IsaResource
[Count
].StartRange
= Index
;
372 IsaResource
[Count
].EndRange
= Index
;
382 case ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR
:
383 Memory
= (EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR
*) AcpiResource
.LargeHeader
;
384 if (Memory
->Length
!= 0) {
385 if (IsaResource
!= NULL
) {
386 IsaResource
[Count
].Type
= EfiIsaAcpiResourceMemory
;
387 IsaResource
[Count
].Attribute
= IsaMemoryAttribute (Memory
->Information
);
388 IsaResource
[Count
].StartRange
= Memory
->BaseAddressMin
;
389 IsaResource
[Count
].EndRange
= Memory
->BaseAddressMin
+ Memory
->Length
- 1;
395 case ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR
:
396 FixedMemory
= (EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR
*) AcpiResource
.LargeHeader
;
397 if (FixedMemory
->Length
!= 0) {
398 if (IsaResource
!= NULL
) {
399 IsaResource
[Count
].Type
= EfiIsaAcpiResourceMemory
;
400 IsaResource
[Count
].Attribute
= IsaMemoryAttribute (FixedMemory
->Information
);
401 IsaResource
[Count
].StartRange
= FixedMemory
->BaseAddress
;
402 IsaResource
[Count
].EndRange
= FixedMemory
->BaseAddress
+ FixedMemory
->Length
- 1;
408 case ACPI_END_TAG_DESCRIPTOR
:
409 if (IsaResource
!= NULL
) {
410 IsaResource
[Count
].Type
= EfiIsaAcpiResourceEndOfList
;
411 IsaResource
[Count
].Attribute
= 0;
412 IsaResource
[Count
].StartRange
= 0;
413 IsaResource
[Count
].EndRange
= 0;
423 Initializes an ISA I/O Instance
425 @param[in] IsaIoDevice The isa device to be initialized.
426 @param[in] DevicePath The device path of the isa device.
427 @param[in] Resources The ACPI resource list.
431 InitializeIsaIoInstance (
432 IN ISA_IO_DEVICE
*IsaIoDevice
,
433 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
434 IN ACPI_RESOURCE_HEADER_PTR Resources
438 ACPI_HID_DEVICE_PATH
*AcpiNode
;
439 ACPI_RESOURCE_HEADER_PTR ResourcePtr
;
442 // Use the ISA IO Protocol structure template to initialize the ISA IO instance
447 sizeof (EFI_ISA_IO_PROTOCOL
)
451 // Count the resources including the ACPI End Tag
453 ResourcePtr
= Resources
;
455 while (ResourcePtr
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
457 Index
+= AcpiResourceToIsaResource (ResourcePtr
, NULL
);
459 if (ResourcePtr
.SmallHeader
->Bits
.Type
== 0) {
460 ResourcePtr
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.SmallHeader
461 + ResourcePtr
.SmallHeader
->Bits
.Length
462 + sizeof (*ResourcePtr
.SmallHeader
));
464 ResourcePtr
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.LargeHeader
465 + ResourcePtr
.LargeHeader
->Length
466 + sizeof (*ResourcePtr
.LargeHeader
));
471 // Get the Isa Resource count for ACPI End Tag
473 Index
+= AcpiResourceToIsaResource (ResourcePtr
, NULL
);
476 // Initialize the ResourceList
478 IsaIoDevice
->IsaIo
.ResourceList
= AllocatePool (sizeof (EFI_ISA_ACPI_RESOURCE_LIST
) + Index
* sizeof (EFI_ISA_ACPI_RESOURCE
));
479 ASSERT (IsaIoDevice
->IsaIo
.ResourceList
!= NULL
);
480 IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
= (EFI_ISA_ACPI_RESOURCE
*) (IsaIoDevice
->IsaIo
.ResourceList
+ 1);
482 AcpiNode
= (ACPI_HID_DEVICE_PATH
*) ((UINT8
*) DevicePath
+ GetDevicePathSize (DevicePath
) - END_DEVICE_PATH_LENGTH
- sizeof (ACPI_HID_DEVICE_PATH
));
483 IsaIoDevice
->IsaIo
.ResourceList
->Device
.HID
= AcpiNode
->HID
;
484 IsaIoDevice
->IsaIo
.ResourceList
->Device
.UID
= AcpiNode
->UID
;
486 ResourcePtr
= Resources
;
488 while (ResourcePtr
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
490 Index
+= AcpiResourceToIsaResource (ResourcePtr
, &IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
[Index
]);
492 if (ResourcePtr
.SmallHeader
->Bits
.Type
== 0) {
493 ResourcePtr
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.SmallHeader
494 + ResourcePtr
.SmallHeader
->Bits
.Length
495 + sizeof (*ResourcePtr
.SmallHeader
));
497 ResourcePtr
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.LargeHeader
498 + ResourcePtr
.LargeHeader
->Length
499 + sizeof (*ResourcePtr
.LargeHeader
));
504 // Convert the ACPI End Tag
506 AcpiResourceToIsaResource (ResourcePtr
, &IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
[Index
]);
510 Performs an ISA I/O Read Cycle
512 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
513 @param[in] Width Specifies the width of the I/O operation.
514 @param[in] Offset The offset in ISA I/O space to start the I/O operation.
515 @param[in] Count The number of I/O operations to perform.
516 @param[out] Buffer The destination buffer to store the results
518 @retval EFI_SUCCESS The data was read from the device sucessfully.
519 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
520 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
521 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
526 IN EFI_ISA_IO_PROTOCOL
*This
,
527 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
534 ISA_IO_DEVICE
*IsaIoDevice
;
536 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
539 // Verify Isa IO Access
541 Status
= IsaIoVerifyAccess (
548 if (EFI_ERROR (Status
)) {
552 Status
= IsaIoDevice
->PciIo
->Io
.Read (
554 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
555 EFI_PCI_IO_PASS_THROUGH_BAR
,
561 if (EFI_ERROR (Status
)) {
563 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
564 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
572 Performs an ISA I/O Write Cycle
574 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
575 @param[in] Width Specifies the width of the I/O operation.
576 @param[in] Offset The offset in ISA I/O space to start the I/O operation.
577 @param[in] Count The number of I/O operations to perform.
578 @param[in] Buffer The source buffer to write data from
580 @retval EFI_SUCCESS The data was writen to the device sucessfully.
581 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
582 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
583 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
588 IN EFI_ISA_IO_PROTOCOL
*This
,
589 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
596 ISA_IO_DEVICE
*IsaIoDevice
;
598 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
601 // Verify Isa IO Access
603 Status
= IsaIoVerifyAccess (
610 if (EFI_ERROR (Status
)) {
614 Status
= IsaIoDevice
->PciIo
->Io
.Write (
616 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
617 EFI_PCI_IO_PASS_THROUGH_BAR
,
623 if (EFI_ERROR (Status
)) {
625 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
626 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
634 Writes an 8-bit I/O Port
636 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
637 @param[in] Offset The offset in ISA IO space to start the IO operation.
638 @param[in] Value The data to write port.
640 @retval EFI_SUCCESS Success.
641 @retval EFI_INVALID_PARAMETER Parameter is invalid.
642 @retval EFI_UNSUPPORTED The address range specified by Offset is not valid.
643 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
647 IN EFI_ISA_IO_PROTOCOL
*This
,
653 ISA_IO_DEVICE
*IsaIoDevice
;
655 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
657 Status
= IsaIoDevice
->PciIo
->Io
.Write (
660 EFI_PCI_IO_PASS_THROUGH_BAR
,
665 if (EFI_ERROR (Status
)) {
667 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
668 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
674 // Wait for 50 microseconds to take affect.
682 Writes I/O operation base address and count number to a 8 bit I/O Port.
684 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
685 @param[in] AddrOffset The address' offset.
686 @param[in] PageOffset The page's offest.
687 @param[in] CountOffset The count's offset.
688 @param[in] BaseAddress The base address.
689 @param[in] Count The number of I/O operations to perform.
691 @retval EFI_SUCCESS Success.
692 @retval EFI_INVALID_PARAMETER Parameter is invalid.
693 @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid.
694 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
698 IN EFI_ISA_IO_PROTOCOL
*This
,
699 IN UINT32 AddrOffset
,
700 IN UINT32 PageOffset
,
701 IN UINT32 CountOffset
,
702 IN UINT32 BaseAddress
,
708 Status
= WritePort (This
, AddrOffset
, (UINT8
) (BaseAddress
& 0xff));
709 if (EFI_ERROR (Status
)) {
713 Status
= WritePort (This
, AddrOffset
, (UINT8
) ((BaseAddress
>> 8) & 0xff));
714 if (EFI_ERROR (Status
)) {
718 Status
= WritePort (This
, PageOffset
, (UINT8
) ((BaseAddress
>> 16) & 0xff));
719 if (EFI_ERROR (Status
)) {
723 Status
= WritePort (This
, CountOffset
, (UINT8
) (Count
& 0xff));
724 if (EFI_ERROR (Status
)) {
728 Status
= WritePort (This
, CountOffset
, (UINT8
) ((Count
>> 8) & 0xff));
733 Unmaps a memory region for DMA
735 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
736 @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map().
738 @retval EFI_SUCCESS The range was unmapped.
739 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
744 IN EFI_ISA_IO_PROTOCOL
*This
,
748 ISA_MAP_INFO
*IsaMapInfo
;
751 // Check if DMA is supported.
753 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) {
754 return EFI_UNSUPPORTED
;
758 // See if the Map() operation associated with this Unmap() required a mapping
759 // buffer.If a mapping buffer was not required, then this function simply
760 // returns EFI_SUCCESS.
762 if (Mapping
!= NULL
) {
764 // Get the MAP_INFO structure from Mapping
766 IsaMapInfo
= (ISA_MAP_INFO
*) Mapping
;
769 // If this is a write operation from the Agent's point of view,
770 // then copy the contents of the mapped buffer into the real buffer
771 // so the processor can read the contents of the real buffer.
773 if (IsaMapInfo
->Operation
== EfiIsaIoOperationBusMasterWrite
) {
775 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
776 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
777 IsaMapInfo
->NumberOfBytes
781 // Free the mapped buffer and the MAP_INFO structure.
783 gBS
->FreePages (IsaMapInfo
->MappedHostAddress
, IsaMapInfo
->NumberOfPages
);
784 FreePool (IsaMapInfo
);
791 Flushes any posted write data to the system memory.
793 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
795 @retval EFI_SUCCESS The buffers were flushed.
796 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error.
801 IN EFI_ISA_IO_PROTOCOL
*This
805 ISA_IO_DEVICE
*IsaIoDevice
;
807 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
809 Status
= IsaIoDevice
->PciIo
->Flush (IsaIoDevice
->PciIo
);
811 if (EFI_ERROR (Status
)) {
813 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
814 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
822 Performs an ISA Memory Read Cycle
824 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
825 @param[in] Width Specifies the width of the memory operation.
826 @param[in] Offset The offset in ISA memory space to start the memory operation.
827 @param[in] Count The number of memory operations to perform.
828 @param[out] Buffer The destination buffer to store the results
830 @retval EFI_SUCCESS The data was read from the device successfully.
831 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
832 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
833 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
838 IN EFI_ISA_IO_PROTOCOL
*This
,
839 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
846 ISA_IO_DEVICE
*IsaIoDevice
;
849 // Check if ISA memory is supported.
851 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
852 return EFI_UNSUPPORTED
;
855 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
858 // Verify the Isa Io Access
860 Status
= IsaIoVerifyAccess (
867 if (EFI_ERROR (Status
)) {
871 Status
= IsaIoDevice
->PciIo
->Mem
.Read (
873 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
874 EFI_PCI_IO_PASS_THROUGH_BAR
,
880 if (EFI_ERROR (Status
)) {
882 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
883 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
891 Performs an ISA Memory Write Cycle
893 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
894 @param[in] Width Specifies the width of the memory operation.
895 @param[in] Offset The offset in ISA memory space to start the memory operation.
896 @param[in] Count The number of memory operations to perform.
897 @param[in] Buffer The source buffer to write data from
899 @retval EFI_SUCCESS The data was written to the device sucessfully.
900 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
901 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
902 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
907 IN EFI_ISA_IO_PROTOCOL
*This
,
908 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
915 ISA_IO_DEVICE
*IsaIoDevice
;
918 // Check if ISA memory is supported.
920 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
921 return EFI_UNSUPPORTED
;
924 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
927 // Verify Isa IO Access
929 Status
= IsaIoVerifyAccess (
936 if (EFI_ERROR (Status
)) {
940 Status
= IsaIoDevice
->PciIo
->Mem
.Write (
942 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
943 EFI_PCI_IO_PASS_THROUGH_BAR
,
949 if (EFI_ERROR (Status
)) {
951 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
952 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
960 Copy one region of ISA memory space to another region of ISA memory space on the ISA controller.
962 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
963 @param[in] Width Specifies the width of the memory copy operation.
964 @param[in] DestOffset The offset of the destination
965 @param[in] SrcOffset The offset of the source
966 @param[in] Count The number of memory copy operations to perform
968 @retval EFI_SUCCESS The data was copied sucessfully.
969 @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device.
970 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
971 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
976 IN EFI_ISA_IO_PROTOCOL
*This
,
977 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
978 IN UINT32 DestOffset
,
984 ISA_IO_DEVICE
*IsaIoDevice
;
987 // Check if ISA memory is supported.
989 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
990 return EFI_UNSUPPORTED
;
993 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
996 // Verify Isa IO Access for destination and source
998 Status
= IsaIoVerifyAccess (
1005 if (EFI_ERROR (Status
)) {
1009 Status
= IsaIoVerifyAccess (
1016 if (EFI_ERROR (Status
)) {
1020 Status
= IsaIoDevice
->PciIo
->CopyMem (
1022 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
1023 EFI_PCI_IO_PASS_THROUGH_BAR
,
1025 EFI_PCI_IO_PASS_THROUGH_BAR
,
1030 if (EFI_ERROR (Status
)) {
1031 REPORT_STATUS_CODE (
1032 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1033 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
1041 Maps a memory region for DMA, note this implementation
1042 only supports slave read/write operation to save code size.
1044 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1045 @param Operation Indicates the type of DMA (slave or bus master), and if
1046 the DMA operation is going to read or write to system memory.
1047 @param ChannelNumber The slave channel number to use for this DMA operation.
1048 If Operation and ChannelAttributes shows that this device
1049 performs bus mastering DMA, then this field is ignored.
1050 The legal range for this field is 0..7.
1051 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
1052 @param HostAddress The system memory address to map to the device.
1053 @param NumberOfBytes On input the number of bytes to map. On output the number
1054 of bytes that were mapped.
1055 @param DeviceAddress The resulting map address for the bus master device to use
1056 to access the hosts HostAddress.
1057 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
1059 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
1060 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
1061 @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.
1062 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1063 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1066 IsaIoMapOnlySupportSlaveReadWrite (
1067 IN EFI_ISA_IO_PROTOCOL
*This
,
1068 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1069 IN UINT8 ChannelNumber OPTIONAL
,
1070 IN UINT32 ChannelAttributes
,
1071 IN VOID
*HostAddress
,
1072 IN OUT UINTN
*NumberOfBytes
,
1073 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1078 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1079 ISA_MAP_INFO
*IsaMapInfo
;
1081 UINTN MaxNumberOfBytes
;
1086 UINT8 DmaChannelMode
;
1088 if ((NULL
== This
) ||
1089 (NULL
== HostAddress
) ||
1090 (NULL
== NumberOfBytes
) ||
1091 (NULL
== DeviceAddress
) ||
1094 return EFI_INVALID_PARAMETER
;
1098 // Initialize the return values to their defaults
1103 // Make sure the Operation parameter is valid.
1104 // Light IsaIo only supports two operations.
1106 if (!(Operation
== EfiIsaIoOperationSlaveRead
||
1107 Operation
== EfiIsaIoOperationSlaveWrite
)) {
1108 return EFI_INVALID_PARAMETER
;
1111 if (ChannelNumber
>= 4) {
1113 // The Light IsaIo doesn't support channelNumber larger than 4.
1115 return EFI_INVALID_PARAMETER
;
1119 // Map the HostAddress to a DeviceAddress.
1121 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1122 if ((PhysicalAddress
+ *NumberOfBytes
) > BASE_16MB
) {
1124 // Common Buffer operations can not be remapped. If the common buffer
1125 // is above 16MB, then it is not possible to generate a mapping, so return
1128 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1129 return EFI_UNSUPPORTED
;
1132 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1135 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1136 if (IsaMapInfo
== NULL
) {
1138 return EFI_OUT_OF_RESOURCES
;
1141 // Return a pointer to the MAP_INFO structure in Mapping
1143 *Mapping
= IsaMapInfo
;
1146 // Initialize the MAP_INFO structure
1148 IsaMapInfo
->Operation
= Operation
;
1149 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
1150 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1151 IsaMapInfo
->HostAddress
= PhysicalAddress
;
1152 IsaMapInfo
->MappedHostAddress
= BASE_16MB
- 1;
1155 // Allocate a buffer below 16MB to map the transfer to.
1157 Status
= gBS
->AllocatePages (
1159 EfiBootServicesData
,
1160 IsaMapInfo
->NumberOfPages
,
1161 &IsaMapInfo
->MappedHostAddress
1163 if (EFI_ERROR (Status
)) {
1164 FreePool (IsaMapInfo
);
1170 // If this is a read operation from the DMA agents's point of view,
1171 // then copy the contents of the real buffer into the mapped buffer
1172 // so the DMA agent can read the contents of the real buffer.
1174 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1176 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1177 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1178 IsaMapInfo
->NumberOfBytes
1182 // The DeviceAddress is the address of the maped buffer below 16 MB
1184 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1187 // The transfer is below 16 MB, so the DeviceAddress is simply the
1190 *DeviceAddress
= PhysicalAddress
;
1194 // Figure out what to program into the DMA Channel Mode Register
1196 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1197 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1198 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1200 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1203 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
1205 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1208 // A Slave DMA transfer can not cross a 64K boundary.
1209 // Compute *NumberOfBytes based on this restriction.
1211 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1212 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1213 *NumberOfBytes
= MaxNumberOfBytes
;
1216 // Compute the values to program into the BaseAddress and Count registers
1217 // of the Slave DMA controller
1219 BaseAddress
= (UINT32
) (*DeviceAddress
);
1220 Count
= (UINT16
) (*NumberOfBytes
- 1);
1222 // Program the DMA Write Single Mask Register for ChannelNumber
1223 // Clear the DMA Byte Pointer Register
1225 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1226 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1227 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1229 Status
= WritePort (
1232 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1234 if (EFI_ERROR (Status
)) {
1238 Status
= WritePort (
1241 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1243 if (EFI_ERROR (Status
)) {
1247 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1248 if (EFI_ERROR (Status
)) {
1252 Status
= WriteDmaPort (
1254 mDmaRegisters
[ChannelNumber
].Address
,
1255 mDmaRegisters
[ChannelNumber
].Page
,
1256 mDmaRegisters
[ChannelNumber
].Count
,
1260 if (EFI_ERROR (Status
)) {
1264 Status
= WritePort (
1267 (UINT8
) (ChannelNumber
& 0x03)
1269 if (EFI_ERROR (Status
)) {
1277 Maps a memory region for DMA. This implementation implement the
1278 the full mapping support.
1280 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1281 @param Operation Indicates the type of DMA (slave or bus master), and if
1282 the DMA operation is going to read or write to system memory.
1283 @param ChannelNumber The slave channel number to use for this DMA operation.
1284 If Operation and ChannelAttributes shows that this device
1285 performs bus mastering DMA, then this field is ignored.
1286 The legal range for this field is 0..7.
1287 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
1288 @param HostAddress The system memory address to map to the device.
1289 @param NumberOfBytes On input the number of bytes to map. On output the number
1290 of bytes that were mapped.
1291 @param DeviceAddress The resulting map address for the bus master device to use
1292 to access the hosts HostAddress.
1293 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
1295 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1296 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1297 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1298 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1299 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1302 IsaIoMapFullSupport (
1303 IN EFI_ISA_IO_PROTOCOL
*This
,
1304 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1305 IN UINT8 ChannelNumber OPTIONAL
,
1306 IN UINT32 ChannelAttributes
,
1307 IN VOID
*HostAddress
,
1308 IN OUT UINTN
*NumberOfBytes
,
1309 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1316 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1317 ISA_MAP_INFO
*IsaMapInfo
;
1319 UINTN MaxNumberOfBytes
;
1324 UINT8 DmaChannelMode
;
1326 if ((NULL
== This
) ||
1327 (NULL
== HostAddress
) ||
1328 (NULL
== NumberOfBytes
) ||
1329 (NULL
== DeviceAddress
) ||
1332 return EFI_INVALID_PARAMETER
;
1336 // Initialize the return values to their defaults
1341 // Make sure the Operation parameter is valid
1343 if (Operation
< 0 || Operation
>= EfiIsaIoOperationMaximum
) {
1344 return EFI_INVALID_PARAMETER
;
1347 if (ChannelNumber
>= 8) {
1348 return EFI_INVALID_PARAMETER
;
1352 // See if this is a Slave DMA Operation
1356 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1357 Operation
= EfiIsaIoOperationBusMasterRead
;
1362 if (Operation
== EfiIsaIoOperationSlaveWrite
) {
1363 Operation
= EfiIsaIoOperationBusMasterWrite
;
1370 // Make sure that ChannelNumber is a valid channel number
1371 // Channel 4 is used to cascade, so it is illegal.
1373 if (ChannelNumber
== 4 || ChannelNumber
> 7) {
1374 return EFI_INVALID_PARAMETER
;
1377 // This implementation only support COMPATIBLE DMA Transfers
1379 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE
) == 0) {
1380 return EFI_INVALID_PARAMETER
;
1383 if ((ChannelAttributes
&
1384 (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A
|
1385 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B
|
1386 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C
)) != 0) {
1387 return EFI_INVALID_PARAMETER
;
1390 if (ChannelNumber
< 4) {
1392 // If this is Channel 0..3, then the width must be 8 bit
1394 if (((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) == 0) ||
1395 ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
) != 0)
1397 return EFI_INVALID_PARAMETER
;
1401 // If this is Channel 4..7, then the width must be 16 bit
1403 if (((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) != 0) ||
1404 ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
) == 0)) {
1405 return EFI_INVALID_PARAMETER
;
1409 // Either Demand Mode or Single Mode must be selected, but not both
1411 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) != 0) {
1412 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) != 0) {
1413 return EFI_INVALID_PARAMETER
;
1416 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) == 0) {
1417 return EFI_INVALID_PARAMETER
;
1422 // Map the HostAddress to a DeviceAddress.
1424 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1425 if ((PhysicalAddress
+*NumberOfBytes
) > BASE_16MB
) {
1427 // Common Buffer operations can not be remapped. If the common buffer
1428 // is above 16MB, then it is not possible to generate a mapping, so return
1431 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1432 return EFI_UNSUPPORTED
;
1435 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1438 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1439 if (IsaMapInfo
== NULL
) {
1441 return EFI_OUT_OF_RESOURCES
;
1444 // Return a pointer to the MAP_INFO structure in Mapping
1446 *Mapping
= IsaMapInfo
;
1449 // Initialize the MAP_INFO structure
1451 IsaMapInfo
->Operation
= Operation
;
1452 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
1453 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1454 IsaMapInfo
->HostAddress
= PhysicalAddress
;
1455 IsaMapInfo
->MappedHostAddress
= BASE_16MB
- 1;
1458 // Allocate a buffer below 16MB to map the transfer to.
1460 Status
= gBS
->AllocatePages (
1462 EfiBootServicesData
,
1463 IsaMapInfo
->NumberOfPages
,
1464 &IsaMapInfo
->MappedHostAddress
1466 if (EFI_ERROR (Status
)) {
1467 FreePool (IsaMapInfo
);
1473 // If this is a read operation from the DMA agents's point of view,
1474 // then copy the contents of the real buffer into the mapped buffer
1475 // so the DMA agent can read the contents of the real buffer.
1477 if (Operation
== EfiIsaIoOperationBusMasterRead
) {
1479 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1480 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1481 IsaMapInfo
->NumberOfBytes
1485 // The DeviceAddress is the address of the maped buffer below 16 MB
1487 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1490 // The transfer is below 16 MB, so the DeviceAddress is simply the
1493 *DeviceAddress
= PhysicalAddress
;
1496 // If this is a Bus Master operation then return
1502 // Figure out what to program into the DMA Channel Mode Register
1504 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1506 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1508 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1511 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE
) != 0) {
1512 DmaMode
|= B_8237_DMA_CHMODE_AE
;
1515 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) != 0) {
1516 DmaMode
|= V_8237_DMA_CHMODE_DEMAND
;
1519 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) != 0) {
1520 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1523 // A Slave DMA transfer can not cross a 64K boundary.
1524 // Compute *NumberOfBytes based on this restriction.
1526 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1527 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1528 *NumberOfBytes
= MaxNumberOfBytes
;
1531 // Compute the values to program into the BaseAddress and Count registers
1532 // of the Slave DMA controller
1534 if (ChannelNumber
< 4) {
1535 BaseAddress
= (UINT32
) (*DeviceAddress
);
1536 Count
= (UINT16
) (*NumberOfBytes
- 1);
1538 BaseAddress
= (UINT32
) (((UINT32
) (*DeviceAddress
) & 0xff0000) | (((UINT32
) (*DeviceAddress
) & 0xffff) >> 1));
1539 Count
= (UINT16
) ((*NumberOfBytes
- 1) >> 1);
1542 // Program the DMA Write Single Mask Register for ChannelNumber
1543 // Clear the DMA Byte Pointer Register
1545 if (ChannelNumber
< 4) {
1546 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1547 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1548 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1550 DmaMask
= R_8237_DMA_WRSMSK_CH4_7
;
1551 DmaClear
= R_8237_DMA_CBPR_CH4_7
;
1552 DmaChannelMode
= R_8237_DMA_CHMODE_CH4_7
;
1555 Status
= WritePort (
1558 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1560 if (EFI_ERROR (Status
)) {
1564 Status
= WritePort (
1567 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1569 if (EFI_ERROR (Status
)) {
1573 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1574 if (EFI_ERROR (Status
)) {
1578 Status
= WriteDmaPort (
1580 mDmaRegisters
[ChannelNumber
].Address
,
1581 mDmaRegisters
[ChannelNumber
].Page
,
1582 mDmaRegisters
[ChannelNumber
].Count
,
1586 if (EFI_ERROR (Status
)) {
1590 Status
= WritePort (
1593 (UINT8
) (ChannelNumber
& 0x03)
1595 if (EFI_ERROR (Status
)) {
1603 Maps a memory region for DMA
1605 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1606 @param Operation Indicates the type of DMA (slave or bus master), and if
1607 the DMA operation is going to read or write to system memory.
1608 @param ChannelNumber The slave channel number to use for this DMA operation.
1609 If Operation and ChannelAttributes shows that this device
1610 performs bus mastering DMA, then this field is ignored.
1611 The legal range for this field is 0..7.
1612 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
1613 @param HostAddress The system memory address to map to the device.
1614 @param NumberOfBytes On input the number of bytes to map. On output the number
1615 of bytes that were mapped.
1616 @param DeviceAddress The resulting map address for the bus master device to use
1617 to access the hosts HostAddress.
1618 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
1620 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
1621 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
1622 @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.
1623 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1624 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1629 IN EFI_ISA_IO_PROTOCOL
*This
,
1630 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1631 IN UINT8 ChannelNumber OPTIONAL
,
1632 IN UINT32 ChannelAttributes
,
1633 IN VOID
*HostAddress
,
1634 IN OUT UINTN
*NumberOfBytes
,
1635 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1640 // Check if DMA is supported.
1642 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) {
1643 return EFI_UNSUPPORTED
;
1646 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1649 // So we just return EFI_UNSUPPORTED for these functions.
1651 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA
) != 0) {
1652 return IsaIoMapOnlySupportSlaveReadWrite (
1664 return IsaIoMapFullSupport (
1678 Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping.
1680 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1681 @param[in] Type The type allocation to perform.
1682 @param[in] MemoryType The type of memory to allocate.
1683 @param[in] Pages The number of pages to allocate.
1684 @param[out] HostAddress A pointer to store the base address of the allocated range.
1685 @param[in] Attributes The requested bit mask of attributes for the allocated range.
1687 @retval EFI_SUCCESS The requested memory pages were allocated.
1688 @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL
1689 @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified
1690 by HostAddress, Pages, and Type is not available for common buffer use.
1691 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1695 IsaIoAllocateBuffer (
1696 IN EFI_ISA_IO_PROTOCOL
*This
,
1697 IN EFI_ALLOCATE_TYPE Type
,
1698 IN EFI_MEMORY_TYPE MemoryType
,
1700 OUT VOID
**HostAddress
,
1701 IN UINT64 Attributes
1705 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1708 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1710 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1712 if (((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) ||
1713 ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA
) != 0)) {
1714 return EFI_UNSUPPORTED
;
1717 if (HostAddress
== NULL
) {
1718 return EFI_INVALID_PARAMETER
;
1721 if (Type
< AllocateAnyPages
|| Type
>= MaxAllocateType
) {
1722 return EFI_INVALID_PARAMETER
;
1725 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1727 if (MemoryType
!= EfiBootServicesData
&& MemoryType
!= EfiRuntimeServicesData
) {
1728 return EFI_INVALID_PARAMETER
;
1731 if ((Attributes
& ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
| EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED
)) != 0) {
1732 return EFI_UNSUPPORTED
;
1735 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) (BASE_16MB
- 1);
1736 if (Type
== AllocateAddress
) {
1737 if ((UINTN
) (*HostAddress
) >= BASE_16MB
) {
1738 return EFI_UNSUPPORTED
;
1740 PhysicalAddress
= (UINTN
) (*HostAddress
);
1744 if (Type
== AllocateAnyPages
) {
1745 Type
= AllocateMaxAddress
;
1748 Status
= gBS
->AllocatePages (Type
, MemoryType
, Pages
, &PhysicalAddress
);
1749 if (EFI_ERROR (Status
)) {
1750 REPORT_STATUS_CODE (
1751 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1752 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
1757 *HostAddress
= (VOID
*) (UINTN
) PhysicalAddress
;
1762 Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer().
1764 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1765 @param[in] Pages The number of pages to free.
1766 @param[in] HostAddress The base address of the allocated range.
1768 @retval EFI_SUCCESS The requested memory pages were freed.
1769 @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1774 IN EFI_ISA_IO_PROTOCOL
*This
,
1776 IN VOID
*HostAddress
1782 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1784 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1786 if (((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) ||
1787 ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA
) != 0)) {
1788 return EFI_UNSUPPORTED
;
1791 Status
= gBS
->FreePages (
1792 (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
,
1795 if (EFI_ERROR (Status
)) {
1796 REPORT_STATUS_CODE (
1797 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1798 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR