2 The implementation for EFI_ISA_IO_PROTOCOL.
4 Copyright (c) 2006 - 2007, Intel Corporation.<BR>
5 All rights reserved. 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.
15 #include "InternalIsaIo.h"
18 // Driver Support Global Variables
20 EFI_ISA_IO_PROTOCOL IsaIoInterface
= {
40 static EFI_ISA_DMA_REGISTERS DmaRegisters
[8] = {
65 }, // Channel 4 is invalid
84 report a error Status code of PCI bus driver controller
86 @param Code - The error status code.
88 @return EFI_SUCCESS - Success to report status code.
91 ReportErrorStatusCode (
92 EFI_STATUS_CODE_VALUE Code
96 return REPORT_STATUS_CODE (
97 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
103 // Driver Support Functions
107 Initializes an ISA I/O Instance
109 @param IsaIoDevice - The iso device to be initialized.
110 @param IsaDeviceResourceList - The resource list.
112 @retval EFI_SUCCESS - Initial success.
116 InitializeIsaIoInstance (
117 IN ISA_IO_DEVICE
*IsaIoDevice
,
118 IN EFI_ISA_ACPI_RESOURCE_LIST
*IsaDeviceResourceList
122 // Initializes an ISA I/O Instance
127 sizeof (EFI_ISA_IO_PROTOCOL
)
130 IsaIoDevice
->IsaIo
.ResourceList
= IsaDeviceResourceList
;
136 Performs an ISA I/O Read Cycle
138 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
139 @param Width - Signifies the width of the I/O operation.
140 @param Offset - The offset in ISA I/O space to start the I/O operation.
141 @param Count - The number of I/O operations to perform.
142 @param Buffer - The destination buffer to store the results
144 @retval EFI_SUCCESS - The data was read from the device sucessfully.
145 @retval EFI_UNSUPPORTED - The Offset is not valid for this device.
146 @retval EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
147 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
153 IN EFI_ISA_IO_PROTOCOL
*This
,
154 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
162 ISA_IO_DEVICE
*IsaIoDevice
;
164 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
167 // Verify Isa IO Access
169 Status
= IsaIoVerifyAccess (
176 if (EFI_ERROR (Status
)) {
180 // Call PciIo->Io.Read
182 Status
= IsaIoDevice
->PciIo
->Io
.Read (
184 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
185 EFI_PCI_IO_PASS_THROUGH_BAR
,
191 if (EFI_ERROR (Status
)) {
192 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
199 Performs an ISA I/O Write Cycle
201 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
202 @param Width - Signifies the width of the I/O operation.
203 @param Offset - The offset in ISA I/O space to start the I/O operation.
204 @param Count - The number of I/O operations to perform.
205 @param Buffer - The source buffer to write data from
207 @retval EFI_SUCCESS - The data was writen to the device sucessfully.
208 @retval EFI_UNSUPPORTED - The Offset is not valid for this device.
209 @retval EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
210 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
216 IN EFI_ISA_IO_PROTOCOL
*This
,
217 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
224 ISA_IO_DEVICE
*IsaIoDevice
;
226 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
229 // Verify Isa IO Access
231 Status
= IsaIoVerifyAccess (
238 if (EFI_ERROR (Status
)) {
242 // Call PciIo->Io.Write
244 Status
= IsaIoDevice
->PciIo
->Io
.Write (
246 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
247 EFI_PCI_IO_PASS_THROUGH_BAR
,
253 if (EFI_ERROR (Status
)) {
254 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
261 Writes an 8 bit I/O Port
263 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
264 @param Offset - The offset in ISA IO space to start the IO operation.
265 @param Value - The data to write port.
267 @retval EFI_SUCCESS - Success.
268 @retval EFI_INVALID_PARAMETER - Parameter is invalid.
269 @retval EFI_UNSUPPORTED - The address range specified by Offset is not valid.
270 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
275 IN EFI_ISA_IO_PROTOCOL
*This
,
282 ISA_IO_DEVICE
*IsaIoDevice
;
284 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
287 // Call PciIo->Io.Write
289 Status
= IsaIoDevice
->PciIo
->Io
.Write (
292 EFI_PCI_IO_PASS_THROUGH_BAR
,
297 if (EFI_ERROR (Status
)) {
298 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
308 Writes I/O operation base address and count number to a 8 bit I/O Port.
310 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
311 @param AddrOffset - The address' offset.
312 @param PageOffset - The page's offest.
313 @param CountOffset - The count's offset.
314 @param BaseAddress - The base address.
315 @param Count - The number of I/O operations to perform.
317 @retval EFI_SUCCESS - Success.
318 @retval EFI_INVALID_PARAMETER - Parameter is invalid.
319 @retval EFI_UNSUPPORTED - The address range specified by these Offsets and Count is not valid.
320 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
325 IN EFI_ISA_IO_PROTOCOL
*This
,
326 IN UINT32 AddrOffset
,
327 IN UINT32 PageOffset
,
328 IN UINT32 CountOffset
,
329 IN UINT32 BaseAddress
,
336 Status
= WritePort (This
, AddrOffset
, (UINT8
) (BaseAddress
& 0xff));
337 if (EFI_ERROR (Status
)) {
341 Status
= WritePort (This
, AddrOffset
, (UINT8
) ((BaseAddress
>> 8) & 0xff));
342 if (EFI_ERROR (Status
)) {
346 Status
= WritePort (This
, PageOffset
, (UINT8
) ((BaseAddress
>> 16) & 0xff));
347 if (EFI_ERROR (Status
)) {
351 Status
= WritePort (This
, CountOffset
, (UINT8
) (Count
& 0xff));
352 if (EFI_ERROR (Status
)) {
356 Status
= WritePort (This
, CountOffset
, (UINT8
) ((Count
>> 8) & 0xff));
357 if (EFI_ERROR (Status
)) {
365 Unmaps a memory region for DMA
367 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
368 @param Mapping - The mapping value returned from EFI_ISA_IO.Map().
370 @retval EFI_SUCCESS - The range was unmapped.
371 @retval EFI_DEVICE_ERROR - The data was not committed to the target system memory.
377 IN EFI_ISA_IO_PROTOCOL
*This
,
381 ISA_MAP_INFO
*IsaMapInfo
;
384 // Unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
386 if (!FeaturePcdGet (PcdIsaBusSupportDma
)) {
387 return EFI_UNSUPPORTED
;
391 // See if the Map() operation associated with this Unmap() required a mapping
392 // buffer.If a mapping buffer was not required, then this function simply
393 // returns EFI_SUCCESS.
395 if (Mapping
!= NULL
) {
397 // Get the MAP_INFO structure from Mapping
399 IsaMapInfo
= (ISA_MAP_INFO
*) Mapping
;
402 // If this is a write operation from the Agent's point of view,
403 // then copy the contents of the mapped buffer into the real buffer
404 // so the processor can read the contents of the real buffer.
406 if (IsaMapInfo
->Operation
== EfiIsaIoOperationBusMasterWrite
) {
408 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
409 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
410 IsaMapInfo
->NumberOfBytes
414 // Free the mapped buffer and the MAP_INFO structure.
416 gBS
->FreePages (IsaMapInfo
->MappedHostAddress
, IsaMapInfo
->NumberOfPages
);
417 gBS
->FreePool (IsaMapInfo
);
426 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
428 @retval EFI_SUCCESS - The buffers were flushed.
429 @retval EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
435 IN EFI_ISA_IO_PROTOCOL
*This
440 ISA_IO_DEVICE
*IsaIoDevice
;
442 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
447 Status
= IsaIoDevice
->PciIo
->Flush (IsaIoDevice
->PciIo
);
449 if (EFI_ERROR (Status
)) {
450 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
457 Verifies access to an ISA device
459 @param IsaIoDevice - The ISA device to be verified.
460 @param Type - The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo.
461 @param Width - Signifies the width of the memory operation.
462 @param Count - The number of memory operations to perform.
463 @param Offset - The offset in ISA memory space to start the memory operation.
465 @retval EFI_SUCCESS - Verify success.
466 @retval EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
467 @retval EFI_UNSUPPORTED - The device ont support the access type.
472 IN ISA_IO_DEVICE
*IsaIoDevice
,
473 IN ISA_ACCESS_TYPE Type
,
474 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
476 IN OUT UINT32
*Offset
480 EFI_ISA_ACPI_RESOURCE
*Item
;
483 if (Width
< EfiIsaIoWidthUint8
||
484 Width
>= EfiIsaIoWidthMaximum
||
485 Width
== EfiIsaIoWidthReserved
||
486 Width
== EfiIsaIoWidthFifoReserved
||
487 Width
== EfiIsaIoWidthFillReserved
489 return EFI_INVALID_PARAMETER
;
493 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
494 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
496 if (Width
>= EfiIsaIoWidthFifoUint8
&& Width
<= EfiIsaIoWidthFifoReserved
) {
500 Width
= (EFI_ISA_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
502 Status
= EFI_UNSUPPORTED
;
503 Item
= IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
;
504 while (Item
->Type
!= EfiIsaAcpiResourceEndOfList
) {
505 if ((Type
== IsaAccessTypeMem
&& Item
->Type
== EfiIsaAcpiResourceMemory
) ||
506 (Type
== IsaAccessTypeIo
&& Item
->Type
== EfiIsaAcpiResourceIo
)
508 if (*Offset
>= Item
->StartRange
&& (*Offset
+ Count
* (UINT32
)(1 << Width
)) - 1 <= Item
->EndRange
) {
512 if (*Offset
>= Item
->StartRange
&& *Offset
<= Item
->EndRange
) {
513 Status
= EFI_INVALID_PARAMETER
;
525 Performs an ISA Memory Read Cycle
527 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
528 @param Width - Signifies the width of the memory operation.
529 @param Offset - The offset in ISA memory space to start the memory operation.
530 @param Count - The number of memory operations to perform.
531 @param Buffer - The destination buffer to store the results
533 @retval EFI_SUCCESS - The data was read from the device successfully.
534 @retval EFI_UNSUPPORTED - The Offset is not valid for this device.
535 @retval EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
536 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
542 IN EFI_ISA_IO_PROTOCOL
*This
,
543 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
551 ISA_IO_DEVICE
*IsaIoDevice
;
554 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
557 // So we just return EFI_UNSUPPORTED for these functions.
559 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory
)) {
560 return EFI_UNSUPPORTED
;
563 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
566 // Verify the Isa Io Access
568 Status
= IsaIoVerifyAccess (
575 if (EFI_ERROR (Status
)) {
579 // Call PciIo->Mem.Read
581 Status
= IsaIoDevice
->PciIo
->Mem
.Read (
583 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
584 EFI_PCI_IO_PASS_THROUGH_BAR
,
590 if (EFI_ERROR (Status
)) {
591 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
598 Performs an ISA Memory Write Cycle
600 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
601 @param Width - Signifies the width of the memory operation.
602 @param Offset - The offset in ISA memory space to start the memory operation.
603 @param Count - The number of memory operations to perform.
604 @param Buffer - The source buffer to write data from
606 @retval EFI_SUCCESS - The data was written to the device sucessfully.
607 @retval EFI_UNSUPPORTED - The Offset is not valid for this device.
608 @retval EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
609 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
615 IN EFI_ISA_IO_PROTOCOL
*This
,
616 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
623 ISA_IO_DEVICE
*IsaIoDevice
;
626 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
629 // So we just return EFI_UNSUPPORTED for these functions.
631 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory
)) {
632 return EFI_UNSUPPORTED
;
635 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
638 // Verify Isa IO Access
640 Status
= IsaIoVerifyAccess (
647 if (EFI_ERROR (Status
)) {
651 // Call PciIo->Mem.Write
653 Status
= IsaIoDevice
->PciIo
->Mem
.Write (
655 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
656 EFI_PCI_IO_PASS_THROUGH_BAR
,
662 if (EFI_ERROR (Status
)) {
663 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
670 Performs an ISA I/O Copy Memory
672 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
673 @param Width - Signifies the width of the memory copy operation.
674 @param DestOffset - The offset of the destination
675 @param SrcOffset - The offset of the source
676 @param Count - The number of memory copy operations to perform
678 @retval EFI_SUCCESS - The data was copied sucessfully.
679 @retval EFI_UNSUPPORTED - The DestOffset or SrcOffset is not valid for this device.
680 @retval EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
681 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
687 IN EFI_ISA_IO_PROTOCOL
*This
,
688 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
689 IN UINT32 DestOffset
,
696 ISA_IO_DEVICE
*IsaIoDevice
;
699 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
702 // So we just return EFI_UNSUPPORTED for these functions.
704 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory
)) {
705 return EFI_UNSUPPORTED
;
708 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
711 // Verify Isa IO Access for destination and source
713 Status
= IsaIoVerifyAccess (
720 if (EFI_ERROR (Status
)) {
724 Status
= IsaIoVerifyAccess (
731 if (EFI_ERROR (Status
)) {
735 // Call PciIo->CopyMem
737 Status
= IsaIoDevice
->PciIo
->CopyMem (
739 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
740 EFI_PCI_IO_PASS_THROUGH_BAR
,
742 EFI_PCI_IO_PASS_THROUGH_BAR
,
747 if (EFI_ERROR (Status
)) {
748 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
755 Maps a memory region for DMA, note this implementation
756 only supports slave read/write operation to save code size.
758 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
759 @param Operation - Indicates the type of DMA (slave or bus master), and if
760 the DMA operation is going to read or write to system memory.
761 @param ChannelNumber - The slave channel number to use for this DMA operation.
762 If Operation and ChannelAttributes shows that this device
763 performs bus mastering DMA, then this field is ignored.
764 The legal range for this field is 0..7.
765 @param ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
766 @param HostAddress - The system memory address to map to the device.
767 @param NumberOfBytes - On input the number of bytes to map. On output the number
768 of bytes that were mapped.
769 @param DeviceAddress - The resulting map address for the bus master device to use
770 to access the hosts HostAddress.
771 @param Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
773 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
774 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
775 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
776 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.
777 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
782 IsaIoMap_OnlySupportSlaveReadWrite (
783 IN EFI_ISA_IO_PROTOCOL
*This
,
784 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
785 IN UINT8 ChannelNumber OPTIONAL
,
786 IN UINT32 ChannelAttributes
,
787 IN VOID
*HostAddress
,
788 IN OUT UINTN
*NumberOfBytes
,
789 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
795 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
796 ISA_MAP_INFO
*IsaMapInfo
;
798 UINTN MaxNumberOfBytes
;
804 UINT8 DmaChannelMode
;
806 if ((NULL
== This
) ||
807 (NULL
== HostAddress
) ||
808 (NULL
== NumberOfBytes
) ||
809 (NULL
== DeviceAddress
) ||
812 return EFI_INVALID_PARAMETER
;
817 // Initialize the return values to their defaults
822 // Make sure the Operation parameter is valid.
823 // Light IsaIo only supports two operations.
825 if (!(Operation
== EfiIsaIoOperationSlaveRead
||
826 Operation
== EfiIsaIoOperationSlaveWrite
)) {
827 return EFI_INVALID_PARAMETER
;
830 if (ChannelNumber
>= 4) {
832 // The Light IsaIo doesn't support channelNumber larger than 4.
834 return EFI_INVALID_PARAMETER
;
838 // Map the HostAddress to a DeviceAddress.
840 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
841 if ((PhysicalAddress
+*NumberOfBytes
) > ISA_MAX_MEMORY_ADDRESS
) {
843 // Common Buffer operations can not be remapped. If the common buffer
844 // is above 16MB, then it is not possible to generate a mapping, so return
847 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
848 return EFI_UNSUPPORTED
;
851 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
854 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
855 if (IsaMapInfo
== NULL
) {
857 return EFI_OUT_OF_RESOURCES
;
860 // Return a pointer to the MAP_INFO structure in Mapping
862 *Mapping
= IsaMapInfo
;
865 // Initialize the MAP_INFO structure
867 IsaMapInfo
->Operation
= Operation
;
868 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
869 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
870 IsaMapInfo
->HostAddress
= PhysicalAddress
;
871 IsaMapInfo
->MappedHostAddress
= ISA_MAX_MEMORY_ADDRESS
- 1;
874 // Allocate a buffer below 16MB to map the transfer to.
876 Status
= gBS
->AllocatePages (
879 IsaMapInfo
->NumberOfPages
,
880 &IsaMapInfo
->MappedHostAddress
882 if (EFI_ERROR (Status
)) {
883 gBS
->FreePool (IsaMapInfo
);
889 // If this is a read operation from the DMA agents's point of view,
890 // then copy the contents of the real buffer into the mapped buffer
891 // so the DMA agent can read the contents of the real buffer.
893 if (Operation
== EfiIsaIoOperationSlaveRead
) {
895 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
896 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
897 IsaMapInfo
->NumberOfBytes
901 // The DeviceAddress is the address of the maped buffer below 16 MB
903 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
906 // The transfer is below 16 MB, so the DeviceAddress is simply the
909 *DeviceAddress
= PhysicalAddress
;
913 // Figure out what to program into the DMA Channel Mode Register
915 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
916 if (Operation
== EfiIsaIoOperationSlaveRead
) {
917 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
919 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
922 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
924 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
927 // A Slave DMA transfer can not cross a 64K boundary.
928 // Compute *NumberOfBytes based on this restriction.
930 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
931 if (*NumberOfBytes
> MaxNumberOfBytes
) {
932 *NumberOfBytes
= MaxNumberOfBytes
;
935 // Compute the values to program into the BaseAddress and Count registers
936 // of the Slave DMA controller
938 BaseAddress
= (UINT32
) (*DeviceAddress
);
939 Count
= (UINT16
) (*NumberOfBytes
- 1);
941 // Program the DMA Write Single Mask Register for ChannelNumber
942 // Clear the DMA Byte Pointer Register
944 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
945 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
946 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
951 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
953 if (EFI_ERROR (Status
)) {
960 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
962 if (EFI_ERROR (Status
)) {
966 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
967 if (EFI_ERROR (Status
)) {
971 Status
= WriteDmaPort (
973 DmaRegisters
[ChannelNumber
].Address
,
974 DmaRegisters
[ChannelNumber
].Page
,
975 DmaRegisters
[ChannelNumber
].Count
,
979 if (EFI_ERROR (Status
)) {
986 (UINT8
) (ChannelNumber
& 0x03)
988 if (EFI_ERROR (Status
)) {
996 Maps a memory region for DMA. This implementation implement the
997 the full mapping support.
999 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1000 @param Operation - Indicates the type of DMA (slave or bus master), and if
1001 the DMA operation is going to read or write to system memory.
1002 @param ChannelNumber - The slave channel number to use for this DMA operation.
1003 If Operation and ChannelAttributes shows that this device
1004 performs bus mastering DMA, then this field is ignored.
1005 The legal range for this field is 0..7.
1006 @param ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
1007 @param HostAddress - The system memory address to map to the device.
1008 @param NumberOfBytes - On input the number of bytes to map. On output the number
1009 of bytes that were mapped.
1010 @param DeviceAddress - The resulting map address for the bus master device to use
1011 - to access the hosts HostAddress.
1012 @param Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
1014 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1015 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1016 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1017 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1018 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1023 IsaIoMap_FullSupport (
1024 IN EFI_ISA_IO_PROTOCOL
*This
,
1025 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1026 IN UINT8 ChannelNumber OPTIONAL
,
1027 IN UINT32 ChannelAttributes
,
1028 IN VOID
*HostAddress
,
1029 IN OUT UINTN
*NumberOfBytes
,
1030 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1038 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1039 ISA_MAP_INFO
*IsaMapInfo
;
1041 UINTN MaxNumberOfBytes
;
1047 UINT8 DmaChannelMode
;
1049 if ((NULL
== This
) ||
1050 (NULL
== HostAddress
) ||
1051 (NULL
== NumberOfBytes
) ||
1052 (NULL
== DeviceAddress
) ||
1055 return EFI_INVALID_PARAMETER
;
1060 // Initialize the return values to their defaults
1065 // Make sure the Operation parameter is valid
1067 if (Operation
< 0 || Operation
>= EfiIsaIoOperationMaximum
) {
1068 return EFI_INVALID_PARAMETER
;
1071 // See if this is a Slave DMA Operation
1075 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1076 Operation
= EfiIsaIoOperationBusMasterRead
;
1081 if (Operation
== EfiIsaIoOperationSlaveWrite
) {
1082 Operation
= EfiIsaIoOperationBusMasterWrite
;
1089 // Make sure that ChannelNumber is a valid channel number
1090 // Channel 4 is used to cascade, so it is illegal.
1092 if (ChannelNumber
== 4 || ChannelNumber
> 7) {
1093 return EFI_INVALID_PARAMETER
;
1096 // This implementation only support COMPATIBLE DMA Transfers
1098 if (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE
)) {
1099 return EFI_INVALID_PARAMETER
;
1102 if (ChannelAttributes
&
1104 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A
|
1105 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B
|
1106 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C
1109 return EFI_INVALID_PARAMETER
;
1112 if (ChannelNumber
< 4) {
1114 // If this is Channel 0..3, then the width must be 8 bit
1116 if (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) ||
1117 (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
)
1119 return EFI_INVALID_PARAMETER
;
1123 // If this is Channel 4..7, then the width must be 16 bit
1125 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) ||
1126 (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
))
1128 return EFI_INVALID_PARAMETER
;
1132 // Either Demand Mode or Single Mode must be selected, but not both
1134 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) {
1135 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) {
1136 return EFI_INVALID_PARAMETER
;
1139 if (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
)) {
1140 return EFI_INVALID_PARAMETER
;
1145 // Map the HostAddress to a DeviceAddress.
1147 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1148 if ((PhysicalAddress
+*NumberOfBytes
) > ISA_MAX_MEMORY_ADDRESS
) {
1150 // Common Buffer operations can not be remapped. If the common buffer
1151 // is above 16MB, then it is not possible to generate a mapping, so return
1154 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1155 return EFI_UNSUPPORTED
;
1158 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1161 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1162 if (IsaMapInfo
== NULL
) {
1164 return EFI_OUT_OF_RESOURCES
;
1167 // Return a pointer to the MAP_INFO structure in Mapping
1169 *Mapping
= IsaMapInfo
;
1172 // Initialize the MAP_INFO structure
1174 IsaMapInfo
->Operation
= Operation
;
1175 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
1176 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1177 IsaMapInfo
->HostAddress
= PhysicalAddress
;
1178 IsaMapInfo
->MappedHostAddress
= ISA_MAX_MEMORY_ADDRESS
- 1;
1181 // Allocate a buffer below 16MB to map the transfer to.
1183 Status
= gBS
->AllocatePages (
1185 EfiBootServicesData
,
1186 IsaMapInfo
->NumberOfPages
,
1187 &IsaMapInfo
->MappedHostAddress
1189 if (EFI_ERROR (Status
)) {
1190 gBS
->FreePool (IsaMapInfo
);
1196 // If this is a read operation from the DMA agents's point of view,
1197 // then copy the contents of the real buffer into the mapped buffer
1198 // so the DMA agent can read the contents of the real buffer.
1200 if (Operation
== EfiIsaIoOperationBusMasterRead
) {
1202 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1203 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1204 IsaMapInfo
->NumberOfBytes
1208 // The DeviceAddress is the address of the maped buffer below 16 MB
1210 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1213 // The transfer is below 16 MB, so the DeviceAddress is simply the
1216 *DeviceAddress
= PhysicalAddress
;
1219 // If this is a Bus Master operation then return
1225 // Figure out what to program into the DMA Channel Mode Register
1227 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1229 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1231 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1234 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE
) {
1235 DmaMode
|= B_8237_DMA_CHMODE_AE
;
1238 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) {
1239 DmaMode
|= V_8237_DMA_CHMODE_DEMAND
;
1242 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) {
1243 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1246 // A Slave DMA transfer can not cross a 64K boundary.
1247 // Compute *NumberOfBytes based on this restriction.
1249 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1250 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1251 *NumberOfBytes
= MaxNumberOfBytes
;
1254 // Compute the values to program into the BaseAddress and Count registers
1255 // of the Slave DMA controller
1257 if (ChannelNumber
< 4) {
1258 BaseAddress
= (UINT32
) (*DeviceAddress
);
1259 Count
= (UINT16
) (*NumberOfBytes
- 1);
1261 BaseAddress
= (UINT32
) (((UINT32
) (*DeviceAddress
) & 0xff0000) | (((UINT32
) (*DeviceAddress
) & 0xffff) >> 1));
1262 Count
= (UINT16
) ((*NumberOfBytes
- 1) >> 1);
1265 // Program the DMA Write Single Mask Register for ChannelNumber
1266 // Clear the DMA Byte Pointer Register
1268 if (ChannelNumber
< 4) {
1269 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1270 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1271 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1273 DmaMask
= R_8237_DMA_WRSMSK_CH4_7
;
1274 DmaClear
= R_8237_DMA_CBPR_CH4_7
;
1275 DmaChannelMode
= R_8237_DMA_CHMODE_CH4_7
;
1278 Status
= WritePort (
1281 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1283 if (EFI_ERROR (Status
)) {
1287 Status
= WritePort (
1290 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1292 if (EFI_ERROR (Status
)) {
1296 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1297 if (EFI_ERROR (Status
)) {
1301 Status
= WriteDmaPort (
1303 DmaRegisters
[ChannelNumber
].Address
,
1304 DmaRegisters
[ChannelNumber
].Page
,
1305 DmaRegisters
[ChannelNumber
].Count
,
1309 if (EFI_ERROR (Status
)) {
1313 Status
= WritePort (
1316 (UINT8
) (ChannelNumber
& 0x03)
1318 if (EFI_ERROR (Status
)) {
1326 Maps a memory region for DMA
1328 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1329 @param Operation - Indicates the type of DMA (slave or bus master), and if
1330 the DMA operation is going to read or write to system memory.
1331 @param ChannelNumber - The slave channel number to use for this DMA operation.
1332 If Operation and ChannelAttributes shows that this device
1333 performs bus mastering DMA, then this field is ignored.
1334 The legal range for this field is 0..7.
1335 @param ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
1336 @param HostAddress - The system memory address to map to the device.
1337 @param NumberOfBytes - On input the number of bytes to map. On output the number
1338 of bytes that were mapped.
1339 @param DeviceAddress - The resulting map address for the bus master device to use
1340 - to access the hosts HostAddress.
1341 @param Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
1344 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1345 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1346 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1347 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1348 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1354 IN EFI_ISA_IO_PROTOCOL
*This
,
1355 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1356 IN UINT8 ChannelNumber OPTIONAL
,
1357 IN UINT32 ChannelAttributes
,
1358 IN VOID
*HostAddress
,
1359 IN OUT UINTN
*NumberOfBytes
,
1360 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1366 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1368 if (!FeaturePcdGet (PcdIsaBusSupportDma
)) {
1369 return EFI_UNSUPPORTED
;
1372 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1375 // So we just return EFI_UNSUPPORTED for these functions.
1377 if (FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma
)) {
1378 return IsaIoMap_OnlySupportSlaveReadWrite (
1390 return IsaIoMap_FullSupport (
1404 Allocates a common buffer for DMA
1406 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1407 @param Type - The type allocation to perform.
1408 @param MemoryType - The type of memory to allocate.
1409 @param Pages - The number of pages to allocate.
1410 @param HostAddress - A pointer to store the base address of the allocated range.
1411 @param Attributes - The requested bit mask of attributes for the allocated range.
1413 @retval EFI_SUCCESS - The requested memory pages were allocated.
1414 @retval EFI_INVALID_PARAMETER - Type is invalid or MemoryType is invalid or HostAddress is NULL
1415 @retval EFI_UNSUPPORTED - Attributes is unsupported or the memory range specified
1416 by HostAddress, Pages, and Type is not available for common buffer use.
1417 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1422 IsaIoAllocateBuffer (
1423 IN EFI_ISA_IO_PROTOCOL
*This
,
1424 IN EFI_ALLOCATE_TYPE Type
,
1425 IN EFI_MEMORY_TYPE MemoryType
,
1427 OUT VOID
**HostAddress
,
1428 IN UINT64 Attributes
1432 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1435 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1437 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1439 if (!FeaturePcdGet (PcdIsaBusSupportDma
) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma
)) {
1440 return EFI_UNSUPPORTED
;
1443 if (HostAddress
== NULL
) {
1444 return EFI_INVALID_PARAMETER
;
1447 if (Type
< AllocateAnyPages
|| Type
>= MaxAllocateType
) {
1448 return EFI_INVALID_PARAMETER
;
1451 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1453 if (MemoryType
!= EfiBootServicesData
&& MemoryType
!= EfiRuntimeServicesData
) {
1454 return EFI_INVALID_PARAMETER
;
1457 if (Attributes
&~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
| EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED
)) {
1458 return EFI_UNSUPPORTED
;
1461 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) (ISA_MAX_MEMORY_ADDRESS
- 1);
1462 if (Type
== AllocateAddress
) {
1463 if ((UINTN
) (*HostAddress
) >= ISA_MAX_MEMORY_ADDRESS
) {
1464 return EFI_UNSUPPORTED
;
1466 PhysicalAddress
= (UINTN
) (*HostAddress
);
1470 if (Type
== AllocateAnyPages
) {
1471 Type
= AllocateMaxAddress
;
1474 Status
= gBS
->AllocatePages (Type
, MemoryType
, Pages
, &PhysicalAddress
);
1475 if (EFI_ERROR (Status
)) {
1476 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
1480 *HostAddress
= (VOID
*) (UINTN
) PhysicalAddress
;
1486 Frees a common buffer
1488 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1489 @param Pages - The number of pages to free.
1490 @param HostAddress - The base address of the allocated range.
1493 @retval EFI_SUCCESS - The requested memory pages were freed.
1494 @retval EFI_INVALID_PARAMETER - The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1501 IN EFI_ISA_IO_PROTOCOL
*This
,
1503 IN VOID
*HostAddress
1507 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1510 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1512 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1514 if (!FeaturePcdGet (PcdIsaBusSupportDma
) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma
)) {
1515 return EFI_UNSUPPORTED
;
1518 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1519 Status
= gBS
->FreePages (
1523 if (EFI_ERROR (Status
)) {
1524 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);