2 The implementation for EFI_ISA_IO_PROTOCOL.
4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
14 EFI_ISA_IO_PROTOCOL mIsaIoInterface
= {
34 EFI_ISA_DMA_REGISTERS mDmaRegisters
[8] = {
59 }, // Channel 4 is invalid
78 Verifies access to an ISA device
80 @param[in] IsaIoDevice The ISA device to be verified.
81 @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo.
82 @param[in] Width The width of the memory operation.
83 @param[in] Count The number of memory operations to perform.
84 @param[in] Offset The offset in ISA memory space to start the memory operation.
86 @retval EFI_SUCCESS Verify success.
87 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
88 @retval EFI_UNSUPPORTED The device ont support the access type.
92 IN ISA_IO_DEVICE
*IsaIoDevice
,
93 IN ISA_ACCESS_TYPE Type
,
94 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
99 EFI_ISA_ACPI_RESOURCE
*Item
;
102 if ((UINT32
)Width
>= EfiIsaIoWidthMaximum
||
103 Width
== EfiIsaIoWidthReserved
||
104 Width
== EfiIsaIoWidthFifoReserved
||
105 Width
== EfiIsaIoWidthFillReserved
107 return EFI_INVALID_PARAMETER
;
111 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
112 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
114 if (Width
>= EfiIsaIoWidthFifoUint8
&& Width
< EfiIsaIoWidthFifoReserved
) {
118 Width
= (EFI_ISA_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
120 Status
= EFI_UNSUPPORTED
;
121 Item
= IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
;
122 while (Item
->Type
!= EfiIsaAcpiResourceEndOfList
) {
123 if ((Type
== IsaAccessTypeMem
&& Item
->Type
== EfiIsaAcpiResourceMemory
) ||
124 (Type
== IsaAccessTypeIo
&& Item
->Type
== EfiIsaAcpiResourceIo
)) {
125 if (Offset
>= Item
->StartRange
&& (Offset
+ Count
* (UINT32
)(1 << Width
)) - 1 <= Item
->EndRange
) {
129 if (Offset
>= Item
->StartRange
&& Offset
<= Item
->EndRange
) {
130 Status
= EFI_INVALID_PARAMETER
;
141 Convert the IO Information in ACPI descriptor to IO ISA Attribute.
143 @param[in] Information The IO Information in ACPI descriptor
145 @return UINT32 The IO ISA Attribute
156 switch (Information
& EFI_ACPI_IO_DECODE_MASK
) {
157 case EFI_ACPI_IO_DECODE_16_BIT
:
158 Attribute
|= EFI_ISA_ACPI_IO_DECODE_16_BITS
;
161 case EFI_ACPI_IO_DECODE_10_BIT
:
162 Attribute
|= EFI_ISA_ACPI_IO_DECODE_10_BITS
;
170 Convert the IRQ Information in ACPI descriptor to IRQ ISA Attribute.
172 @param[in] Information The IRQ Information in ACPI descriptor
174 @return UINT32 The IRQ ISA Attribute
185 if ((Information
& EFI_ACPI_IRQ_POLARITY_MASK
) == EFI_ACPI_IRQ_HIGH_TRUE
) {
186 if ((Information
& EFI_ACPI_IRQ_MODE
) == EFI_ACPI_IRQ_LEVEL_TRIGGERED
) {
187 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE
;
189 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE
;
192 if ((Information
& EFI_ACPI_IRQ_MODE
) == EFI_ACPI_IRQ_LEVEL_TRIGGERED
) {
193 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE
;
195 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE
;
202 Convert the Memory Information in ACPI descriptor to Memory ISA Attribute.
204 @param[in] Information The Memory Information in ACPI descriptor
206 @return UINT32 The Memory ISA Attribute
217 switch (Information
& EFI_ACPI_MEMORY_WRITE_STATUS_MASK
) {
218 case EFI_ACPI_MEMORY_WRITABLE
:
219 Attribute
|= EFI_ISA_ACPI_MEMORY_WRITEABLE
;
227 Convert the DMA Information in ACPI descriptor to DMA ISA Attribute.
229 @param[in] Information The DMA Information in ACPI descriptor
231 @return UINT32 The DMA ISA Attribute
240 Attribute
= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
;
242 switch (Information
& EFI_ACPI_DMA_SPEED_TYPE_MASK
) {
243 case EFI_ACPI_DMA_SPEED_TYPE_COMPATIBILITY
:
244 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE
;
246 case EFI_ACPI_DMA_SPEED_TYPE_A
:
247 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A
;
249 case EFI_ACPI_DMA_SPEED_TYPE_B
:
250 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B
;
252 case EFI_ACPI_DMA_SPEED_TYPE_F
:
253 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C
;
257 switch (Information
& EFI_ACPI_DMA_TRANSFER_TYPE_MASK
) {
258 case EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT
:
259 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
;
261 case EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT
:
262 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
;
270 Convert the ACPI resource descriptor to ISA resource descriptor.
272 @param[in] AcpiResource Pointer to the ACPI resource descriptor
273 @param[out] IsaResource The optional pointer to the buffer to
274 store the converted ISA resource descriptor
276 @return UINTN Number of ISA resource descriptor needed
279 AcpiResourceToIsaResource (
280 IN ACPI_RESOURCE_HEADER_PTR AcpiResource
,
281 OUT EFI_ISA_ACPI_RESOURCE
*IsaResource OPTIONAL
287 EFI_ACPI_IO_PORT_DESCRIPTOR
*Io
;
288 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*FixedIo
;
289 EFI_ACPI_IRQ_DESCRIPTOR
*Irq
;
290 EFI_ACPI_DMA_DESCRIPTOR
*Dma
;
291 EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR
*Memory
;
292 EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR
*FixedMemory
;
297 switch (AcpiResource
.SmallHeader
->Byte
) {
298 case ACPI_DMA_DESCRIPTOR
:
299 Dma
= (EFI_ACPI_DMA_DESCRIPTOR
*) AcpiResource
.SmallHeader
;
300 for (Index
= 0; Index
< sizeof (Dma
->ChannelMask
) * 8; Index
++) {
301 if (Dma
->ChannelMask
& (1 << Index
)) {
302 if ((Count
> 0) && (LastIndex
+ 1 == Index
)) {
303 if (IsaResource
!= NULL
) {
304 IsaResource
[Count
- 1].EndRange
++;
307 if (IsaResource
!= NULL
) {
308 IsaResource
[Count
].Type
= EfiIsaAcpiResourceDma
;
309 IsaResource
[Count
].Attribute
= IsaDmaAttribute (Dma
->Information
);
310 IsaResource
[Count
].StartRange
= Index
;
311 IsaResource
[Count
].EndRange
= Index
;
321 case ACPI_IO_PORT_DESCRIPTOR
:
322 Io
= (EFI_ACPI_IO_PORT_DESCRIPTOR
*) AcpiResource
.SmallHeader
;
323 if (Io
->Length
!= 0) {
324 if (IsaResource
!= NULL
) {
325 IsaResource
[Count
].Type
= EfiIsaAcpiResourceIo
;
326 IsaResource
[Count
].Attribute
= IsaIoAttribute (Io
->Information
);
327 IsaResource
[Count
].StartRange
= Io
->BaseAddressMin
;
328 IsaResource
[Count
].EndRange
= Io
->BaseAddressMin
+ Io
->Length
- 1;
334 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
:
335 FixedIo
= (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*) AcpiResource
.SmallHeader
;
336 if (FixedIo
->Length
!= 0) {
337 if (IsaResource
!= NULL
) {
338 IsaResource
[Count
].Type
= EfiIsaAcpiResourceIo
;
339 IsaResource
[Count
].Attribute
= EFI_ISA_ACPI_IO_DECODE_10_BITS
;
340 IsaResource
[Count
].StartRange
= FixedIo
->BaseAddress
;
341 IsaResource
[Count
].EndRange
= FixedIo
->BaseAddress
+ FixedIo
->Length
- 1;
347 case ACPI_IRQ_DESCRIPTOR
:
348 case ACPI_IRQ_NOFLAG_DESCRIPTOR
:
349 Irq
= (EFI_ACPI_IRQ_DESCRIPTOR
*) AcpiResource
.SmallHeader
;
350 for (Index
= 0; Index
< sizeof (Irq
->Mask
) * 8; Index
++) {
351 if (Irq
->Mask
& (1 << Index
)) {
352 if ((Count
> 0) && (LastIndex
+ 1 == Index
)) {
353 if (IsaResource
!= NULL
) {
354 IsaResource
[Count
- 1].EndRange
++;
357 if (IsaResource
!= NULL
) {
358 IsaResource
[Count
].Type
= EfiIsaAcpiResourceInterrupt
;
359 if (AcpiResource
.SmallHeader
->Byte
== ACPI_IRQ_DESCRIPTOR
) {
360 IsaResource
[Count
].Attribute
= IsaIrqAttribute (Irq
->Information
);
362 IsaResource
[Count
].Attribute
= EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE
;
364 IsaResource
[Count
].StartRange
= Index
;
365 IsaResource
[Count
].EndRange
= Index
;
375 case ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR
:
376 Memory
= (EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR
*) AcpiResource
.LargeHeader
;
377 if (Memory
->Length
!= 0) {
378 if (IsaResource
!= NULL
) {
379 IsaResource
[Count
].Type
= EfiIsaAcpiResourceMemory
;
380 IsaResource
[Count
].Attribute
= IsaMemoryAttribute (Memory
->Information
);
381 IsaResource
[Count
].StartRange
= Memory
->BaseAddressMin
;
382 IsaResource
[Count
].EndRange
= Memory
->BaseAddressMin
+ Memory
->Length
- 1;
388 case ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR
:
389 FixedMemory
= (EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR
*) AcpiResource
.LargeHeader
;
390 if (FixedMemory
->Length
!= 0) {
391 if (IsaResource
!= NULL
) {
392 IsaResource
[Count
].Type
= EfiIsaAcpiResourceMemory
;
393 IsaResource
[Count
].Attribute
= IsaMemoryAttribute (FixedMemory
->Information
);
394 IsaResource
[Count
].StartRange
= FixedMemory
->BaseAddress
;
395 IsaResource
[Count
].EndRange
= FixedMemory
->BaseAddress
+ FixedMemory
->Length
- 1;
401 case ACPI_END_TAG_DESCRIPTOR
:
402 if (IsaResource
!= NULL
) {
403 IsaResource
[Count
].Type
= EfiIsaAcpiResourceEndOfList
;
404 IsaResource
[Count
].Attribute
= 0;
405 IsaResource
[Count
].StartRange
= 0;
406 IsaResource
[Count
].EndRange
= 0;
416 Initializes an ISA I/O Instance
418 @param[in] IsaIoDevice The isa device to be initialized.
419 @param[in] DevicePath The device path of the isa device.
420 @param[in] Resources The ACPI resource list.
424 InitializeIsaIoInstance (
425 IN ISA_IO_DEVICE
*IsaIoDevice
,
426 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
427 IN ACPI_RESOURCE_HEADER_PTR Resources
431 ACPI_HID_DEVICE_PATH
*AcpiNode
;
432 ACPI_RESOURCE_HEADER_PTR ResourcePtr
;
435 // Use the ISA IO Protocol structure template to initialize the ISA IO instance
440 sizeof (EFI_ISA_IO_PROTOCOL
)
444 // Count the resources including the ACPI End Tag
446 ResourcePtr
= Resources
;
448 while (ResourcePtr
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
450 Index
+= AcpiResourceToIsaResource (ResourcePtr
, NULL
);
452 if (ResourcePtr
.SmallHeader
->Bits
.Type
== 0) {
453 ResourcePtr
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.SmallHeader
454 + ResourcePtr
.SmallHeader
->Bits
.Length
455 + sizeof (*ResourcePtr
.SmallHeader
));
457 ResourcePtr
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.LargeHeader
458 + ResourcePtr
.LargeHeader
->Length
459 + sizeof (*ResourcePtr
.LargeHeader
));
464 // Get the Isa Resource count for ACPI End Tag
466 Index
+= AcpiResourceToIsaResource (ResourcePtr
, NULL
);
469 // Initialize the ResourceList
471 IsaIoDevice
->IsaIo
.ResourceList
= AllocatePool (sizeof (EFI_ISA_ACPI_RESOURCE_LIST
) + Index
* sizeof (EFI_ISA_ACPI_RESOURCE
));
472 ASSERT (IsaIoDevice
->IsaIo
.ResourceList
!= NULL
);
473 IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
= (EFI_ISA_ACPI_RESOURCE
*) (IsaIoDevice
->IsaIo
.ResourceList
+ 1);
475 AcpiNode
= (ACPI_HID_DEVICE_PATH
*) ((UINT8
*) DevicePath
+ GetDevicePathSize (DevicePath
) - END_DEVICE_PATH_LENGTH
- sizeof (ACPI_HID_DEVICE_PATH
));
476 IsaIoDevice
->IsaIo
.ResourceList
->Device
.HID
= AcpiNode
->HID
;
477 IsaIoDevice
->IsaIo
.ResourceList
->Device
.UID
= AcpiNode
->UID
;
479 ResourcePtr
= Resources
;
481 while (ResourcePtr
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
483 Index
+= AcpiResourceToIsaResource (ResourcePtr
, &IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
[Index
]);
485 if (ResourcePtr
.SmallHeader
->Bits
.Type
== 0) {
486 ResourcePtr
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.SmallHeader
487 + ResourcePtr
.SmallHeader
->Bits
.Length
488 + sizeof (*ResourcePtr
.SmallHeader
));
490 ResourcePtr
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.LargeHeader
491 + ResourcePtr
.LargeHeader
->Length
492 + sizeof (*ResourcePtr
.LargeHeader
));
497 // Convert the ACPI End Tag
499 AcpiResourceToIsaResource (ResourcePtr
, &IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
[Index
]);
503 Performs an ISA I/O Read Cycle
505 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
506 @param[in] Width Specifies the width of the I/O operation.
507 @param[in] Offset The offset in ISA I/O space to start the I/O operation.
508 @param[in] Count The number of I/O operations to perform.
509 @param[out] Buffer The destination buffer to store the results
511 @retval EFI_SUCCESS The data was read from the device sucessfully.
512 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
513 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
514 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
519 IN EFI_ISA_IO_PROTOCOL
*This
,
520 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
527 ISA_IO_DEVICE
*IsaIoDevice
;
529 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
532 // Verify Isa IO Access
534 Status
= IsaIoVerifyAccess (
541 if (EFI_ERROR (Status
)) {
545 Status
= IsaIoDevice
->PciIo
->Io
.Read (
547 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
548 EFI_PCI_IO_PASS_THROUGH_BAR
,
554 if (EFI_ERROR (Status
)) {
556 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
557 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
565 Performs an ISA I/O Write Cycle
567 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
568 @param[in] Width Specifies the width of the I/O operation.
569 @param[in] Offset The offset in ISA I/O space to start the I/O operation.
570 @param[in] Count The number of I/O operations to perform.
571 @param[in] Buffer The source buffer to write data from
573 @retval EFI_SUCCESS The data was writen to the device sucessfully.
574 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
575 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
576 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
581 IN EFI_ISA_IO_PROTOCOL
*This
,
582 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
589 ISA_IO_DEVICE
*IsaIoDevice
;
591 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
594 // Verify Isa IO Access
596 Status
= IsaIoVerifyAccess (
603 if (EFI_ERROR (Status
)) {
607 Status
= IsaIoDevice
->PciIo
->Io
.Write (
609 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
610 EFI_PCI_IO_PASS_THROUGH_BAR
,
616 if (EFI_ERROR (Status
)) {
618 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
619 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
627 Writes an 8-bit I/O Port
629 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
630 @param[in] Offset The offset in ISA IO space to start the IO operation.
631 @param[in] Value The data to write port.
633 @retval EFI_SUCCESS Success.
634 @retval EFI_INVALID_PARAMETER Parameter is invalid.
635 @retval EFI_UNSUPPORTED The address range specified by Offset is not valid.
636 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
640 IN EFI_ISA_IO_PROTOCOL
*This
,
646 ISA_IO_DEVICE
*IsaIoDevice
;
648 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
650 Status
= IsaIoDevice
->PciIo
->Io
.Write (
653 EFI_PCI_IO_PASS_THROUGH_BAR
,
658 if (EFI_ERROR (Status
)) {
660 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
661 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
667 // Wait for 50 microseconds to take affect.
675 Writes I/O operation base address and count number to a 8 bit I/O Port.
677 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
678 @param[in] AddrOffset The address' offset.
679 @param[in] PageOffset The page's offest.
680 @param[in] CountOffset The count's offset.
681 @param[in] BaseAddress The base address.
682 @param[in] Count The number of I/O operations to perform.
684 @retval EFI_SUCCESS Success.
685 @retval EFI_INVALID_PARAMETER Parameter is invalid.
686 @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid.
687 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
691 IN EFI_ISA_IO_PROTOCOL
*This
,
692 IN UINT32 AddrOffset
,
693 IN UINT32 PageOffset
,
694 IN UINT32 CountOffset
,
695 IN UINT32 BaseAddress
,
701 Status
= WritePort (This
, AddrOffset
, (UINT8
) (BaseAddress
& 0xff));
702 if (EFI_ERROR (Status
)) {
706 Status
= WritePort (This
, AddrOffset
, (UINT8
) ((BaseAddress
>> 8) & 0xff));
707 if (EFI_ERROR (Status
)) {
711 Status
= WritePort (This
, PageOffset
, (UINT8
) ((BaseAddress
>> 16) & 0xff));
712 if (EFI_ERROR (Status
)) {
716 Status
= WritePort (This
, CountOffset
, (UINT8
) (Count
& 0xff));
717 if (EFI_ERROR (Status
)) {
721 Status
= WritePort (This
, CountOffset
, (UINT8
) ((Count
>> 8) & 0xff));
726 Unmaps a memory region for DMA
728 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
729 @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map().
731 @retval EFI_SUCCESS The range was unmapped.
732 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
737 IN EFI_ISA_IO_PROTOCOL
*This
,
741 ISA_MAP_INFO
*IsaMapInfo
;
744 // Check if DMA is supported.
746 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) {
747 return EFI_UNSUPPORTED
;
751 // See if the Map() operation associated with this Unmap() required a mapping
752 // buffer.If a mapping buffer was not required, then this function simply
753 // returns EFI_SUCCESS.
755 if (Mapping
!= NULL
) {
757 // Get the MAP_INFO structure from Mapping
759 IsaMapInfo
= (ISA_MAP_INFO
*) Mapping
;
762 // If this is a write operation from the Agent's point of view,
763 // then copy the contents of the mapped buffer into the real buffer
764 // so the processor can read the contents of the real buffer.
766 if (IsaMapInfo
->Operation
== EfiIsaIoOperationBusMasterWrite
) {
768 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
769 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
770 IsaMapInfo
->NumberOfBytes
774 // Free the mapped buffer and the MAP_INFO structure.
776 gBS
->FreePages (IsaMapInfo
->MappedHostAddress
, IsaMapInfo
->NumberOfPages
);
777 FreePool (IsaMapInfo
);
784 Flushes any posted write data to the system memory.
786 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
788 @retval EFI_SUCCESS The buffers were flushed.
789 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error.
794 IN EFI_ISA_IO_PROTOCOL
*This
798 ISA_IO_DEVICE
*IsaIoDevice
;
800 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
802 Status
= IsaIoDevice
->PciIo
->Flush (IsaIoDevice
->PciIo
);
804 if (EFI_ERROR (Status
)) {
806 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
807 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
815 Performs an ISA Memory Read Cycle
817 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
818 @param[in] Width Specifies the width of the memory operation.
819 @param[in] Offset The offset in ISA memory space to start the memory operation.
820 @param[in] Count The number of memory operations to perform.
821 @param[out] Buffer The destination buffer to store the results
823 @retval EFI_SUCCESS The data was read from the device successfully.
824 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
825 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
826 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
831 IN EFI_ISA_IO_PROTOCOL
*This
,
832 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
839 ISA_IO_DEVICE
*IsaIoDevice
;
842 // Check if ISA memory is supported.
844 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
845 return EFI_UNSUPPORTED
;
848 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
851 // Verify the Isa Io Access
853 Status
= IsaIoVerifyAccess (
860 if (EFI_ERROR (Status
)) {
864 Status
= IsaIoDevice
->PciIo
->Mem
.Read (
866 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
867 EFI_PCI_IO_PASS_THROUGH_BAR
,
873 if (EFI_ERROR (Status
)) {
875 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
876 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
884 Performs an ISA Memory Write Cycle
886 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
887 @param[in] Width Specifies the width of the memory operation.
888 @param[in] Offset The offset in ISA memory space to start the memory operation.
889 @param[in] Count The number of memory operations to perform.
890 @param[in] Buffer The source buffer to write data from
892 @retval EFI_SUCCESS The data was written to the device sucessfully.
893 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
894 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
895 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
900 IN EFI_ISA_IO_PROTOCOL
*This
,
901 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
908 ISA_IO_DEVICE
*IsaIoDevice
;
911 // Check if ISA memory is supported.
913 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
914 return EFI_UNSUPPORTED
;
917 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
920 // Verify Isa IO Access
922 Status
= IsaIoVerifyAccess (
929 if (EFI_ERROR (Status
)) {
933 Status
= IsaIoDevice
->PciIo
->Mem
.Write (
935 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
936 EFI_PCI_IO_PASS_THROUGH_BAR
,
942 if (EFI_ERROR (Status
)) {
944 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
945 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
953 Copy one region of ISA memory space to another region of ISA memory space on the ISA controller.
955 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
956 @param[in] Width Specifies the width of the memory copy operation.
957 @param[in] DestOffset The offset of the destination
958 @param[in] SrcOffset The offset of the source
959 @param[in] Count The number of memory copy operations to perform
961 @retval EFI_SUCCESS The data was copied sucessfully.
962 @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device.
963 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
964 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
969 IN EFI_ISA_IO_PROTOCOL
*This
,
970 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
971 IN UINT32 DestOffset
,
977 ISA_IO_DEVICE
*IsaIoDevice
;
980 // Check if ISA memory is supported.
982 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
983 return EFI_UNSUPPORTED
;
986 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
989 // Verify Isa IO Access for destination and source
991 Status
= IsaIoVerifyAccess (
998 if (EFI_ERROR (Status
)) {
1002 Status
= IsaIoVerifyAccess (
1009 if (EFI_ERROR (Status
)) {
1013 Status
= IsaIoDevice
->PciIo
->CopyMem (
1015 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
1016 EFI_PCI_IO_PASS_THROUGH_BAR
,
1018 EFI_PCI_IO_PASS_THROUGH_BAR
,
1023 if (EFI_ERROR (Status
)) {
1024 REPORT_STATUS_CODE (
1025 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1026 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
1034 Maps a memory region for DMA, note this implementation
1035 only supports slave read/write operation to save code size.
1037 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1038 @param Operation Indicates the type of DMA (slave or bus master), and if
1039 the DMA operation is going to read or write to system memory.
1040 @param ChannelNumber The slave channel number to use for this DMA operation.
1041 If Operation and ChannelAttributes shows that this device
1042 performs bus mastering DMA, then this field is ignored.
1043 The legal range for this field is 0..7.
1044 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
1045 @param HostAddress The system memory address to map to the device.
1046 @param NumberOfBytes On input the number of bytes to map. On output the number
1047 of bytes that were mapped.
1048 @param DeviceAddress The resulting map address for the bus master device to use
1049 to access the hosts HostAddress.
1050 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
1052 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
1053 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
1054 @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.
1055 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1056 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1059 IsaIoMapOnlySupportSlaveReadWrite (
1060 IN EFI_ISA_IO_PROTOCOL
*This
,
1061 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1062 IN UINT8 ChannelNumber OPTIONAL
,
1063 IN UINT32 ChannelAttributes
,
1064 IN VOID
*HostAddress
,
1065 IN OUT UINTN
*NumberOfBytes
,
1066 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1071 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1072 ISA_MAP_INFO
*IsaMapInfo
;
1074 UINTN MaxNumberOfBytes
;
1079 UINT8 DmaChannelMode
;
1081 if ((NULL
== This
) ||
1082 (NULL
== HostAddress
) ||
1083 (NULL
== NumberOfBytes
) ||
1084 (NULL
== DeviceAddress
) ||
1087 return EFI_INVALID_PARAMETER
;
1091 // Initialize the return values to their defaults
1096 // Make sure the Operation parameter is valid.
1097 // Light IsaIo only supports two operations.
1099 if (!(Operation
== EfiIsaIoOperationSlaveRead
||
1100 Operation
== EfiIsaIoOperationSlaveWrite
)) {
1101 return EFI_INVALID_PARAMETER
;
1104 if (ChannelNumber
>= 4) {
1106 // The Light IsaIo doesn't support channelNumber larger than 4.
1108 return EFI_INVALID_PARAMETER
;
1112 // Map the HostAddress to a DeviceAddress.
1114 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1115 if ((PhysicalAddress
+ *NumberOfBytes
) > BASE_16MB
) {
1117 // Common Buffer operations can not be remapped. If the common buffer
1118 // is above 16MB, then it is not possible to generate a mapping, so return
1121 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1122 return EFI_UNSUPPORTED
;
1125 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1128 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1129 if (IsaMapInfo
== NULL
) {
1131 return EFI_OUT_OF_RESOURCES
;
1134 // Return a pointer to the MAP_INFO structure in Mapping
1136 *Mapping
= IsaMapInfo
;
1139 // Initialize the MAP_INFO structure
1141 IsaMapInfo
->Operation
= Operation
;
1142 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
1143 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1144 IsaMapInfo
->HostAddress
= PhysicalAddress
;
1145 IsaMapInfo
->MappedHostAddress
= BASE_16MB
- 1;
1148 // Allocate a buffer below 16MB to map the transfer to.
1150 Status
= gBS
->AllocatePages (
1152 EfiBootServicesData
,
1153 IsaMapInfo
->NumberOfPages
,
1154 &IsaMapInfo
->MappedHostAddress
1156 if (EFI_ERROR (Status
)) {
1157 FreePool (IsaMapInfo
);
1163 // If this is a read operation from the DMA agents's point of view,
1164 // then copy the contents of the real buffer into the mapped buffer
1165 // so the DMA agent can read the contents of the real buffer.
1167 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1169 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1170 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1171 IsaMapInfo
->NumberOfBytes
1175 // The DeviceAddress is the address of the maped buffer below 16 MB
1177 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1180 // The transfer is below 16 MB, so the DeviceAddress is simply the
1183 *DeviceAddress
= PhysicalAddress
;
1187 // Figure out what to program into the DMA Channel Mode Register
1189 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1190 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1191 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1193 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1196 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
1198 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1201 // A Slave DMA transfer can not cross a 64K boundary.
1202 // Compute *NumberOfBytes based on this restriction.
1204 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1205 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1206 *NumberOfBytes
= MaxNumberOfBytes
;
1209 // Compute the values to program into the BaseAddress and Count registers
1210 // of the Slave DMA controller
1212 BaseAddress
= (UINT32
) (*DeviceAddress
);
1213 Count
= (UINT16
) (*NumberOfBytes
- 1);
1215 // Program the DMA Write Single Mask Register for ChannelNumber
1216 // Clear the DMA Byte Pointer Register
1218 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1219 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1220 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1222 Status
= WritePort (
1225 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1227 if (EFI_ERROR (Status
)) {
1231 Status
= WritePort (
1234 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1236 if (EFI_ERROR (Status
)) {
1240 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1241 if (EFI_ERROR (Status
)) {
1245 Status
= WriteDmaPort (
1247 mDmaRegisters
[ChannelNumber
].Address
,
1248 mDmaRegisters
[ChannelNumber
].Page
,
1249 mDmaRegisters
[ChannelNumber
].Count
,
1253 if (EFI_ERROR (Status
)) {
1257 Status
= WritePort (
1260 (UINT8
) (ChannelNumber
& 0x03)
1262 if (EFI_ERROR (Status
)) {
1270 Maps a memory region for DMA. This implementation implement the
1271 the full mapping support.
1273 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1274 @param Operation Indicates the type of DMA (slave or bus master), and if
1275 the DMA operation is going to read or write to system memory.
1276 @param ChannelNumber The slave channel number to use for this DMA operation.
1277 If Operation and ChannelAttributes shows that this device
1278 performs bus mastering DMA, then this field is ignored.
1279 The legal range for this field is 0..7.
1280 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
1281 @param HostAddress The system memory address to map to the device.
1282 @param NumberOfBytes On input the number of bytes to map. On output the number
1283 of bytes that were mapped.
1284 @param DeviceAddress The resulting map address for the bus master device to use
1285 to access the hosts HostAddress.
1286 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
1288 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1289 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1290 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1291 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1292 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1295 IsaIoMapFullSupport (
1296 IN EFI_ISA_IO_PROTOCOL
*This
,
1297 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1298 IN UINT8 ChannelNumber OPTIONAL
,
1299 IN UINT32 ChannelAttributes
,
1300 IN VOID
*HostAddress
,
1301 IN OUT UINTN
*NumberOfBytes
,
1302 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1309 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1310 ISA_MAP_INFO
*IsaMapInfo
;
1312 UINTN MaxNumberOfBytes
;
1317 UINT8 DmaChannelMode
;
1319 if ((NULL
== This
) ||
1320 (NULL
== HostAddress
) ||
1321 (NULL
== NumberOfBytes
) ||
1322 (NULL
== DeviceAddress
) ||
1325 return EFI_INVALID_PARAMETER
;
1329 // Initialize the return values to their defaults
1334 // Make sure the Operation parameter is valid
1336 if ((UINT32
)Operation
>= EfiIsaIoOperationMaximum
) {
1337 return EFI_INVALID_PARAMETER
;
1340 if (ChannelNumber
>= 8) {
1341 return EFI_INVALID_PARAMETER
;
1345 // See if this is a Slave DMA Operation
1349 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1350 Operation
= EfiIsaIoOperationBusMasterRead
;
1355 if (Operation
== EfiIsaIoOperationSlaveWrite
) {
1356 Operation
= EfiIsaIoOperationBusMasterWrite
;
1363 // Make sure that ChannelNumber is a valid channel number
1364 // Channel 4 is used to cascade, so it is illegal.
1366 if (ChannelNumber
== 4 || ChannelNumber
> 7) {
1367 return EFI_INVALID_PARAMETER
;
1370 // This implementation only support COMPATIBLE DMA Transfers
1372 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE
) == 0) {
1373 return EFI_INVALID_PARAMETER
;
1376 if ((ChannelAttributes
&
1377 (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A
|
1378 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B
|
1379 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C
)) != 0) {
1380 return EFI_INVALID_PARAMETER
;
1383 if (ChannelNumber
< 4) {
1385 // If this is Channel 0..3, then the width must be 8 bit
1387 if (((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) == 0) ||
1388 ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
) != 0)
1390 return EFI_INVALID_PARAMETER
;
1394 // If this is Channel 4..7, then the width must be 16 bit
1396 if (((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) != 0) ||
1397 ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
) == 0)) {
1398 return EFI_INVALID_PARAMETER
;
1402 // Either Demand Mode or Single Mode must be selected, but not both
1404 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) != 0) {
1405 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) != 0) {
1406 return EFI_INVALID_PARAMETER
;
1409 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) == 0) {
1410 return EFI_INVALID_PARAMETER
;
1415 // Map the HostAddress to a DeviceAddress.
1417 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1418 if ((PhysicalAddress
+*NumberOfBytes
) > BASE_16MB
) {
1420 // Common Buffer operations can not be remapped. If the common buffer
1421 // is above 16MB, then it is not possible to generate a mapping, so return
1424 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1425 return EFI_UNSUPPORTED
;
1428 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1431 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1432 if (IsaMapInfo
== NULL
) {
1434 return EFI_OUT_OF_RESOURCES
;
1437 // Return a pointer to the MAP_INFO structure in Mapping
1439 *Mapping
= IsaMapInfo
;
1442 // Initialize the MAP_INFO structure
1444 IsaMapInfo
->Operation
= Operation
;
1445 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
1446 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1447 IsaMapInfo
->HostAddress
= PhysicalAddress
;
1448 IsaMapInfo
->MappedHostAddress
= BASE_16MB
- 1;
1451 // Allocate a buffer below 16MB to map the transfer to.
1453 Status
= gBS
->AllocatePages (
1455 EfiBootServicesData
,
1456 IsaMapInfo
->NumberOfPages
,
1457 &IsaMapInfo
->MappedHostAddress
1459 if (EFI_ERROR (Status
)) {
1460 FreePool (IsaMapInfo
);
1466 // If this is a read operation from the DMA agents's point of view,
1467 // then copy the contents of the real buffer into the mapped buffer
1468 // so the DMA agent can read the contents of the real buffer.
1470 if (Operation
== EfiIsaIoOperationBusMasterRead
) {
1472 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1473 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1474 IsaMapInfo
->NumberOfBytes
1478 // The DeviceAddress is the address of the maped buffer below 16 MB
1480 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1483 // The transfer is below 16 MB, so the DeviceAddress is simply the
1486 *DeviceAddress
= PhysicalAddress
;
1489 // If this is a Bus Master operation then return
1495 // Figure out what to program into the DMA Channel Mode Register
1497 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1499 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1501 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1504 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE
) != 0) {
1505 DmaMode
|= B_8237_DMA_CHMODE_AE
;
1508 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) != 0) {
1509 DmaMode
|= V_8237_DMA_CHMODE_DEMAND
;
1512 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) != 0) {
1513 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1516 // A Slave DMA transfer can not cross a 64K boundary.
1517 // Compute *NumberOfBytes based on this restriction.
1519 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1520 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1521 *NumberOfBytes
= MaxNumberOfBytes
;
1524 // Compute the values to program into the BaseAddress and Count registers
1525 // of the Slave DMA controller
1527 if (ChannelNumber
< 4) {
1528 BaseAddress
= (UINT32
) (*DeviceAddress
);
1529 Count
= (UINT16
) (*NumberOfBytes
- 1);
1531 BaseAddress
= (UINT32
) (((UINT32
) (*DeviceAddress
) & 0xff0000) | (((UINT32
) (*DeviceAddress
) & 0xffff) >> 1));
1532 Count
= (UINT16
) ((*NumberOfBytes
- 1) >> 1);
1535 // Program the DMA Write Single Mask Register for ChannelNumber
1536 // Clear the DMA Byte Pointer Register
1538 if (ChannelNumber
< 4) {
1539 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1540 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1541 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1543 DmaMask
= R_8237_DMA_WRSMSK_CH4_7
;
1544 DmaClear
= R_8237_DMA_CBPR_CH4_7
;
1545 DmaChannelMode
= R_8237_DMA_CHMODE_CH4_7
;
1548 Status
= WritePort (
1551 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1553 if (EFI_ERROR (Status
)) {
1557 Status
= WritePort (
1560 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1562 if (EFI_ERROR (Status
)) {
1566 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1567 if (EFI_ERROR (Status
)) {
1571 Status
= WriteDmaPort (
1573 mDmaRegisters
[ChannelNumber
].Address
,
1574 mDmaRegisters
[ChannelNumber
].Page
,
1575 mDmaRegisters
[ChannelNumber
].Count
,
1579 if (EFI_ERROR (Status
)) {
1583 Status
= WritePort (
1586 (UINT8
) (ChannelNumber
& 0x03)
1588 if (EFI_ERROR (Status
)) {
1596 Maps a memory region for DMA
1598 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1599 @param Operation Indicates the type of DMA (slave or bus master), and if
1600 the DMA operation is going to read or write to system memory.
1601 @param ChannelNumber The slave channel number to use for this DMA operation.
1602 If Operation and ChannelAttributes shows that this device
1603 performs bus mastering DMA, then this field is ignored.
1604 The legal range for this field is 0..7.
1605 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
1606 @param HostAddress The system memory address to map to the device.
1607 @param NumberOfBytes On input the number of bytes to map. On output the number
1608 of bytes that were mapped.
1609 @param DeviceAddress The resulting map address for the bus master device to use
1610 to access the hosts HostAddress.
1611 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
1613 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
1614 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
1615 @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.
1616 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1617 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1622 IN EFI_ISA_IO_PROTOCOL
*This
,
1623 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1624 IN UINT8 ChannelNumber OPTIONAL
,
1625 IN UINT32 ChannelAttributes
,
1626 IN VOID
*HostAddress
,
1627 IN OUT UINTN
*NumberOfBytes
,
1628 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1633 // Check if DMA is supported.
1635 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) {
1636 return EFI_UNSUPPORTED
;
1639 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1642 // So we just return EFI_UNSUPPORTED for these functions.
1644 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA
) != 0) {
1645 return IsaIoMapOnlySupportSlaveReadWrite (
1657 return IsaIoMapFullSupport (
1671 Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping.
1673 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1674 @param[in] Type The type allocation to perform.
1675 @param[in] MemoryType The type of memory to allocate.
1676 @param[in] Pages The number of pages to allocate.
1677 @param[out] HostAddress A pointer to store the base address of the allocated range.
1678 @param[in] Attributes The requested bit mask of attributes for the allocated range.
1680 @retval EFI_SUCCESS The requested memory pages were allocated.
1681 @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL
1682 @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified
1683 by HostAddress, Pages, and Type is not available for common buffer use.
1684 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1688 IsaIoAllocateBuffer (
1689 IN EFI_ISA_IO_PROTOCOL
*This
,
1690 IN EFI_ALLOCATE_TYPE Type
,
1691 IN EFI_MEMORY_TYPE MemoryType
,
1693 OUT VOID
**HostAddress
,
1694 IN UINT64 Attributes
1698 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1701 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1703 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1705 if (((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) ||
1706 ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA
) != 0)) {
1707 return EFI_UNSUPPORTED
;
1710 if (HostAddress
== NULL
) {
1711 return EFI_INVALID_PARAMETER
;
1714 if ((UINT32
)Type
>= MaxAllocateType
) {
1715 return EFI_INVALID_PARAMETER
;
1718 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1720 if (MemoryType
!= EfiBootServicesData
&& MemoryType
!= EfiRuntimeServicesData
) {
1721 return EFI_INVALID_PARAMETER
;
1724 if ((Attributes
& ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
| EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED
)) != 0) {
1725 return EFI_UNSUPPORTED
;
1728 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) (BASE_16MB
- 1);
1729 if (Type
== AllocateAddress
) {
1730 if ((UINTN
) (*HostAddress
) >= BASE_16MB
) {
1731 return EFI_UNSUPPORTED
;
1733 PhysicalAddress
= (UINTN
) (*HostAddress
);
1737 if (Type
== AllocateAnyPages
) {
1738 Type
= AllocateMaxAddress
;
1741 Status
= gBS
->AllocatePages (Type
, MemoryType
, Pages
, &PhysicalAddress
);
1742 if (EFI_ERROR (Status
)) {
1743 REPORT_STATUS_CODE (
1744 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1745 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
1750 *HostAddress
= (VOID
*) (UINTN
) PhysicalAddress
;
1755 Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer().
1757 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1758 @param[in] Pages The number of pages to free.
1759 @param[in] HostAddress The base address of the allocated range.
1761 @retval EFI_SUCCESS The requested memory pages were freed.
1762 @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1767 IN EFI_ISA_IO_PROTOCOL
*This
,
1769 IN VOID
*HostAddress
1775 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1777 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1779 if (((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) ||
1780 ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA
) != 0)) {
1781 return EFI_UNSUPPORTED
;
1784 Status
= gBS
->FreePages (
1785 (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
,
1788 if (EFI_ERROR (Status
)) {
1789 REPORT_STATUS_CODE (
1790 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1791 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR