3 Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. <BR>
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
19 The implementation for EFI_ISA_IO_PROTOCOL.
24 // Include common header file for this module.
26 #include "InternalIsaIo.h"
28 #include <IndustryStandard/Pcat.h>
31 // Driver Support Global Variables
33 EFI_ISA_IO_PROTOCOL IsaIoInterface
= {
53 static EFI_ISA_DMA_REGISTERS DmaRegisters
[8] = {
78 }, // Channel 4 is invalid
97 ReportErrorStatusCode (
98 EFI_STATUS_CODE_VALUE Code
104 report a error Status code of PCI bus driver controller
108 Code - The error status code.
112 EFI_SUCCESS - Success to report status code.
117 return REPORT_STATUS_CODE (
118 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
124 // Driver Support Functions
128 InitializeIsaIoInstance (
129 IN ISA_IO_DEVICE
*IsaIoDevice
,
130 IN EFI_ISA_ACPI_RESOURCE_LIST
*IsaDeviceResourceList
136 Initializes an ISA I/O Instance
140 IsaIoDevice - The iso device to be initialized.
141 IsaDeviceResourceList - The resource list.
145 EFI_SUCCESS - Initial success.
150 // Initializes an ISA I/O Instance
155 sizeof (EFI_ISA_IO_PROTOCOL
)
158 IsaIoDevice
->IsaIo
.ResourceList
= IsaDeviceResourceList
;
166 IN EFI_ISA_IO_PROTOCOL
*This
,
167 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
176 Performs an ISA I/O Read Cycle
180 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
181 Width - Signifies the width of the I/O operation.
182 Offset - The offset in ISA I/O space to start the I/O operation.
183 Count - The number of I/O operations to perform.
184 Buffer - The destination buffer to store the results
188 EFI_SUCCESS - The data was read from the device sucessfully.
189 EFI_UNSUPPORTED - The Offset is not valid for this device.
190 EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
191 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
196 ISA_IO_DEVICE
*IsaIoDevice
;
198 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
201 // Verify Isa IO Access
203 Status
= IsaIoVerifyAccess (
210 if (EFI_ERROR (Status
)) {
214 // Call PciIo->Io.Read
216 Status
= IsaIoDevice
->PciIo
->Io
.Read (
218 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
219 EFI_PCI_IO_PASS_THROUGH_BAR
,
225 if (EFI_ERROR (Status
)) {
226 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
235 IN EFI_ISA_IO_PROTOCOL
*This
,
236 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
245 Performs an ISA I/O Write Cycle
249 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
250 Width - Signifies the width of the I/O operation.
251 Offset - The offset in ISA I/O space to start the I/O operation.
252 Count - The number of I/O operations to perform.
253 Buffer - The source buffer to write data from
257 EFI_SUCCESS - The data was writen to the device sucessfully.
258 EFI_UNSUPPORTED - The Offset is not valid for this device.
259 EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
260 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
265 ISA_IO_DEVICE
*IsaIoDevice
;
267 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
270 // Verify Isa IO Access
272 Status
= IsaIoVerifyAccess (
279 if (EFI_ERROR (Status
)) {
283 // Call PciIo->Io.Write
285 Status
= IsaIoDevice
->PciIo
->Io
.Write (
287 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
288 EFI_PCI_IO_PASS_THROUGH_BAR
,
294 if (EFI_ERROR (Status
)) {
295 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
303 IN EFI_ISA_IO_PROTOCOL
*This
,
311 Writes an 8 bit I/O Port
315 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
316 Offset - The offset in ISA IO space to start the IO operation.
317 Value - The data to write port.
321 EFI_SUCCESS - Success.
322 EFI_INVALID_PARAMETER - Parameter is invalid.
323 EFI_UNSUPPORTED - The address range specified by Offset is not valid.
324 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
329 ISA_IO_DEVICE
*IsaIoDevice
;
331 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
334 // Call PciIo->Io.Write
336 Status
= IsaIoDevice
->PciIo
->Io
.Write (
339 EFI_PCI_IO_PASS_THROUGH_BAR
,
344 if (EFI_ERROR (Status
)) {
345 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
356 IN EFI_ISA_IO_PROTOCOL
*This
,
357 IN UINT32 AddrOffset
,
358 IN UINT32 PageOffset
,
359 IN UINT32 CountOffset
,
360 IN UINT32 BaseAddress
,
367 Writes I/O operation base address and count number to a 8 bit I/O Port.
371 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
372 AddrOffset - The address' offset.
373 PageOffset - The page's offest.
374 CountOffset - The count's offset.
375 BaseAddress - The base address.
376 Count - The number of I/O operations to perform.
380 EFI_SUCCESS - Success.
381 EFI_INVALID_PARAMETER - Parameter is invalid.
382 EFI_UNSUPPORTED - The address range specified by these Offsets and Count is not valid.
383 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
389 Status
= WritePort (This
, AddrOffset
, (UINT8
) (BaseAddress
& 0xff));
390 if (EFI_ERROR (Status
)) {
394 Status
= WritePort (This
, AddrOffset
, (UINT8
) ((BaseAddress
>> 8) & 0xff));
395 if (EFI_ERROR (Status
)) {
399 Status
= WritePort (This
, PageOffset
, (UINT8
) ((BaseAddress
>> 16) & 0xff));
400 if (EFI_ERROR (Status
)) {
404 Status
= WritePort (This
, CountOffset
, (UINT8
) (Count
& 0xff));
405 if (EFI_ERROR (Status
)) {
409 Status
= WritePort (This
, CountOffset
, (UINT8
) ((Count
>> 8) & 0xff));
410 if (EFI_ERROR (Status
)) {
420 IN EFI_ISA_IO_PROTOCOL
*This
,
427 Unmaps a memory region for DMA
431 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
432 Mapping - The mapping value returned from EFI_ISA_IO.Map().
436 EFI_SUCCESS - The range was unmapped.
437 EFI_DEVICE_ERROR - The data was not committed to the target system memory.
441 ISA_MAP_INFO
*IsaMapInfo
;
444 // Unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
446 if (!FeaturePcdGet (PcdIsaBusSupportDma
)) {
447 return EFI_UNSUPPORTED
;
451 // See if the Map() operation associated with this Unmap() required a mapping
452 // buffer.If a mapping buffer was not required, then this function simply
453 // returns EFI_SUCCESS.
455 if (Mapping
!= NULL
) {
457 // Get the MAP_INFO structure from Mapping
459 IsaMapInfo
= (ISA_MAP_INFO
*) Mapping
;
462 // If this is a write operation from the Agent's point of view,
463 // then copy the contents of the mapped buffer into the real buffer
464 // so the processor can read the contents of the real buffer.
466 if (IsaMapInfo
->Operation
== EfiIsaIoOperationBusMasterWrite
) {
468 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
469 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
470 IsaMapInfo
->NumberOfBytes
474 // Free the mapped buffer and the MAP_INFO structure.
476 gBS
->FreePages (IsaMapInfo
->MappedHostAddress
, IsaMapInfo
->NumberOfPages
);
477 gBS
->FreePool (IsaMapInfo
);
486 IN EFI_ISA_IO_PROTOCOL
*This
496 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
500 EFI_SUCCESS - The buffers were flushed.
501 EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
506 ISA_IO_DEVICE
*IsaIoDevice
;
508 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
513 Status
= IsaIoDevice
->PciIo
->Flush (IsaIoDevice
->PciIo
);
515 if (EFI_ERROR (Status
)) {
516 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
524 IN ISA_IO_DEVICE
*IsaIoDevice
,
525 IN ISA_ACCESS_TYPE Type
,
526 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
528 IN OUT UINT32
*Offset
534 Verifies access to an ISA device
538 IsaIoDevice - The ISA device to be verified.
539 Type - The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo.
540 Width - Signifies the width of the memory operation.
541 Count - The number of memory operations to perform.
542 Offset - The offset in ISA memory space to start the memory operation.
546 EFI_SUCCESS - Verify success.
547 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
548 EFI_UNSUPPORTED - The device ont support the access type.
552 EFI_ISA_ACPI_RESOURCE
*Item
;
555 if (Width
< EfiIsaIoWidthUint8
||
556 Width
>= EfiIsaIoWidthMaximum
||
557 Width
== EfiIsaIoWidthReserved
||
558 Width
== EfiIsaIoWidthFifoReserved
||
559 Width
== EfiIsaIoWidthFillReserved
561 return EFI_INVALID_PARAMETER
;
565 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
566 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
568 if (Width
>= EfiIsaIoWidthFifoUint8
&& Width
<= EfiIsaIoWidthFifoReserved
) {
572 Width
= (EFI_ISA_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
574 Status
= EFI_UNSUPPORTED
;
575 Item
= IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
;
576 while (Item
->Type
!= EfiIsaAcpiResourceEndOfList
) {
577 if ((Type
== IsaAccessTypeMem
&& Item
->Type
== EfiIsaAcpiResourceMemory
) ||
578 (Type
== IsaAccessTypeIo
&& Item
->Type
== EfiIsaAcpiResourceIo
)
580 if (*Offset
>= Item
->StartRange
&& (*Offset
+ Count
* (UINT32
)(1 << Width
)) - 1 <= Item
->EndRange
) {
584 if (*Offset
>= Item
->StartRange
&& *Offset
<= Item
->EndRange
) {
585 Status
= EFI_INVALID_PARAMETER
;
598 IN EFI_ISA_IO_PROTOCOL
*This
,
599 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
608 Performs an ISA Memory Read Cycle
612 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
613 Width - Signifies the width of the memory operation.
614 Offset - The offset in ISA memory space to start the memory operation.
615 Count - The number of memory operations to perform.
616 Buffer - The destination buffer to store the results
620 EFI_SUCCESS - The data was read from the device successfully.
621 EFI_UNSUPPORTED - The Offset is not valid for this device.
622 EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
623 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
628 ISA_IO_DEVICE
*IsaIoDevice
;
631 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
634 // So we just return EFI_UNSUPPORTED for these functions.
636 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory
)) {
637 return EFI_UNSUPPORTED
;
640 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
643 // Verify the Isa Io Access
645 Status
= IsaIoVerifyAccess (
652 if (EFI_ERROR (Status
)) {
656 // Call PciIo->Mem.Read
658 Status
= IsaIoDevice
->PciIo
->Mem
.Read (
660 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
661 EFI_PCI_IO_PASS_THROUGH_BAR
,
667 if (EFI_ERROR (Status
)) {
668 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
677 IN EFI_ISA_IO_PROTOCOL
*This
,
678 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
687 Performs an ISA Memory Write Cycle
691 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
692 Width - Signifies the width of the memory operation.
693 Offset - The offset in ISA memory space to start the memory operation.
694 Count - The number of memory operations to perform.
695 Buffer - The source buffer to write data from
699 EFI_SUCCESS - The data was written to the device sucessfully.
700 EFI_UNSUPPORTED - The Offset is not valid for this device.
701 EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
702 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
707 ISA_IO_DEVICE
*IsaIoDevice
;
710 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
713 // So we just return EFI_UNSUPPORTED for these functions.
715 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory
)) {
716 return EFI_UNSUPPORTED
;
719 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
722 // Verify Isa IO Access
724 Status
= IsaIoVerifyAccess (
731 if (EFI_ERROR (Status
)) {
735 // Call PciIo->Mem.Write
737 Status
= IsaIoDevice
->PciIo
->Mem
.Write (
739 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
740 EFI_PCI_IO_PASS_THROUGH_BAR
,
746 if (EFI_ERROR (Status
)) {
747 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
756 IN EFI_ISA_IO_PROTOCOL
*This
,
757 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
758 IN UINT32 DestOffset
,
766 Performs an ISA I/O Copy Memory
770 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
771 Width - Signifies the width of the memory copy operation.
772 DestOffset - The offset of the destination
773 SrcOffset - The offset of the source
774 Count - The number of memory copy operations to perform
778 EFI_SUCCESS - The data was copied sucessfully.
779 EFI_UNSUPPORTED - The DestOffset or SrcOffset is not valid for this device.
780 EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
781 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
786 ISA_IO_DEVICE
*IsaIoDevice
;
789 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
792 // So we just return EFI_UNSUPPORTED for these functions.
794 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory
)) {
795 return EFI_UNSUPPORTED
;
798 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
801 // Verify Isa IO Access for destination and source
803 Status
= IsaIoVerifyAccess (
810 if (EFI_ERROR (Status
)) {
814 Status
= IsaIoVerifyAccess (
821 if (EFI_ERROR (Status
)) {
825 // Call PciIo->CopyMem
827 Status
= IsaIoDevice
->PciIo
->CopyMem (
829 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
830 EFI_PCI_IO_PASS_THROUGH_BAR
,
832 EFI_PCI_IO_PASS_THROUGH_BAR
,
837 if (EFI_ERROR (Status
)) {
838 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
846 IsaIoMap_OnlySupportSlaveReadWrite (
847 IN EFI_ISA_IO_PROTOCOL
*This
,
848 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
849 IN UINT8 ChannelNumber OPTIONAL
,
850 IN UINT32 ChannelAttributes
,
851 IN VOID
*HostAddress
,
852 IN OUT UINTN
*NumberOfBytes
,
853 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
860 Maps a memory region for DMA, note this implementation
861 only supports slave read/write operation to save code size.
865 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
866 Operation - Indicates the type of DMA (slave or bus master), and if
867 the DMA operation is going to read or write to system memory.
868 ChannelNumber - The slave channel number to use for this DMA operation.
869 If Operation and ChannelAttributes shows that this device
870 performs bus mastering DMA, then this field is ignored.
871 The legal range for this field is 0..7.
872 ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
873 HostAddress - The system memory address to map to the device.
874 NumberOfBytes - On input the number of bytes to map. On output the number
875 of bytes that were mapped.
876 DeviceAddress - The resulting map address for the bus master device to use
877 to access the hosts HostAddress.
878 Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
882 EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
883 EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
884 EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
885 EFI_DEVICE_ERROR - The system hardware could not map the requested address.
886 EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
891 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
892 ISA_MAP_INFO
*IsaMapInfo
;
894 UINTN MaxNumberOfBytes
;
900 UINT8 DmaChannelMode
;
902 if ((NULL
== This
) ||
903 (NULL
== HostAddress
) ||
904 (NULL
== NumberOfBytes
) ||
905 (NULL
== DeviceAddress
) ||
908 return EFI_INVALID_PARAMETER
;
913 // Initialize the return values to their defaults
918 // Make sure the Operation parameter is valid.
919 // Light IsaIo only supports two operations.
921 if (!(Operation
== EfiIsaIoOperationSlaveRead
||
922 Operation
== EfiIsaIoOperationSlaveWrite
)) {
923 return EFI_INVALID_PARAMETER
;
926 if (ChannelNumber
>= 4) {
928 // The Light IsaIo doesn't support channelNumber larger than 4.
930 return EFI_INVALID_PARAMETER
;
934 // Map the HostAddress to a DeviceAddress.
936 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
937 if ((PhysicalAddress
+*NumberOfBytes
) > ISA_MAX_MEMORY_ADDRESS
) {
939 // Common Buffer operations can not be remapped. If the common buffer
940 // is above 16MB, then it is not possible to generate a mapping, so return
943 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
944 return EFI_UNSUPPORTED
;
947 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
950 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
951 if (IsaMapInfo
== NULL
) {
953 return EFI_OUT_OF_RESOURCES
;
956 // Return a pointer to the MAP_INFO structure in Mapping
958 *Mapping
= IsaMapInfo
;
961 // Initialize the MAP_INFO structure
963 IsaMapInfo
->Operation
= Operation
;
964 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
965 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
966 IsaMapInfo
->HostAddress
= PhysicalAddress
;
967 IsaMapInfo
->MappedHostAddress
= ISA_MAX_MEMORY_ADDRESS
- 1;
970 // Allocate a buffer below 16MB to map the transfer to.
972 Status
= gBS
->AllocatePages (
975 IsaMapInfo
->NumberOfPages
,
976 &IsaMapInfo
->MappedHostAddress
978 if (EFI_ERROR (Status
)) {
979 gBS
->FreePool (IsaMapInfo
);
985 // If this is a read operation from the DMA agents's point of view,
986 // then copy the contents of the real buffer into the mapped buffer
987 // so the DMA agent can read the contents of the real buffer.
989 if (Operation
== EfiIsaIoOperationSlaveRead
) {
991 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
992 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
993 IsaMapInfo
->NumberOfBytes
997 // The DeviceAddress is the address of the maped buffer below 16 MB
999 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1002 // The transfer is below 16 MB, so the DeviceAddress is simply the
1005 *DeviceAddress
= PhysicalAddress
;
1009 // Figure out what to program into the DMA Channel Mode Register
1011 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1012 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1013 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1015 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1018 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
1020 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1023 // A Slave DMA transfer can not cross a 64K boundary.
1024 // Compute *NumberOfBytes based on this restriction.
1026 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1027 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1028 *NumberOfBytes
= MaxNumberOfBytes
;
1031 // Compute the values to program into the BaseAddress and Count registers
1032 // of the Slave DMA controller
1034 BaseAddress
= (UINT32
) (*DeviceAddress
);
1035 Count
= (UINT16
) (*NumberOfBytes
- 1);
1037 // Program the DMA Write Single Mask Register for ChannelNumber
1038 // Clear the DMA Byte Pointer Register
1040 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1041 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1042 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1044 Status
= WritePort (
1047 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1049 if (EFI_ERROR (Status
)) {
1053 Status
= WritePort (
1056 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1058 if (EFI_ERROR (Status
)) {
1062 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1063 if (EFI_ERROR (Status
)) {
1067 Status
= WriteDmaPort (
1069 DmaRegisters
[ChannelNumber
].Address
,
1070 DmaRegisters
[ChannelNumber
].Page
,
1071 DmaRegisters
[ChannelNumber
].Count
,
1075 if (EFI_ERROR (Status
)) {
1079 Status
= WritePort (
1082 (UINT8
) (ChannelNumber
& 0x03)
1084 if (EFI_ERROR (Status
)) {
1093 IsaIoMap_FullSupport (
1094 IN EFI_ISA_IO_PROTOCOL
*This
,
1095 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1096 IN UINT8 ChannelNumber OPTIONAL
,
1097 IN UINT32 ChannelAttributes
,
1098 IN VOID
*HostAddress
,
1099 IN OUT UINTN
*NumberOfBytes
,
1100 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1105 Routine Description:
1107 Maps a memory region for DMA. This implementation implement the
1108 the full mapping support.
1112 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1113 Operation - Indicates the type of DMA (slave or bus master), and if
1114 the DMA operation is going to read or write to system memory.
1115 ChannelNumber - The slave channel number to use for this DMA operation.
1116 If Operation and ChannelAttributes shows that this device
1117 performs bus mastering DMA, then this field is ignored.
1118 The legal range for this field is 0..7.
1119 ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
1120 HostAddress - The system memory address to map to the device.
1121 NumberOfBytes - On input the number of bytes to map. On output the number
1122 of bytes that were mapped.
1123 DeviceAddress - The resulting map address for the bus master device to use
1124 - to access the hosts HostAddress.
1125 Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
1129 EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1130 EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1131 EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1132 EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1133 EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1140 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1141 ISA_MAP_INFO
*IsaMapInfo
;
1143 UINTN MaxNumberOfBytes
;
1149 UINT8 DmaChannelMode
;
1151 if ((NULL
== This
) ||
1152 (NULL
== HostAddress
) ||
1153 (NULL
== NumberOfBytes
) ||
1154 (NULL
== DeviceAddress
) ||
1157 return EFI_INVALID_PARAMETER
;
1162 // Initialize the return values to their defaults
1167 // Make sure the Operation parameter is valid
1169 if (Operation
< 0 || Operation
>= EfiIsaIoOperationMaximum
) {
1170 return EFI_INVALID_PARAMETER
;
1173 // See if this is a Slave DMA Operation
1177 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1178 Operation
= EfiIsaIoOperationBusMasterRead
;
1183 if (Operation
== EfiIsaIoOperationSlaveWrite
) {
1184 Operation
= EfiIsaIoOperationBusMasterWrite
;
1191 // Make sure that ChannelNumber is a valid channel number
1192 // Channel 4 is used to cascade, so it is illegal.
1194 if (ChannelNumber
== 4 || ChannelNumber
> 7) {
1195 return EFI_INVALID_PARAMETER
;
1198 // This implementation only support COMPATIBLE DMA Transfers
1200 if (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE
)) {
1201 return EFI_INVALID_PARAMETER
;
1204 if (ChannelAttributes
&
1206 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A
|
1207 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B
|
1208 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C
1211 return EFI_INVALID_PARAMETER
;
1214 if (ChannelNumber
< 4) {
1216 // If this is Channel 0..3, then the width must be 8 bit
1218 if (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) ||
1219 (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
)
1221 return EFI_INVALID_PARAMETER
;
1225 // If this is Channel 4..7, then the width must be 16 bit
1227 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) ||
1228 (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
))
1230 return EFI_INVALID_PARAMETER
;
1234 // Either Demand Mode or Single Mode must be selected, but not both
1236 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) {
1237 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) {
1238 return EFI_INVALID_PARAMETER
;
1241 if (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
)) {
1242 return EFI_INVALID_PARAMETER
;
1247 // Map the HostAddress to a DeviceAddress.
1249 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1250 if ((PhysicalAddress
+*NumberOfBytes
) > ISA_MAX_MEMORY_ADDRESS
) {
1252 // Common Buffer operations can not be remapped. If the common buffer
1253 // is above 16MB, then it is not possible to generate a mapping, so return
1256 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1257 return EFI_UNSUPPORTED
;
1260 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1263 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1264 if (IsaMapInfo
== NULL
) {
1266 return EFI_OUT_OF_RESOURCES
;
1269 // Return a pointer to the MAP_INFO structure in Mapping
1271 *Mapping
= IsaMapInfo
;
1274 // Initialize the MAP_INFO structure
1276 IsaMapInfo
->Operation
= Operation
;
1277 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
1278 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1279 IsaMapInfo
->HostAddress
= PhysicalAddress
;
1280 IsaMapInfo
->MappedHostAddress
= ISA_MAX_MEMORY_ADDRESS
- 1;
1283 // Allocate a buffer below 16MB to map the transfer to.
1285 Status
= gBS
->AllocatePages (
1287 EfiBootServicesData
,
1288 IsaMapInfo
->NumberOfPages
,
1289 &IsaMapInfo
->MappedHostAddress
1291 if (EFI_ERROR (Status
)) {
1292 gBS
->FreePool (IsaMapInfo
);
1298 // If this is a read operation from the DMA agents's point of view,
1299 // then copy the contents of the real buffer into the mapped buffer
1300 // so the DMA agent can read the contents of the real buffer.
1302 if (Operation
== EfiIsaIoOperationBusMasterRead
) {
1304 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1305 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1306 IsaMapInfo
->NumberOfBytes
1310 // The DeviceAddress is the address of the maped buffer below 16 MB
1312 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1315 // The transfer is below 16 MB, so the DeviceAddress is simply the
1318 *DeviceAddress
= PhysicalAddress
;
1321 // If this is a Bus Master operation then return
1327 // Figure out what to program into the DMA Channel Mode Register
1329 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1331 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1333 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1336 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE
) {
1337 DmaMode
|= B_8237_DMA_CHMODE_AE
;
1340 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) {
1341 DmaMode
|= V_8237_DMA_CHMODE_DEMAND
;
1344 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) {
1345 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1348 // A Slave DMA transfer can not cross a 64K boundary.
1349 // Compute *NumberOfBytes based on this restriction.
1351 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1352 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1353 *NumberOfBytes
= MaxNumberOfBytes
;
1356 // Compute the values to program into the BaseAddress and Count registers
1357 // of the Slave DMA controller
1359 if (ChannelNumber
< 4) {
1360 BaseAddress
= (UINT32
) (*DeviceAddress
);
1361 Count
= (UINT16
) (*NumberOfBytes
- 1);
1363 BaseAddress
= (UINT32
) (((UINT32
) (*DeviceAddress
) & 0xff0000) | (((UINT32
) (*DeviceAddress
) & 0xffff) >> 1));
1364 Count
= (UINT16
) ((*NumberOfBytes
- 1) >> 1);
1367 // Program the DMA Write Single Mask Register for ChannelNumber
1368 // Clear the DMA Byte Pointer Register
1370 if (ChannelNumber
< 4) {
1371 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1372 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1373 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1375 DmaMask
= R_8237_DMA_WRSMSK_CH4_7
;
1376 DmaClear
= R_8237_DMA_CBPR_CH4_7
;
1377 DmaChannelMode
= R_8237_DMA_CHMODE_CH4_7
;
1380 Status
= WritePort (
1383 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1385 if (EFI_ERROR (Status
)) {
1389 Status
= WritePort (
1392 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1394 if (EFI_ERROR (Status
)) {
1398 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1399 if (EFI_ERROR (Status
)) {
1403 Status
= WriteDmaPort (
1405 DmaRegisters
[ChannelNumber
].Address
,
1406 DmaRegisters
[ChannelNumber
].Page
,
1407 DmaRegisters
[ChannelNumber
].Count
,
1411 if (EFI_ERROR (Status
)) {
1415 Status
= WritePort (
1418 (UINT8
) (ChannelNumber
& 0x03)
1420 if (EFI_ERROR (Status
)) {
1430 IN EFI_ISA_IO_PROTOCOL
*This
,
1431 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1432 IN UINT8 ChannelNumber OPTIONAL
,
1433 IN UINT32 ChannelAttributes
,
1434 IN VOID
*HostAddress
,
1435 IN OUT UINTN
*NumberOfBytes
,
1436 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1441 Routine Description:
1443 Maps a memory region for DMA
1447 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1448 Operation - Indicates the type of DMA (slave or bus master), and if
1449 the DMA operation is going to read or write to system memory.
1450 ChannelNumber - The slave channel number to use for this DMA operation.
1451 If Operation and ChannelAttributes shows that this device
1452 performs bus mastering DMA, then this field is ignored.
1453 The legal range for this field is 0..7.
1454 ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
1455 HostAddress - The system memory address to map to the device.
1456 NumberOfBytes - On input the number of bytes to map. On output the number
1457 of bytes that were mapped.
1458 DeviceAddress - The resulting map address for the bus master device to use
1459 - to access the hosts HostAddress.
1460 Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
1464 EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1465 EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1466 EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1467 EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1468 EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1473 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1475 if (!FeaturePcdGet (PcdIsaBusSupportDma
)) {
1476 return EFI_UNSUPPORTED
;
1479 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1482 // So we just return EFI_UNSUPPORTED for these functions.
1484 if (FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma
)) {
1485 return IsaIoMap_OnlySupportSlaveReadWrite (
1497 return IsaIoMap_FullSupport (
1511 IsaIoAllocateBuffer (
1512 IN EFI_ISA_IO_PROTOCOL
*This
,
1513 IN EFI_ALLOCATE_TYPE Type
,
1514 IN EFI_MEMORY_TYPE MemoryType
,
1516 OUT VOID
**HostAddress
,
1517 IN UINT64 Attributes
1521 Routine Description:
1523 Allocates a common buffer for DMA
1527 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1528 Type - The type allocation to perform.
1529 MemoryType - The type of memory to allocate.
1530 Pages - The number of pages to allocate.
1531 HostAddress - A pointer to store the base address of the allocated range.
1532 Attributes - The requested bit mask of attributes for the allocated range.
1536 EFI_SUCCESS - The requested memory pages were allocated.
1537 EFI_INVALID_PARAMETER - Type is invalid or MemoryType is invalid or HostAddress is NULL
1538 EFI_UNSUPPORTED - Attributes is unsupported or the memory range specified
1539 by HostAddress, Pages, and Type is not available for common buffer use.
1540 EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1545 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1548 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1550 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1552 if (!FeaturePcdGet (PcdIsaBusSupportDma
) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma
)) {
1553 return EFI_UNSUPPORTED
;
1556 if (HostAddress
== NULL
) {
1557 return EFI_INVALID_PARAMETER
;
1560 if (Type
< AllocateAnyPages
|| Type
>= MaxAllocateType
) {
1561 return EFI_INVALID_PARAMETER
;
1564 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1566 if (MemoryType
!= EfiBootServicesData
&& MemoryType
!= EfiRuntimeServicesData
) {
1567 return EFI_INVALID_PARAMETER
;
1570 if (Attributes
&~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
| EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED
)) {
1571 return EFI_UNSUPPORTED
;
1574 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) (ISA_MAX_MEMORY_ADDRESS
- 1);
1575 if (Type
== AllocateAddress
) {
1576 if ((UINTN
) (*HostAddress
) >= ISA_MAX_MEMORY_ADDRESS
) {
1577 return EFI_UNSUPPORTED
;
1579 PhysicalAddress
= (UINTN
) (*HostAddress
);
1583 if (Type
== AllocateAnyPages
) {
1584 Type
= AllocateMaxAddress
;
1587 Status
= gBS
->AllocatePages (Type
, MemoryType
, Pages
, &PhysicalAddress
);
1588 if (EFI_ERROR (Status
)) {
1589 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
1593 *HostAddress
= (VOID
*) (UINTN
) PhysicalAddress
;
1600 IN EFI_ISA_IO_PROTOCOL
*This
,
1602 IN VOID
*HostAddress
1606 Routine Description:
1608 Frees a common buffer
1612 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1613 Pages - The number of pages to free.
1614 HostAddress - The base address of the allocated range.
1618 EFI_SUCCESS - The requested memory pages were freed.
1619 EFI_INVALID_PARAMETER - The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1624 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1627 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1629 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1631 if (!FeaturePcdGet (PcdIsaBusSupportDma
) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma
)) {
1632 return EFI_UNSUPPORTED
;
1635 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1636 Status
= gBS
->FreePages (
1640 if (EFI_ERROR (Status
)) {
1641 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);