2 The implementation for EFI_ISA_IO_PROTOCOL.
4 Copyright (c) 2010 - 2018, 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 ((UINT32
)Width
>= EfiIsaIoWidthMaximum
||
109 Width
== EfiIsaIoWidthReserved
||
110 Width
== EfiIsaIoWidthFifoReserved
||
111 Width
== EfiIsaIoWidthFillReserved
113 return EFI_INVALID_PARAMETER
;
117 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
118 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
120 if (Width
>= EfiIsaIoWidthFifoUint8
&& Width
< EfiIsaIoWidthFifoReserved
) {
124 Width
= (EFI_ISA_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
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
) {
135 if (Offset
>= Item
->StartRange
&& Offset
<= Item
->EndRange
) {
136 Status
= EFI_INVALID_PARAMETER
;
147 Convert the IO Information in ACPI descriptor to IO ISA Attribute.
149 @param[in] Information The IO Information in ACPI descriptor
151 @return UINT32 The IO ISA Attribute
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
;
167 case EFI_ACPI_IO_DECODE_10_BIT
:
168 Attribute
|= EFI_ISA_ACPI_IO_DECODE_10_BITS
;
176 Convert the IRQ Information in ACPI descriptor to IRQ ISA Attribute.
178 @param[in] Information The IRQ Information in ACPI descriptor
180 @return UINT32 The IRQ ISA Attribute
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
;
195 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE
;
198 if ((Information
& EFI_ACPI_IRQ_MODE
) == EFI_ACPI_IRQ_LEVEL_TRIGGERED
) {
199 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE
;
201 Attribute
= EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE
;
208 Convert the Memory Information in ACPI descriptor to Memory ISA Attribute.
210 @param[in] Information The Memory Information in ACPI descriptor
212 @return UINT32 The Memory ISA Attribute
223 switch (Information
& EFI_ACPI_MEMORY_WRITE_STATUS_MASK
) {
224 case EFI_ACPI_MEMORY_WRITABLE
:
225 Attribute
|= EFI_ISA_ACPI_MEMORY_WRITEABLE
;
233 Convert the DMA Information in ACPI descriptor to DMA ISA Attribute.
235 @param[in] Information The DMA Information in ACPI descriptor
237 @return UINT32 The DMA ISA Attribute
246 Attribute
= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
;
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
;
252 case EFI_ACPI_DMA_SPEED_TYPE_A
:
253 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A
;
255 case EFI_ACPI_DMA_SPEED_TYPE_B
:
256 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B
;
258 case EFI_ACPI_DMA_SPEED_TYPE_F
:
259 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C
;
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
;
267 case EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT
:
268 Attribute
|= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
;
276 Convert the ACPI resource descriptor to ISA resource descriptor.
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
282 @return UINTN Number of ISA resource descriptor needed
285 AcpiResourceToIsaResource (
286 IN ACPI_RESOURCE_HEADER_PTR AcpiResource
,
287 OUT EFI_ISA_ACPI_RESOURCE
*IsaResource OPTIONAL
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
;
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
++;
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
;
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;
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;
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
++;
363 if (IsaResource
!= NULL
) {
364 IsaResource
[Count
].Type
= EfiIsaAcpiResourceInterrupt
;
365 if (AcpiResource
.SmallHeader
->Byte
== ACPI_IRQ_DESCRIPTOR
) {
366 IsaResource
[Count
].Attribute
= IsaIrqAttribute (Irq
->Information
);
368 IsaResource
[Count
].Attribute
= EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE
;
370 IsaResource
[Count
].StartRange
= Index
;
371 IsaResource
[Count
].EndRange
= Index
;
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;
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;
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;
422 Initializes an ISA I/O Instance
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.
430 InitializeIsaIoInstance (
431 IN ISA_IO_DEVICE
*IsaIoDevice
,
432 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
433 IN ACPI_RESOURCE_HEADER_PTR Resources
437 ACPI_HID_DEVICE_PATH
*AcpiNode
;
438 ACPI_RESOURCE_HEADER_PTR ResourcePtr
;
441 // Use the ISA IO Protocol structure template to initialize the ISA IO instance
446 sizeof (EFI_ISA_IO_PROTOCOL
)
450 // Count the resources including the ACPI End Tag
452 ResourcePtr
= Resources
;
454 while (ResourcePtr
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
456 Index
+= AcpiResourceToIsaResource (ResourcePtr
, NULL
);
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
));
463 ResourcePtr
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.LargeHeader
464 + ResourcePtr
.LargeHeader
->Length
465 + sizeof (*ResourcePtr
.LargeHeader
));
470 // Get the Isa Resource count for ACPI End Tag
472 Index
+= AcpiResourceToIsaResource (ResourcePtr
, NULL
);
475 // Initialize the ResourceList
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);
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
;
485 ResourcePtr
= Resources
;
487 while (ResourcePtr
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
489 Index
+= AcpiResourceToIsaResource (ResourcePtr
, &IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
[Index
]);
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
));
496 ResourcePtr
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.LargeHeader
497 + ResourcePtr
.LargeHeader
->Length
498 + sizeof (*ResourcePtr
.LargeHeader
));
503 // Convert the ACPI End Tag
505 AcpiResourceToIsaResource (ResourcePtr
, &IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
[Index
]);
509 Performs an ISA I/O Read Cycle
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
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.
525 IN EFI_ISA_IO_PROTOCOL
*This
,
526 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
533 ISA_IO_DEVICE
*IsaIoDevice
;
535 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
538 // Verify Isa IO Access
540 Status
= IsaIoVerifyAccess (
547 if (EFI_ERROR (Status
)) {
551 Status
= IsaIoDevice
->PciIo
->Io
.Read (
553 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
554 EFI_PCI_IO_PASS_THROUGH_BAR
,
560 if (EFI_ERROR (Status
)) {
562 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
563 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
571 Performs an ISA I/O Write Cycle
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
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.
587 IN EFI_ISA_IO_PROTOCOL
*This
,
588 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
595 ISA_IO_DEVICE
*IsaIoDevice
;
597 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
600 // Verify Isa IO Access
602 Status
= IsaIoVerifyAccess (
609 if (EFI_ERROR (Status
)) {
613 Status
= IsaIoDevice
->PciIo
->Io
.Write (
615 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
616 EFI_PCI_IO_PASS_THROUGH_BAR
,
622 if (EFI_ERROR (Status
)) {
624 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
625 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
633 Writes an 8-bit I/O Port
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.
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.
646 IN EFI_ISA_IO_PROTOCOL
*This
,
652 ISA_IO_DEVICE
*IsaIoDevice
;
654 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
656 Status
= IsaIoDevice
->PciIo
->Io
.Write (
659 EFI_PCI_IO_PASS_THROUGH_BAR
,
664 if (EFI_ERROR (Status
)) {
666 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
667 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
673 // Wait for 50 microseconds to take affect.
681 Writes I/O operation base address and count number to a 8 bit I/O Port.
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.
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.
697 IN EFI_ISA_IO_PROTOCOL
*This
,
698 IN UINT32 AddrOffset
,
699 IN UINT32 PageOffset
,
700 IN UINT32 CountOffset
,
701 IN UINT32 BaseAddress
,
707 Status
= WritePort (This
, AddrOffset
, (UINT8
) (BaseAddress
& 0xff));
708 if (EFI_ERROR (Status
)) {
712 Status
= WritePort (This
, AddrOffset
, (UINT8
) ((BaseAddress
>> 8) & 0xff));
713 if (EFI_ERROR (Status
)) {
717 Status
= WritePort (This
, PageOffset
, (UINT8
) ((BaseAddress
>> 16) & 0xff));
718 if (EFI_ERROR (Status
)) {
722 Status
= WritePort (This
, CountOffset
, (UINT8
) (Count
& 0xff));
723 if (EFI_ERROR (Status
)) {
727 Status
= WritePort (This
, CountOffset
, (UINT8
) ((Count
>> 8) & 0xff));
732 Unmaps a memory region for DMA
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().
737 @retval EFI_SUCCESS The range was unmapped.
738 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
743 IN EFI_ISA_IO_PROTOCOL
*This
,
747 ISA_MAP_INFO
*IsaMapInfo
;
750 // Check if DMA is supported.
752 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) {
753 return EFI_UNSUPPORTED
;
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.
761 if (Mapping
!= NULL
) {
763 // Get the MAP_INFO structure from Mapping
765 IsaMapInfo
= (ISA_MAP_INFO
*) Mapping
;
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.
772 if (IsaMapInfo
->Operation
== EfiIsaIoOperationBusMasterWrite
) {
774 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
775 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
776 IsaMapInfo
->NumberOfBytes
780 // Free the mapped buffer and the MAP_INFO structure.
782 gBS
->FreePages (IsaMapInfo
->MappedHostAddress
, IsaMapInfo
->NumberOfPages
);
783 FreePool (IsaMapInfo
);
790 Flushes any posted write data to the system memory.
792 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
794 @retval EFI_SUCCESS The buffers were flushed.
795 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error.
800 IN EFI_ISA_IO_PROTOCOL
*This
804 ISA_IO_DEVICE
*IsaIoDevice
;
806 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
808 Status
= IsaIoDevice
->PciIo
->Flush (IsaIoDevice
->PciIo
);
810 if (EFI_ERROR (Status
)) {
812 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
813 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
821 Performs an ISA Memory Read Cycle
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
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.
837 IN EFI_ISA_IO_PROTOCOL
*This
,
838 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
845 ISA_IO_DEVICE
*IsaIoDevice
;
848 // Check if ISA memory is supported.
850 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
851 return EFI_UNSUPPORTED
;
854 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
857 // Verify the Isa Io Access
859 Status
= IsaIoVerifyAccess (
866 if (EFI_ERROR (Status
)) {
870 Status
= IsaIoDevice
->PciIo
->Mem
.Read (
872 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
873 EFI_PCI_IO_PASS_THROUGH_BAR
,
879 if (EFI_ERROR (Status
)) {
881 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
882 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
890 Performs an ISA Memory Write Cycle
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
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.
906 IN EFI_ISA_IO_PROTOCOL
*This
,
907 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
914 ISA_IO_DEVICE
*IsaIoDevice
;
917 // Check if ISA memory is supported.
919 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
920 return EFI_UNSUPPORTED
;
923 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
926 // Verify Isa IO Access
928 Status
= IsaIoVerifyAccess (
935 if (EFI_ERROR (Status
)) {
939 Status
= IsaIoDevice
->PciIo
->Mem
.Write (
941 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
942 EFI_PCI_IO_PASS_THROUGH_BAR
,
948 if (EFI_ERROR (Status
)) {
950 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
951 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
959 Copy one region of ISA memory space to another region of ISA memory space on the ISA controller.
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
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.
975 IN EFI_ISA_IO_PROTOCOL
*This
,
976 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
977 IN UINT32 DestOffset
,
983 ISA_IO_DEVICE
*IsaIoDevice
;
986 // Check if ISA memory is supported.
988 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
989 return EFI_UNSUPPORTED
;
992 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
995 // Verify Isa IO Access for destination and source
997 Status
= IsaIoVerifyAccess (
1004 if (EFI_ERROR (Status
)) {
1008 Status
= IsaIoVerifyAccess (
1015 if (EFI_ERROR (Status
)) {
1019 Status
= IsaIoDevice
->PciIo
->CopyMem (
1021 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
1022 EFI_PCI_IO_PASS_THROUGH_BAR
,
1024 EFI_PCI_IO_PASS_THROUGH_BAR
,
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
1040 Maps a memory region for DMA, note this implementation
1041 only supports slave read/write operation to save code size.
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().
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.
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
,
1077 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1078 ISA_MAP_INFO
*IsaMapInfo
;
1080 UINTN MaxNumberOfBytes
;
1085 UINT8 DmaChannelMode
;
1087 if ((NULL
== This
) ||
1088 (NULL
== HostAddress
) ||
1089 (NULL
== NumberOfBytes
) ||
1090 (NULL
== DeviceAddress
) ||
1093 return EFI_INVALID_PARAMETER
;
1097 // Initialize the return values to their defaults
1102 // Make sure the Operation parameter is valid.
1103 // Light IsaIo only supports two operations.
1105 if (!(Operation
== EfiIsaIoOperationSlaveRead
||
1106 Operation
== EfiIsaIoOperationSlaveWrite
)) {
1107 return EFI_INVALID_PARAMETER
;
1110 if (ChannelNumber
>= 4) {
1112 // The Light IsaIo doesn't support channelNumber larger than 4.
1114 return EFI_INVALID_PARAMETER
;
1118 // Map the HostAddress to a DeviceAddress.
1120 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1121 if ((PhysicalAddress
+ *NumberOfBytes
) > BASE_16MB
) {
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
1127 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1128 return EFI_UNSUPPORTED
;
1131 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1134 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1135 if (IsaMapInfo
== NULL
) {
1137 return EFI_OUT_OF_RESOURCES
;
1140 // Return a pointer to the MAP_INFO structure in Mapping
1142 *Mapping
= IsaMapInfo
;
1145 // Initialize the MAP_INFO structure
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;
1154 // Allocate a buffer below 16MB to map the transfer to.
1156 Status
= gBS
->AllocatePages (
1158 EfiBootServicesData
,
1159 IsaMapInfo
->NumberOfPages
,
1160 &IsaMapInfo
->MappedHostAddress
1162 if (EFI_ERROR (Status
)) {
1163 FreePool (IsaMapInfo
);
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.
1173 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1175 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1176 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1177 IsaMapInfo
->NumberOfBytes
1181 // The DeviceAddress is the address of the maped buffer below 16 MB
1183 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1186 // The transfer is below 16 MB, so the DeviceAddress is simply the
1189 *DeviceAddress
= PhysicalAddress
;
1193 // Figure out what to program into the DMA Channel Mode Register
1195 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1196 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1197 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1199 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1202 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
1204 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1207 // A Slave DMA transfer can not cross a 64K boundary.
1208 // Compute *NumberOfBytes based on this restriction.
1210 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1211 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1212 *NumberOfBytes
= MaxNumberOfBytes
;
1215 // Compute the values to program into the BaseAddress and Count registers
1216 // of the Slave DMA controller
1218 BaseAddress
= (UINT32
) (*DeviceAddress
);
1219 Count
= (UINT16
) (*NumberOfBytes
- 1);
1221 // Program the DMA Write Single Mask Register for ChannelNumber
1222 // Clear the DMA Byte Pointer Register
1224 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1225 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1226 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1228 Status
= WritePort (
1231 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1233 if (EFI_ERROR (Status
)) {
1237 Status
= WritePort (
1240 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1242 if (EFI_ERROR (Status
)) {
1246 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1247 if (EFI_ERROR (Status
)) {
1251 Status
= WriteDmaPort (
1253 mDmaRegisters
[ChannelNumber
].Address
,
1254 mDmaRegisters
[ChannelNumber
].Page
,
1255 mDmaRegisters
[ChannelNumber
].Count
,
1259 if (EFI_ERROR (Status
)) {
1263 Status
= WritePort (
1266 (UINT8
) (ChannelNumber
& 0x03)
1268 if (EFI_ERROR (Status
)) {
1276 Maps a memory region for DMA. This implementation implement the
1277 the full mapping support.
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().
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.
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
,
1315 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1316 ISA_MAP_INFO
*IsaMapInfo
;
1318 UINTN MaxNumberOfBytes
;
1323 UINT8 DmaChannelMode
;
1325 if ((NULL
== This
) ||
1326 (NULL
== HostAddress
) ||
1327 (NULL
== NumberOfBytes
) ||
1328 (NULL
== DeviceAddress
) ||
1331 return EFI_INVALID_PARAMETER
;
1335 // Initialize the return values to their defaults
1340 // Make sure the Operation parameter is valid
1342 if ((UINT32
)Operation
>= EfiIsaIoOperationMaximum
) {
1343 return EFI_INVALID_PARAMETER
;
1346 if (ChannelNumber
>= 8) {
1347 return EFI_INVALID_PARAMETER
;
1351 // See if this is a Slave DMA Operation
1355 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1356 Operation
= EfiIsaIoOperationBusMasterRead
;
1361 if (Operation
== EfiIsaIoOperationSlaveWrite
) {
1362 Operation
= EfiIsaIoOperationBusMasterWrite
;
1369 // Make sure that ChannelNumber is a valid channel number
1370 // Channel 4 is used to cascade, so it is illegal.
1372 if (ChannelNumber
== 4 || ChannelNumber
> 7) {
1373 return EFI_INVALID_PARAMETER
;
1376 // This implementation only support COMPATIBLE DMA Transfers
1378 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE
) == 0) {
1379 return EFI_INVALID_PARAMETER
;
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
;
1389 if (ChannelNumber
< 4) {
1391 // If this is Channel 0..3, then the width must be 8 bit
1393 if (((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) == 0) ||
1394 ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
) != 0)
1396 return EFI_INVALID_PARAMETER
;
1400 // If this is Channel 4..7, then the width must be 16 bit
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
;
1408 // Either Demand Mode or Single Mode must be selected, but not both
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
;
1415 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) == 0) {
1416 return EFI_INVALID_PARAMETER
;
1421 // Map the HostAddress to a DeviceAddress.
1423 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1424 if ((PhysicalAddress
+*NumberOfBytes
) > BASE_16MB
) {
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
1430 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1431 return EFI_UNSUPPORTED
;
1434 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1437 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1438 if (IsaMapInfo
== NULL
) {
1440 return EFI_OUT_OF_RESOURCES
;
1443 // Return a pointer to the MAP_INFO structure in Mapping
1445 *Mapping
= IsaMapInfo
;
1448 // Initialize the MAP_INFO structure
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;
1457 // Allocate a buffer below 16MB to map the transfer to.
1459 Status
= gBS
->AllocatePages (
1461 EfiBootServicesData
,
1462 IsaMapInfo
->NumberOfPages
,
1463 &IsaMapInfo
->MappedHostAddress
1465 if (EFI_ERROR (Status
)) {
1466 FreePool (IsaMapInfo
);
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.
1476 if (Operation
== EfiIsaIoOperationBusMasterRead
) {
1478 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1479 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1480 IsaMapInfo
->NumberOfBytes
1484 // The DeviceAddress is the address of the maped buffer below 16 MB
1486 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1489 // The transfer is below 16 MB, so the DeviceAddress is simply the
1492 *DeviceAddress
= PhysicalAddress
;
1495 // If this is a Bus Master operation then return
1501 // Figure out what to program into the DMA Channel Mode Register
1503 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1505 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1507 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1510 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE
) != 0) {
1511 DmaMode
|= B_8237_DMA_CHMODE_AE
;
1514 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) != 0) {
1515 DmaMode
|= V_8237_DMA_CHMODE_DEMAND
;
1518 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) != 0) {
1519 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1522 // A Slave DMA transfer can not cross a 64K boundary.
1523 // Compute *NumberOfBytes based on this restriction.
1525 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1526 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1527 *NumberOfBytes
= MaxNumberOfBytes
;
1530 // Compute the values to program into the BaseAddress and Count registers
1531 // of the Slave DMA controller
1533 if (ChannelNumber
< 4) {
1534 BaseAddress
= (UINT32
) (*DeviceAddress
);
1535 Count
= (UINT16
) (*NumberOfBytes
- 1);
1537 BaseAddress
= (UINT32
) (((UINT32
) (*DeviceAddress
) & 0xff0000) | (((UINT32
) (*DeviceAddress
) & 0xffff) >> 1));
1538 Count
= (UINT16
) ((*NumberOfBytes
- 1) >> 1);
1541 // Program the DMA Write Single Mask Register for ChannelNumber
1542 // Clear the DMA Byte Pointer Register
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
;
1549 DmaMask
= R_8237_DMA_WRSMSK_CH4_7
;
1550 DmaClear
= R_8237_DMA_CBPR_CH4_7
;
1551 DmaChannelMode
= R_8237_DMA_CHMODE_CH4_7
;
1554 Status
= WritePort (
1557 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1559 if (EFI_ERROR (Status
)) {
1563 Status
= WritePort (
1566 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1568 if (EFI_ERROR (Status
)) {
1572 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1573 if (EFI_ERROR (Status
)) {
1577 Status
= WriteDmaPort (
1579 mDmaRegisters
[ChannelNumber
].Address
,
1580 mDmaRegisters
[ChannelNumber
].Page
,
1581 mDmaRegisters
[ChannelNumber
].Count
,
1585 if (EFI_ERROR (Status
)) {
1589 Status
= WritePort (
1592 (UINT8
) (ChannelNumber
& 0x03)
1594 if (EFI_ERROR (Status
)) {
1602 Maps a memory region for DMA
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().
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.
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
,
1639 // Check if DMA is supported.
1641 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) {
1642 return EFI_UNSUPPORTED
;
1645 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1648 // So we just return EFI_UNSUPPORTED for these functions.
1650 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA
) != 0) {
1651 return IsaIoMapOnlySupportSlaveReadWrite (
1663 return IsaIoMapFullSupport (
1677 Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping.
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.
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.
1694 IsaIoAllocateBuffer (
1695 IN EFI_ISA_IO_PROTOCOL
*This
,
1696 IN EFI_ALLOCATE_TYPE Type
,
1697 IN EFI_MEMORY_TYPE MemoryType
,
1699 OUT VOID
**HostAddress
,
1700 IN UINT64 Attributes
1704 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1707 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1709 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
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
;
1716 if (HostAddress
== NULL
) {
1717 return EFI_INVALID_PARAMETER
;
1720 if ((UINT32
)Type
>= MaxAllocateType
) {
1721 return EFI_INVALID_PARAMETER
;
1724 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1726 if (MemoryType
!= EfiBootServicesData
&& MemoryType
!= EfiRuntimeServicesData
) {
1727 return EFI_INVALID_PARAMETER
;
1730 if ((Attributes
& ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
| EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED
)) != 0) {
1731 return EFI_UNSUPPORTED
;
1734 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) (BASE_16MB
- 1);
1735 if (Type
== AllocateAddress
) {
1736 if ((UINTN
) (*HostAddress
) >= BASE_16MB
) {
1737 return EFI_UNSUPPORTED
;
1739 PhysicalAddress
= (UINTN
) (*HostAddress
);
1743 if (Type
== AllocateAnyPages
) {
1744 Type
= AllocateMaxAddress
;
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
1756 *HostAddress
= (VOID
*) (UINTN
) PhysicalAddress
;
1761 Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer().
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.
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().
1773 IN EFI_ISA_IO_PROTOCOL
*This
,
1775 IN VOID
*HostAddress
1781 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1783 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
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
;
1790 Status
= gBS
->FreePages (
1791 (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
,
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