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 (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;
339 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
:
340 FixedIo
= (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*) AcpiResource
.SmallHeader
;
341 if (IsaResource
!= NULL
) {
342 IsaResource
[Count
].Type
= EfiIsaAcpiResourceIo
;
343 IsaResource
[Count
].Attribute
= EFI_ISA_ACPI_IO_DECODE_10_BITS
;
344 IsaResource
[Count
].StartRange
= FixedIo
->BaseAddress
;
345 IsaResource
[Count
].EndRange
= FixedIo
->BaseAddress
+ FixedIo
->Length
- 1;
350 case ACPI_IRQ_DESCRIPTOR
:
351 case ACPI_IRQ_NOFLAG_DESCRIPTOR
:
352 Irq
= (EFI_ACPI_IRQ_DESCRIPTOR
*) AcpiResource
.SmallHeader
;
353 for (Index
= 0; Index
< sizeof (Irq
->Mask
) * 8; Index
++) {
354 if (Irq
->Mask
& (1 << Index
)) {
355 if ((Count
> 0) && (LastIndex
+ 1 == Index
)) {
356 if (IsaResource
!= NULL
) {
357 IsaResource
[Count
- 1].EndRange
++;
360 if (IsaResource
!= NULL
) {
361 IsaResource
[Count
].Type
= EfiIsaAcpiResourceInterrupt
;
362 if (AcpiResource
.SmallHeader
->Byte
== ACPI_IRQ_DESCRIPTOR
) {
363 IsaResource
[Count
].Attribute
= IsaIrqAttribute (Irq
->Information
);
365 IsaResource
[Count
].Attribute
= EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE
;
367 IsaResource
[Count
].StartRange
= Index
;
368 IsaResource
[Count
].EndRange
= Index
;
378 case ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR
:
379 Memory
= (EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR
*) AcpiResource
.LargeHeader
;
380 if (IsaResource
!= NULL
) {
381 IsaResource
[Count
].Type
= EfiIsaAcpiResourceMemory
;
382 IsaResource
[Count
].Attribute
= IsaMemoryAttribute (Memory
->Information
);
383 IsaResource
[Count
].StartRange
= Memory
->BaseAddressMin
;
384 IsaResource
[Count
].EndRange
= Memory
->BaseAddressMin
+ Memory
->Length
- 1;
389 case ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR
:
390 FixedMemory
= (EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR
*) AcpiResource
.LargeHeader
;
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;
400 case ACPI_END_TAG_DESCRIPTOR
:
401 if (IsaResource
!= NULL
) {
402 IsaResource
[Count
].Type
= EfiIsaAcpiResourceEndOfList
;
403 IsaResource
[Count
].Attribute
= 0;
404 IsaResource
[Count
].StartRange
= 0;
405 IsaResource
[Count
].EndRange
= 0;
415 Initializes an ISA I/O Instance
417 @param[in] IsaIoDevice The isa device to be initialized.
418 @param[in] DevicePath The device path of the isa device.
419 @param[in] Resources The ACPI resource list.
423 InitializeIsaIoInstance (
424 IN ISA_IO_DEVICE
*IsaIoDevice
,
425 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
426 IN ACPI_RESOURCE_HEADER_PTR Resources
430 ACPI_HID_DEVICE_PATH
*AcpiNode
;
431 ACPI_RESOURCE_HEADER_PTR ResourcePtr
;
434 // Use the ISA IO Protocol structure template to initialize the ISA IO instance
439 sizeof (EFI_ISA_IO_PROTOCOL
)
443 // Count the resources including the ACPI End Tag
445 ResourcePtr
= Resources
;
447 while (ResourcePtr
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
449 Index
+= AcpiResourceToIsaResource (ResourcePtr
, NULL
);
451 if (ResourcePtr
.SmallHeader
->Bits
.Type
== 0) {
452 ResourcePtr
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.SmallHeader
453 + ResourcePtr
.SmallHeader
->Bits
.Length
454 + sizeof (*ResourcePtr
.SmallHeader
));
456 ResourcePtr
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.LargeHeader
457 + ResourcePtr
.LargeHeader
->Length
458 + sizeof (*ResourcePtr
.LargeHeader
));
463 // Get the Isa Resource count for ACPI End Tag
465 Index
+= AcpiResourceToIsaResource (ResourcePtr
, NULL
);
468 // Initialize the ResourceList
470 IsaIoDevice
->IsaIo
.ResourceList
= AllocatePool (sizeof (EFI_ISA_ACPI_RESOURCE_LIST
) + Index
* sizeof (EFI_ISA_ACPI_RESOURCE
));
471 ASSERT (IsaIoDevice
->IsaIo
.ResourceList
!= NULL
);
472 IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
= (EFI_ISA_ACPI_RESOURCE
*) (IsaIoDevice
->IsaIo
.ResourceList
+ 1);
474 AcpiNode
= (ACPI_HID_DEVICE_PATH
*) ((UINT8
*) DevicePath
+ GetDevicePathSize (DevicePath
) - END_DEVICE_PATH_LENGTH
- sizeof (ACPI_HID_DEVICE_PATH
));
475 IsaIoDevice
->IsaIo
.ResourceList
->Device
.HID
= AcpiNode
->HID
;
476 IsaIoDevice
->IsaIo
.ResourceList
->Device
.UID
= AcpiNode
->UID
;
478 ResourcePtr
= Resources
;
480 while (ResourcePtr
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
482 Index
+= AcpiResourceToIsaResource (ResourcePtr
, &IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
[Index
]);
484 if (ResourcePtr
.SmallHeader
->Bits
.Type
== 0) {
485 ResourcePtr
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.SmallHeader
486 + ResourcePtr
.SmallHeader
->Bits
.Length
487 + sizeof (*ResourcePtr
.SmallHeader
));
489 ResourcePtr
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) ResourcePtr
.LargeHeader
490 + ResourcePtr
.LargeHeader
->Length
491 + sizeof (*ResourcePtr
.LargeHeader
));
496 // Convert the ACPI End Tag
498 AcpiResourceToIsaResource (ResourcePtr
, &IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
[Index
]);
502 Performs an ISA I/O Read Cycle
504 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
505 @param[in] Width Specifies the width of the I/O operation.
506 @param[in] Offset The offset in ISA I/O space to start the I/O operation.
507 @param[in] Count The number of I/O operations to perform.
508 @param[out] Buffer The destination buffer to store the results
510 @retval EFI_SUCCESS The data was read from the device sucessfully.
511 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
512 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
513 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
518 IN EFI_ISA_IO_PROTOCOL
*This
,
519 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
526 ISA_IO_DEVICE
*IsaIoDevice
;
528 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
531 // Verify Isa IO Access
533 Status
= IsaIoVerifyAccess (
540 if (EFI_ERROR (Status
)) {
544 Status
= IsaIoDevice
->PciIo
->Io
.Read (
546 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
547 EFI_PCI_IO_PASS_THROUGH_BAR
,
553 if (EFI_ERROR (Status
)) {
555 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
556 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
564 Performs an ISA I/O Write Cycle
566 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
567 @param[in] Width Specifies the width of the I/O operation.
568 @param[in] Offset The offset in ISA I/O space to start the I/O operation.
569 @param[in] Count The number of I/O operations to perform.
570 @param[in] Buffer The source buffer to write data from
572 @retval EFI_SUCCESS The data was writen to the device sucessfully.
573 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
574 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
575 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
580 IN EFI_ISA_IO_PROTOCOL
*This
,
581 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
588 ISA_IO_DEVICE
*IsaIoDevice
;
590 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
593 // Verify Isa IO Access
595 Status
= IsaIoVerifyAccess (
602 if (EFI_ERROR (Status
)) {
606 Status
= IsaIoDevice
->PciIo
->Io
.Write (
608 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
609 EFI_PCI_IO_PASS_THROUGH_BAR
,
615 if (EFI_ERROR (Status
)) {
617 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
618 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
626 Writes an 8-bit I/O Port
628 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
629 @param[in] Offset The offset in ISA IO space to start the IO operation.
630 @param[in] Value The data to write port.
632 @retval EFI_SUCCESS Success.
633 @retval EFI_INVALID_PARAMETER Parameter is invalid.
634 @retval EFI_UNSUPPORTED The address range specified by Offset is not valid.
635 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
639 IN EFI_ISA_IO_PROTOCOL
*This
,
645 ISA_IO_DEVICE
*IsaIoDevice
;
647 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
649 Status
= IsaIoDevice
->PciIo
->Io
.Write (
652 EFI_PCI_IO_PASS_THROUGH_BAR
,
657 if (EFI_ERROR (Status
)) {
659 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
660 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
666 // Wait for 50 microseconds to take affect.
674 Writes I/O operation base address and count number to a 8 bit I/O Port.
676 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
677 @param[in] AddrOffset The address' offset.
678 @param[in] PageOffset The page's offest.
679 @param[in] CountOffset The count's offset.
680 @param[in] BaseAddress The base address.
681 @param[in] Count The number of I/O operations to perform.
683 @retval EFI_SUCCESS Success.
684 @retval EFI_INVALID_PARAMETER Parameter is invalid.
685 @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid.
686 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
690 IN EFI_ISA_IO_PROTOCOL
*This
,
691 IN UINT32 AddrOffset
,
692 IN UINT32 PageOffset
,
693 IN UINT32 CountOffset
,
694 IN UINT32 BaseAddress
,
700 Status
= WritePort (This
, AddrOffset
, (UINT8
) (BaseAddress
& 0xff));
701 if (EFI_ERROR (Status
)) {
705 Status
= WritePort (This
, AddrOffset
, (UINT8
) ((BaseAddress
>> 8) & 0xff));
706 if (EFI_ERROR (Status
)) {
710 Status
= WritePort (This
, PageOffset
, (UINT8
) ((BaseAddress
>> 16) & 0xff));
711 if (EFI_ERROR (Status
)) {
715 Status
= WritePort (This
, CountOffset
, (UINT8
) (Count
& 0xff));
716 if (EFI_ERROR (Status
)) {
720 Status
= WritePort (This
, CountOffset
, (UINT8
) ((Count
>> 8) & 0xff));
725 Unmaps a memory region for DMA
727 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
728 @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map().
730 @retval EFI_SUCCESS The range was unmapped.
731 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
736 IN EFI_ISA_IO_PROTOCOL
*This
,
740 ISA_MAP_INFO
*IsaMapInfo
;
743 // Check if DMA is supported.
745 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) {
746 return EFI_UNSUPPORTED
;
750 // See if the Map() operation associated with this Unmap() required a mapping
751 // buffer.If a mapping buffer was not required, then this function simply
752 // returns EFI_SUCCESS.
754 if (Mapping
!= NULL
) {
756 // Get the MAP_INFO structure from Mapping
758 IsaMapInfo
= (ISA_MAP_INFO
*) Mapping
;
761 // If this is a write operation from the Agent's point of view,
762 // then copy the contents of the mapped buffer into the real buffer
763 // so the processor can read the contents of the real buffer.
765 if (IsaMapInfo
->Operation
== EfiIsaIoOperationBusMasterWrite
) {
767 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
768 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
769 IsaMapInfo
->NumberOfBytes
773 // Free the mapped buffer and the MAP_INFO structure.
775 gBS
->FreePages (IsaMapInfo
->MappedHostAddress
, IsaMapInfo
->NumberOfPages
);
776 FreePool (IsaMapInfo
);
783 Flushes any posted write data to the system memory.
785 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
787 @retval EFI_SUCCESS The buffers were flushed.
788 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error.
793 IN EFI_ISA_IO_PROTOCOL
*This
797 ISA_IO_DEVICE
*IsaIoDevice
;
799 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
801 Status
= IsaIoDevice
->PciIo
->Flush (IsaIoDevice
->PciIo
);
803 if (EFI_ERROR (Status
)) {
805 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
806 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
814 Performs an ISA Memory Read Cycle
816 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
817 @param[in] Width Specifies the width of the memory operation.
818 @param[in] Offset The offset in ISA memory space to start the memory operation.
819 @param[in] Count The number of memory operations to perform.
820 @param[out] Buffer The destination buffer to store the results
822 @retval EFI_SUCCESS The data was read from the device successfully.
823 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
824 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
825 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
830 IN EFI_ISA_IO_PROTOCOL
*This
,
831 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
838 ISA_IO_DEVICE
*IsaIoDevice
;
841 // Check if ISA memory is supported.
843 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
844 return EFI_UNSUPPORTED
;
847 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
850 // Verify the Isa Io Access
852 Status
= IsaIoVerifyAccess (
859 if (EFI_ERROR (Status
)) {
863 Status
= IsaIoDevice
->PciIo
->Mem
.Read (
865 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
866 EFI_PCI_IO_PASS_THROUGH_BAR
,
872 if (EFI_ERROR (Status
)) {
874 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
875 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
883 Performs an ISA Memory Write Cycle
885 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
886 @param[in] Width Specifies the width of the memory operation.
887 @param[in] Offset The offset in ISA memory space to start the memory operation.
888 @param[in] Count The number of memory operations to perform.
889 @param[in] Buffer The source buffer to write data from
891 @retval EFI_SUCCESS The data was written to the device sucessfully.
892 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
893 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
894 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
899 IN EFI_ISA_IO_PROTOCOL
*This
,
900 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
907 ISA_IO_DEVICE
*IsaIoDevice
;
910 // Check if ISA memory is supported.
912 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
913 return EFI_UNSUPPORTED
;
916 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
919 // Verify Isa IO Access
921 Status
= IsaIoVerifyAccess (
928 if (EFI_ERROR (Status
)) {
932 Status
= IsaIoDevice
->PciIo
->Mem
.Write (
934 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
935 EFI_PCI_IO_PASS_THROUGH_BAR
,
941 if (EFI_ERROR (Status
)) {
943 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
944 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
952 Copy one region of ISA memory space to another region of ISA memory space on the ISA controller.
954 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
955 @param[in] Width Specifies the width of the memory copy operation.
956 @param[in] DestOffset The offset of the destination
957 @param[in] SrcOffset The offset of the source
958 @param[in] Count The number of memory copy operations to perform
960 @retval EFI_SUCCESS The data was copied sucessfully.
961 @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device.
962 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
963 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
968 IN EFI_ISA_IO_PROTOCOL
*This
,
969 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
970 IN UINT32 DestOffset
,
976 ISA_IO_DEVICE
*IsaIoDevice
;
979 // Check if ISA memory is supported.
981 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY
) == 0) {
982 return EFI_UNSUPPORTED
;
985 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
988 // Verify Isa IO Access for destination and source
990 Status
= IsaIoVerifyAccess (
997 if (EFI_ERROR (Status
)) {
1001 Status
= IsaIoVerifyAccess (
1008 if (EFI_ERROR (Status
)) {
1012 Status
= IsaIoDevice
->PciIo
->CopyMem (
1014 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
1015 EFI_PCI_IO_PASS_THROUGH_BAR
,
1017 EFI_PCI_IO_PASS_THROUGH_BAR
,
1022 if (EFI_ERROR (Status
)) {
1023 REPORT_STATUS_CODE (
1024 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1025 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
1033 Maps a memory region for DMA, note this implementation
1034 only supports slave read/write operation to save code size.
1036 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1037 @param Operation Indicates the type of DMA (slave or bus master), and if
1038 the DMA operation is going to read or write to system memory.
1039 @param ChannelNumber The slave channel number to use for this DMA operation.
1040 If Operation and ChannelAttributes shows that this device
1041 performs bus mastering DMA, then this field is ignored.
1042 The legal range for this field is 0..7.
1043 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
1044 @param HostAddress The system memory address to map to the device.
1045 @param NumberOfBytes On input the number of bytes to map. On output the number
1046 of bytes that were mapped.
1047 @param DeviceAddress The resulting map address for the bus master device to use
1048 to access the hosts HostAddress.
1049 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
1051 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
1052 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
1053 @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.
1054 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1055 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1058 IsaIoMapOnlySupportSlaveReadWrite (
1059 IN EFI_ISA_IO_PROTOCOL
*This
,
1060 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1061 IN UINT8 ChannelNumber OPTIONAL
,
1062 IN UINT32 ChannelAttributes
,
1063 IN VOID
*HostAddress
,
1064 IN OUT UINTN
*NumberOfBytes
,
1065 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1070 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1071 ISA_MAP_INFO
*IsaMapInfo
;
1073 UINTN MaxNumberOfBytes
;
1078 UINT8 DmaChannelMode
;
1080 if ((NULL
== This
) ||
1081 (NULL
== HostAddress
) ||
1082 (NULL
== NumberOfBytes
) ||
1083 (NULL
== DeviceAddress
) ||
1086 return EFI_INVALID_PARAMETER
;
1090 // Initialize the return values to their defaults
1095 // Make sure the Operation parameter is valid.
1096 // Light IsaIo only supports two operations.
1098 if (!(Operation
== EfiIsaIoOperationSlaveRead
||
1099 Operation
== EfiIsaIoOperationSlaveWrite
)) {
1100 return EFI_INVALID_PARAMETER
;
1103 if (ChannelNumber
>= 4) {
1105 // The Light IsaIo doesn't support channelNumber larger than 4.
1107 return EFI_INVALID_PARAMETER
;
1111 // Map the HostAddress to a DeviceAddress.
1113 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1114 if ((PhysicalAddress
+ *NumberOfBytes
) > BASE_16MB
) {
1116 // Common Buffer operations can not be remapped. If the common buffer
1117 // is above 16MB, then it is not possible to generate a mapping, so return
1120 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1121 return EFI_UNSUPPORTED
;
1124 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1127 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1128 if (IsaMapInfo
== NULL
) {
1130 return EFI_OUT_OF_RESOURCES
;
1133 // Return a pointer to the MAP_INFO structure in Mapping
1135 *Mapping
= IsaMapInfo
;
1138 // Initialize the MAP_INFO structure
1140 IsaMapInfo
->Operation
= Operation
;
1141 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
1142 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1143 IsaMapInfo
->HostAddress
= PhysicalAddress
;
1144 IsaMapInfo
->MappedHostAddress
= BASE_16MB
- 1;
1147 // Allocate a buffer below 16MB to map the transfer to.
1149 Status
= gBS
->AllocatePages (
1151 EfiBootServicesData
,
1152 IsaMapInfo
->NumberOfPages
,
1153 &IsaMapInfo
->MappedHostAddress
1155 if (EFI_ERROR (Status
)) {
1156 FreePool (IsaMapInfo
);
1162 // If this is a read operation from the DMA agents's point of view,
1163 // then copy the contents of the real buffer into the mapped buffer
1164 // so the DMA agent can read the contents of the real buffer.
1166 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1168 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1169 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1170 IsaMapInfo
->NumberOfBytes
1174 // The DeviceAddress is the address of the maped buffer below 16 MB
1176 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1179 // The transfer is below 16 MB, so the DeviceAddress is simply the
1182 *DeviceAddress
= PhysicalAddress
;
1186 // Figure out what to program into the DMA Channel Mode Register
1188 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1189 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1190 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1192 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1195 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
1197 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1200 // A Slave DMA transfer can not cross a 64K boundary.
1201 // Compute *NumberOfBytes based on this restriction.
1203 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1204 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1205 *NumberOfBytes
= MaxNumberOfBytes
;
1208 // Compute the values to program into the BaseAddress and Count registers
1209 // of the Slave DMA controller
1211 BaseAddress
= (UINT32
) (*DeviceAddress
);
1212 Count
= (UINT16
) (*NumberOfBytes
- 1);
1214 // Program the DMA Write Single Mask Register for ChannelNumber
1215 // Clear the DMA Byte Pointer Register
1217 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1218 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1219 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1221 Status
= WritePort (
1224 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1226 if (EFI_ERROR (Status
)) {
1230 Status
= WritePort (
1233 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1235 if (EFI_ERROR (Status
)) {
1239 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1240 if (EFI_ERROR (Status
)) {
1244 Status
= WriteDmaPort (
1246 mDmaRegisters
[ChannelNumber
].Address
,
1247 mDmaRegisters
[ChannelNumber
].Page
,
1248 mDmaRegisters
[ChannelNumber
].Count
,
1252 if (EFI_ERROR (Status
)) {
1256 Status
= WritePort (
1259 (UINT8
) (ChannelNumber
& 0x03)
1261 if (EFI_ERROR (Status
)) {
1269 Maps a memory region for DMA. This implementation implement the
1270 the full mapping support.
1272 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1273 @param Operation Indicates the type of DMA (slave or bus master), and if
1274 the DMA operation is going to read or write to system memory.
1275 @param ChannelNumber The slave channel number to use for this DMA operation.
1276 If Operation and ChannelAttributes shows that this device
1277 performs bus mastering DMA, then this field is ignored.
1278 The legal range for this field is 0..7.
1279 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
1280 @param HostAddress The system memory address to map to the device.
1281 @param NumberOfBytes On input the number of bytes to map. On output the number
1282 of bytes that were mapped.
1283 @param DeviceAddress The resulting map address for the bus master device to use
1284 to access the hosts HostAddress.
1285 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
1287 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1288 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1289 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1290 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1291 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1294 IsaIoMapFullSupport (
1295 IN EFI_ISA_IO_PROTOCOL
*This
,
1296 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1297 IN UINT8 ChannelNumber OPTIONAL
,
1298 IN UINT32 ChannelAttributes
,
1299 IN VOID
*HostAddress
,
1300 IN OUT UINTN
*NumberOfBytes
,
1301 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1308 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1309 ISA_MAP_INFO
*IsaMapInfo
;
1311 UINTN MaxNumberOfBytes
;
1316 UINT8 DmaChannelMode
;
1318 if ((NULL
== This
) ||
1319 (NULL
== HostAddress
) ||
1320 (NULL
== NumberOfBytes
) ||
1321 (NULL
== DeviceAddress
) ||
1324 return EFI_INVALID_PARAMETER
;
1328 // Initialize the return values to their defaults
1333 // Make sure the Operation parameter is valid
1335 if (Operation
< 0 || Operation
>= EfiIsaIoOperationMaximum
) {
1336 return EFI_INVALID_PARAMETER
;
1339 if (ChannelNumber
>= 8) {
1340 return EFI_INVALID_PARAMETER
;
1344 // See if this is a Slave DMA Operation
1348 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1349 Operation
= EfiIsaIoOperationBusMasterRead
;
1354 if (Operation
== EfiIsaIoOperationSlaveWrite
) {
1355 Operation
= EfiIsaIoOperationBusMasterWrite
;
1362 // Make sure that ChannelNumber is a valid channel number
1363 // Channel 4 is used to cascade, so it is illegal.
1365 if (ChannelNumber
== 4 || ChannelNumber
> 7) {
1366 return EFI_INVALID_PARAMETER
;
1369 // This implementation only support COMPATIBLE DMA Transfers
1371 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE
) == 0) {
1372 return EFI_INVALID_PARAMETER
;
1375 if ((ChannelAttributes
&
1376 (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A
|
1377 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B
|
1378 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C
)) != 0) {
1379 return EFI_INVALID_PARAMETER
;
1382 if (ChannelNumber
< 4) {
1384 // If this is Channel 0..3, then the width must be 8 bit
1386 if (((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) == 0) ||
1387 ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
) != 0)
1389 return EFI_INVALID_PARAMETER
;
1393 // If this is Channel 4..7, then the width must be 16 bit
1395 if (((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) != 0) ||
1396 ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
) == 0)) {
1397 return EFI_INVALID_PARAMETER
;
1401 // Either Demand Mode or Single Mode must be selected, but not both
1403 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) != 0) {
1404 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) != 0) {
1405 return EFI_INVALID_PARAMETER
;
1408 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) == 0) {
1409 return EFI_INVALID_PARAMETER
;
1414 // Map the HostAddress to a DeviceAddress.
1416 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1417 if ((PhysicalAddress
+*NumberOfBytes
) > BASE_16MB
) {
1419 // Common Buffer operations can not be remapped. If the common buffer
1420 // is above 16MB, then it is not possible to generate a mapping, so return
1423 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1424 return EFI_UNSUPPORTED
;
1427 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1430 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1431 if (IsaMapInfo
== NULL
) {
1433 return EFI_OUT_OF_RESOURCES
;
1436 // Return a pointer to the MAP_INFO structure in Mapping
1438 *Mapping
= IsaMapInfo
;
1441 // Initialize the MAP_INFO structure
1443 IsaMapInfo
->Operation
= Operation
;
1444 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
1445 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1446 IsaMapInfo
->HostAddress
= PhysicalAddress
;
1447 IsaMapInfo
->MappedHostAddress
= BASE_16MB
- 1;
1450 // Allocate a buffer below 16MB to map the transfer to.
1452 Status
= gBS
->AllocatePages (
1454 EfiBootServicesData
,
1455 IsaMapInfo
->NumberOfPages
,
1456 &IsaMapInfo
->MappedHostAddress
1458 if (EFI_ERROR (Status
)) {
1459 FreePool (IsaMapInfo
);
1465 // If this is a read operation from the DMA agents's point of view,
1466 // then copy the contents of the real buffer into the mapped buffer
1467 // so the DMA agent can read the contents of the real buffer.
1469 if (Operation
== EfiIsaIoOperationBusMasterRead
) {
1471 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1472 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1473 IsaMapInfo
->NumberOfBytes
1477 // The DeviceAddress is the address of the maped buffer below 16 MB
1479 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1482 // The transfer is below 16 MB, so the DeviceAddress is simply the
1485 *DeviceAddress
= PhysicalAddress
;
1488 // If this is a Bus Master operation then return
1494 // Figure out what to program into the DMA Channel Mode Register
1496 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1498 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1500 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1503 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE
) != 0) {
1504 DmaMode
|= B_8237_DMA_CHMODE_AE
;
1507 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) != 0) {
1508 DmaMode
|= V_8237_DMA_CHMODE_DEMAND
;
1511 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) != 0) {
1512 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1515 // A Slave DMA transfer can not cross a 64K boundary.
1516 // Compute *NumberOfBytes based on this restriction.
1518 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1519 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1520 *NumberOfBytes
= MaxNumberOfBytes
;
1523 // Compute the values to program into the BaseAddress and Count registers
1524 // of the Slave DMA controller
1526 if (ChannelNumber
< 4) {
1527 BaseAddress
= (UINT32
) (*DeviceAddress
);
1528 Count
= (UINT16
) (*NumberOfBytes
- 1);
1530 BaseAddress
= (UINT32
) (((UINT32
) (*DeviceAddress
) & 0xff0000) | (((UINT32
) (*DeviceAddress
) & 0xffff) >> 1));
1531 Count
= (UINT16
) ((*NumberOfBytes
- 1) >> 1);
1534 // Program the DMA Write Single Mask Register for ChannelNumber
1535 // Clear the DMA Byte Pointer Register
1537 if (ChannelNumber
< 4) {
1538 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1539 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1540 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1542 DmaMask
= R_8237_DMA_WRSMSK_CH4_7
;
1543 DmaClear
= R_8237_DMA_CBPR_CH4_7
;
1544 DmaChannelMode
= R_8237_DMA_CHMODE_CH4_7
;
1547 Status
= WritePort (
1550 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1552 if (EFI_ERROR (Status
)) {
1556 Status
= WritePort (
1559 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1561 if (EFI_ERROR (Status
)) {
1565 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1566 if (EFI_ERROR (Status
)) {
1570 Status
= WriteDmaPort (
1572 mDmaRegisters
[ChannelNumber
].Address
,
1573 mDmaRegisters
[ChannelNumber
].Page
,
1574 mDmaRegisters
[ChannelNumber
].Count
,
1578 if (EFI_ERROR (Status
)) {
1582 Status
= WritePort (
1585 (UINT8
) (ChannelNumber
& 0x03)
1587 if (EFI_ERROR (Status
)) {
1595 Maps a memory region for DMA
1597 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1598 @param Operation Indicates the type of DMA (slave or bus master), and if
1599 the DMA operation is going to read or write to system memory.
1600 @param ChannelNumber The slave channel number to use for this DMA operation.
1601 If Operation and ChannelAttributes shows that this device
1602 performs bus mastering DMA, then this field is ignored.
1603 The legal range for this field is 0..7.
1604 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
1605 @param HostAddress The system memory address to map to the device.
1606 @param NumberOfBytes On input the number of bytes to map. On output the number
1607 of bytes that were mapped.
1608 @param DeviceAddress The resulting map address for the bus master device to use
1609 to access the hosts HostAddress.
1610 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
1612 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
1613 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
1614 @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.
1615 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1616 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1621 IN EFI_ISA_IO_PROTOCOL
*This
,
1622 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1623 IN UINT8 ChannelNumber OPTIONAL
,
1624 IN UINT32 ChannelAttributes
,
1625 IN VOID
*HostAddress
,
1626 IN OUT UINTN
*NumberOfBytes
,
1627 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1632 // Check if DMA is supported.
1634 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) {
1635 return EFI_UNSUPPORTED
;
1638 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1641 // So we just return EFI_UNSUPPORTED for these functions.
1643 if ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA
) != 0) {
1644 return IsaIoMapOnlySupportSlaveReadWrite (
1656 return IsaIoMapFullSupport (
1670 Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping.
1672 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1673 @param[in] Type The type allocation to perform.
1674 @param[in] MemoryType The type of memory to allocate.
1675 @param[in] Pages The number of pages to allocate.
1676 @param[out] HostAddress A pointer to store the base address of the allocated range.
1677 @param[in] Attributes The requested bit mask of attributes for the allocated range.
1679 @retval EFI_SUCCESS The requested memory pages were allocated.
1680 @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL
1681 @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified
1682 by HostAddress, Pages, and Type is not available for common buffer use.
1683 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1687 IsaIoAllocateBuffer (
1688 IN EFI_ISA_IO_PROTOCOL
*This
,
1689 IN EFI_ALLOCATE_TYPE Type
,
1690 IN EFI_MEMORY_TYPE MemoryType
,
1692 OUT VOID
**HostAddress
,
1693 IN UINT64 Attributes
1697 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1700 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1702 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1704 if (((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) ||
1705 ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA
) != 0)) {
1706 return EFI_UNSUPPORTED
;
1709 if (HostAddress
== NULL
) {
1710 return EFI_INVALID_PARAMETER
;
1713 if (Type
< AllocateAnyPages
|| Type
>= MaxAllocateType
) {
1714 return EFI_INVALID_PARAMETER
;
1717 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1719 if (MemoryType
!= EfiBootServicesData
&& MemoryType
!= EfiRuntimeServicesData
) {
1720 return EFI_INVALID_PARAMETER
;
1723 if ((Attributes
& ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
| EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED
)) != 0) {
1724 return EFI_UNSUPPORTED
;
1727 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) (BASE_16MB
- 1);
1728 if (Type
== AllocateAddress
) {
1729 if ((UINTN
) (*HostAddress
) >= BASE_16MB
) {
1730 return EFI_UNSUPPORTED
;
1732 PhysicalAddress
= (UINTN
) (*HostAddress
);
1736 if (Type
== AllocateAnyPages
) {
1737 Type
= AllocateMaxAddress
;
1740 Status
= gBS
->AllocatePages (Type
, MemoryType
, Pages
, &PhysicalAddress
);
1741 if (EFI_ERROR (Status
)) {
1742 REPORT_STATUS_CODE (
1743 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1744 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
1749 *HostAddress
= (VOID
*) (UINTN
) PhysicalAddress
;
1754 Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer().
1756 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1757 @param[in] Pages The number of pages to free.
1758 @param[in] HostAddress The base address of the allocated range.
1760 @retval EFI_SUCCESS The requested memory pages were freed.
1761 @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1766 IN EFI_ISA_IO_PROTOCOL
*This
,
1768 IN VOID
*HostAddress
1774 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1776 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1778 if (((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_SUPPORT_DMA
) == 0) ||
1779 ((PcdGet8 (PcdIsaBusSupportedFeatures
) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA
) != 0)) {
1780 return EFI_UNSUPPORTED
;
1783 Status
= gBS
->FreePages (
1784 (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
,
1787 if (EFI_ERROR (Status
)) {
1788 REPORT_STATUS_CODE (
1789 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1790 EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR