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 ReportErrorStatusCode (
85 EFI_STATUS_CODE_VALUE Code
91 report a error Status code of PCI bus driver controller
95 Code - The error status code.
99 EFI_SUCCESS - Success to report status code.
104 return REPORT_STATUS_CODE (
105 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
111 // Driver Support Functions
115 InitializeIsaIoInstance (
116 IN ISA_IO_DEVICE
*IsaIoDevice
,
117 IN EFI_ISA_ACPI_RESOURCE_LIST
*IsaDeviceResourceList
123 Initializes an ISA I/O Instance
127 IsaIoDevice - The iso device to be initialized.
128 IsaDeviceResourceList - The resource list.
132 EFI_SUCCESS - Initial success.
137 // Initializes an ISA I/O Instance
142 sizeof (EFI_ISA_IO_PROTOCOL
)
145 IsaIoDevice
->IsaIo
.ResourceList
= IsaDeviceResourceList
;
153 IN EFI_ISA_IO_PROTOCOL
*This
,
154 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
163 Performs an ISA I/O Read Cycle
167 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
168 Width - Signifies the width of the I/O operation.
169 Offset - The offset in ISA I/O space to start the I/O operation.
170 Count - The number of I/O operations to perform.
171 Buffer - The destination buffer to store the results
175 EFI_SUCCESS - The data was read from the device sucessfully.
176 EFI_UNSUPPORTED - The Offset is not valid for this device.
177 EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
178 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
183 ISA_IO_DEVICE
*IsaIoDevice
;
185 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
188 // Verify Isa IO Access
190 Status
= IsaIoVerifyAccess (
197 if (EFI_ERROR (Status
)) {
201 // Call PciIo->Io.Read
203 Status
= IsaIoDevice
->PciIo
->Io
.Read (
205 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
206 EFI_PCI_IO_PASS_THROUGH_BAR
,
212 if (EFI_ERROR (Status
)) {
213 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
222 IN EFI_ISA_IO_PROTOCOL
*This
,
223 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
232 Performs an ISA I/O Write Cycle
236 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
237 Width - Signifies the width of the I/O operation.
238 Offset - The offset in ISA I/O space to start the I/O operation.
239 Count - The number of I/O operations to perform.
240 Buffer - The source buffer to write data from
244 EFI_SUCCESS - The data was writen to the device sucessfully.
245 EFI_UNSUPPORTED - The Offset is not valid for this device.
246 EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
247 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
252 ISA_IO_DEVICE
*IsaIoDevice
;
254 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
257 // Verify Isa IO Access
259 Status
= IsaIoVerifyAccess (
266 if (EFI_ERROR (Status
)) {
270 // Call PciIo->Io.Write
272 Status
= IsaIoDevice
->PciIo
->Io
.Write (
274 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
275 EFI_PCI_IO_PASS_THROUGH_BAR
,
281 if (EFI_ERROR (Status
)) {
282 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
290 IN EFI_ISA_IO_PROTOCOL
*This
,
298 Writes an 8 bit I/O Port
302 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
303 Offset - The offset in ISA IO space to start the IO operation.
304 Value - The data to write port.
308 EFI_SUCCESS - Success.
309 EFI_INVALID_PARAMETER - Parameter is invalid.
310 EFI_UNSUPPORTED - The address range specified by Offset is not valid.
311 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
316 ISA_IO_DEVICE
*IsaIoDevice
;
318 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
321 // Call PciIo->Io.Write
323 Status
= IsaIoDevice
->PciIo
->Io
.Write (
326 EFI_PCI_IO_PASS_THROUGH_BAR
,
331 if (EFI_ERROR (Status
)) {
332 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
343 IN EFI_ISA_IO_PROTOCOL
*This
,
344 IN UINT32 AddrOffset
,
345 IN UINT32 PageOffset
,
346 IN UINT32 CountOffset
,
347 IN UINT32 BaseAddress
,
354 Writes I/O operation base address and count number to a 8 bit I/O Port.
358 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
359 AddrOffset - The address' offset.
360 PageOffset - The page's offest.
361 CountOffset - The count's offset.
362 BaseAddress - The base address.
363 Count - The number of I/O operations to perform.
367 EFI_SUCCESS - Success.
368 EFI_INVALID_PARAMETER - Parameter is invalid.
369 EFI_UNSUPPORTED - The address range specified by these Offsets and Count is not valid.
370 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
376 Status
= WritePort (This
, AddrOffset
, (UINT8
) (BaseAddress
& 0xff));
377 if (EFI_ERROR (Status
)) {
381 Status
= WritePort (This
, AddrOffset
, (UINT8
) ((BaseAddress
>> 8) & 0xff));
382 if (EFI_ERROR (Status
)) {
386 Status
= WritePort (This
, PageOffset
, (UINT8
) ((BaseAddress
>> 16) & 0xff));
387 if (EFI_ERROR (Status
)) {
391 Status
= WritePort (This
, CountOffset
, (UINT8
) (Count
& 0xff));
392 if (EFI_ERROR (Status
)) {
396 Status
= WritePort (This
, CountOffset
, (UINT8
) ((Count
>> 8) & 0xff));
397 if (EFI_ERROR (Status
)) {
407 IN EFI_ISA_IO_PROTOCOL
*This
,
414 Unmaps a memory region for DMA
418 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
419 Mapping - The mapping value returned from EFI_ISA_IO.Map().
423 EFI_SUCCESS - The range was unmapped.
424 EFI_DEVICE_ERROR - The data was not committed to the target system memory.
428 ISA_MAP_INFO
*IsaMapInfo
;
431 // Unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
433 if (!FeaturePcdGet (PcdIsaBusSupportDma
)) {
434 return EFI_UNSUPPORTED
;
438 // See if the Map() operation associated with this Unmap() required a mapping
439 // buffer.If a mapping buffer was not required, then this function simply
440 // returns EFI_SUCCESS.
442 if (Mapping
!= NULL
) {
444 // Get the MAP_INFO structure from Mapping
446 IsaMapInfo
= (ISA_MAP_INFO
*) Mapping
;
449 // If this is a write operation from the Agent's point of view,
450 // then copy the contents of the mapped buffer into the real buffer
451 // so the processor can read the contents of the real buffer.
453 if (IsaMapInfo
->Operation
== EfiIsaIoOperationBusMasterWrite
) {
455 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
456 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
457 IsaMapInfo
->NumberOfBytes
461 // Free the mapped buffer and the MAP_INFO structure.
463 gBS
->FreePages (IsaMapInfo
->MappedHostAddress
, IsaMapInfo
->NumberOfPages
);
464 gBS
->FreePool (IsaMapInfo
);
473 IN EFI_ISA_IO_PROTOCOL
*This
483 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
487 EFI_SUCCESS - The buffers were flushed.
488 EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
493 ISA_IO_DEVICE
*IsaIoDevice
;
495 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
500 Status
= IsaIoDevice
->PciIo
->Flush (IsaIoDevice
->PciIo
);
502 if (EFI_ERROR (Status
)) {
503 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
511 IN ISA_IO_DEVICE
*IsaIoDevice
,
512 IN ISA_ACCESS_TYPE Type
,
513 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
515 IN OUT UINT32
*Offset
521 Verifies access to an ISA device
525 IsaIoDevice - The ISA device to be verified.
526 Type - The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo.
527 Width - Signifies the width of the memory operation.
528 Count - The number of memory operations to perform.
529 Offset - The offset in ISA memory space to start the memory operation.
533 EFI_SUCCESS - Verify success.
534 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
535 EFI_UNSUPPORTED - The device ont support the access type.
539 EFI_ISA_ACPI_RESOURCE
*Item
;
542 if (Width
< EfiIsaIoWidthUint8
||
543 Width
>= EfiIsaIoWidthMaximum
||
544 Width
== EfiIsaIoWidthReserved
||
545 Width
== EfiIsaIoWidthFifoReserved
||
546 Width
== EfiIsaIoWidthFillReserved
548 return EFI_INVALID_PARAMETER
;
552 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
553 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
555 if (Width
>= EfiIsaIoWidthFifoUint8
&& Width
<= EfiIsaIoWidthFifoReserved
) {
559 Width
= (EFI_ISA_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
561 Status
= EFI_UNSUPPORTED
;
562 Item
= IsaIoDevice
->IsaIo
.ResourceList
->ResourceItem
;
563 while (Item
->Type
!= EfiIsaAcpiResourceEndOfList
) {
564 if ((Type
== IsaAccessTypeMem
&& Item
->Type
== EfiIsaAcpiResourceMemory
) ||
565 (Type
== IsaAccessTypeIo
&& Item
->Type
== EfiIsaAcpiResourceIo
)
567 if (*Offset
>= Item
->StartRange
&& (*Offset
+ Count
* (UINT32
)(1 << Width
)) - 1 <= Item
->EndRange
) {
571 if (*Offset
>= Item
->StartRange
&& *Offset
<= Item
->EndRange
) {
572 Status
= EFI_INVALID_PARAMETER
;
585 IN EFI_ISA_IO_PROTOCOL
*This
,
586 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
595 Performs an ISA Memory Read Cycle
599 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
600 Width - Signifies the width of the memory operation.
601 Offset - The offset in ISA memory space to start the memory operation.
602 Count - The number of memory operations to perform.
603 Buffer - The destination buffer to store the results
607 EFI_SUCCESS - The data was read from the device successfully.
608 EFI_UNSUPPORTED - The Offset is not valid for this device.
609 EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
610 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
615 ISA_IO_DEVICE
*IsaIoDevice
;
618 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
621 // So we just return EFI_UNSUPPORTED for these functions.
623 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory
)) {
624 return EFI_UNSUPPORTED
;
627 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
630 // Verify the Isa Io Access
632 Status
= IsaIoVerifyAccess (
639 if (EFI_ERROR (Status
)) {
643 // Call PciIo->Mem.Read
645 Status
= IsaIoDevice
->PciIo
->Mem
.Read (
647 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
648 EFI_PCI_IO_PASS_THROUGH_BAR
,
654 if (EFI_ERROR (Status
)) {
655 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
664 IN EFI_ISA_IO_PROTOCOL
*This
,
665 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
674 Performs an ISA Memory Write Cycle
678 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
679 Width - Signifies the width of the memory operation.
680 Offset - The offset in ISA memory space to start the memory operation.
681 Count - The number of memory operations to perform.
682 Buffer - The source buffer to write data from
686 EFI_SUCCESS - The data was written to the device sucessfully.
687 EFI_UNSUPPORTED - The Offset is not valid for this device.
688 EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
689 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
694 ISA_IO_DEVICE
*IsaIoDevice
;
697 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
700 // So we just return EFI_UNSUPPORTED for these functions.
702 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory
)) {
703 return EFI_UNSUPPORTED
;
706 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
709 // Verify Isa IO Access
711 Status
= IsaIoVerifyAccess (
718 if (EFI_ERROR (Status
)) {
722 // Call PciIo->Mem.Write
724 Status
= IsaIoDevice
->PciIo
->Mem
.Write (
726 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
727 EFI_PCI_IO_PASS_THROUGH_BAR
,
733 if (EFI_ERROR (Status
)) {
734 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
743 IN EFI_ISA_IO_PROTOCOL
*This
,
744 IN EFI_ISA_IO_PROTOCOL_WIDTH Width
,
745 IN UINT32 DestOffset
,
753 Performs an ISA I/O Copy Memory
757 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
758 Width - Signifies the width of the memory copy operation.
759 DestOffset - The offset of the destination
760 SrcOffset - The offset of the source
761 Count - The number of memory copy operations to perform
765 EFI_SUCCESS - The data was copied sucessfully.
766 EFI_UNSUPPORTED - The DestOffset or SrcOffset is not valid for this device.
767 EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
768 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
773 ISA_IO_DEVICE
*IsaIoDevice
;
776 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
779 // So we just return EFI_UNSUPPORTED for these functions.
781 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory
)) {
782 return EFI_UNSUPPORTED
;
785 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (This
);
788 // Verify Isa IO Access for destination and source
790 Status
= IsaIoVerifyAccess (
797 if (EFI_ERROR (Status
)) {
801 Status
= IsaIoVerifyAccess (
808 if (EFI_ERROR (Status
)) {
812 // Call PciIo->CopyMem
814 Status
= IsaIoDevice
->PciIo
->CopyMem (
816 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
817 EFI_PCI_IO_PASS_THROUGH_BAR
,
819 EFI_PCI_IO_PASS_THROUGH_BAR
,
824 if (EFI_ERROR (Status
)) {
825 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
833 IsaIoMap_OnlySupportSlaveReadWrite (
834 IN EFI_ISA_IO_PROTOCOL
*This
,
835 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
836 IN UINT8 ChannelNumber OPTIONAL
,
837 IN UINT32 ChannelAttributes
,
838 IN VOID
*HostAddress
,
839 IN OUT UINTN
*NumberOfBytes
,
840 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
847 Maps a memory region for DMA, note this implementation
848 only supports slave read/write operation to save code size.
852 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
853 Operation - Indicates the type of DMA (slave or bus master), and if
854 the DMA operation is going to read or write to system memory.
855 ChannelNumber - The slave channel number to use for this DMA operation.
856 If Operation and ChannelAttributes shows that this device
857 performs bus mastering DMA, then this field is ignored.
858 The legal range for this field is 0..7.
859 ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
860 HostAddress - The system memory address to map to the device.
861 NumberOfBytes - On input the number of bytes to map. On output the number
862 of bytes that were mapped.
863 DeviceAddress - The resulting map address for the bus master device to use
864 to access the hosts HostAddress.
865 Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
869 EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
870 EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
871 EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
872 EFI_DEVICE_ERROR - The system hardware could not map the requested address.
873 EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
878 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
879 ISA_MAP_INFO
*IsaMapInfo
;
881 UINTN MaxNumberOfBytes
;
887 UINT8 DmaChannelMode
;
889 if ((NULL
== This
) ||
890 (NULL
== HostAddress
) ||
891 (NULL
== NumberOfBytes
) ||
892 (NULL
== DeviceAddress
) ||
895 return EFI_INVALID_PARAMETER
;
900 // Initialize the return values to their defaults
905 // Make sure the Operation parameter is valid.
906 // Light IsaIo only supports two operations.
908 if (!(Operation
== EfiIsaIoOperationSlaveRead
||
909 Operation
== EfiIsaIoOperationSlaveWrite
)) {
910 return EFI_INVALID_PARAMETER
;
913 if (ChannelNumber
>= 4) {
915 // The Light IsaIo doesn't support channelNumber larger than 4.
917 return EFI_INVALID_PARAMETER
;
921 // Map the HostAddress to a DeviceAddress.
923 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
924 if ((PhysicalAddress
+*NumberOfBytes
) > ISA_MAX_MEMORY_ADDRESS
) {
926 // Common Buffer operations can not be remapped. If the common buffer
927 // is above 16MB, then it is not possible to generate a mapping, so return
930 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
931 return EFI_UNSUPPORTED
;
934 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
937 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
938 if (IsaMapInfo
== NULL
) {
940 return EFI_OUT_OF_RESOURCES
;
943 // Return a pointer to the MAP_INFO structure in Mapping
945 *Mapping
= IsaMapInfo
;
948 // Initialize the MAP_INFO structure
950 IsaMapInfo
->Operation
= Operation
;
951 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
952 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
953 IsaMapInfo
->HostAddress
= PhysicalAddress
;
954 IsaMapInfo
->MappedHostAddress
= ISA_MAX_MEMORY_ADDRESS
- 1;
957 // Allocate a buffer below 16MB to map the transfer to.
959 Status
= gBS
->AllocatePages (
962 IsaMapInfo
->NumberOfPages
,
963 &IsaMapInfo
->MappedHostAddress
965 if (EFI_ERROR (Status
)) {
966 gBS
->FreePool (IsaMapInfo
);
972 // If this is a read operation from the DMA agents's point of view,
973 // then copy the contents of the real buffer into the mapped buffer
974 // so the DMA agent can read the contents of the real buffer.
976 if (Operation
== EfiIsaIoOperationSlaveRead
) {
978 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
979 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
980 IsaMapInfo
->NumberOfBytes
984 // The DeviceAddress is the address of the maped buffer below 16 MB
986 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
989 // The transfer is below 16 MB, so the DeviceAddress is simply the
992 *DeviceAddress
= PhysicalAddress
;
996 // Figure out what to program into the DMA Channel Mode Register
998 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
999 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1000 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1002 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1005 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
1007 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1010 // A Slave DMA transfer can not cross a 64K boundary.
1011 // Compute *NumberOfBytes based on this restriction.
1013 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1014 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1015 *NumberOfBytes
= MaxNumberOfBytes
;
1018 // Compute the values to program into the BaseAddress and Count registers
1019 // of the Slave DMA controller
1021 BaseAddress
= (UINT32
) (*DeviceAddress
);
1022 Count
= (UINT16
) (*NumberOfBytes
- 1);
1024 // Program the DMA Write Single Mask Register for ChannelNumber
1025 // Clear the DMA Byte Pointer Register
1027 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1028 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1029 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1031 Status
= WritePort (
1034 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1036 if (EFI_ERROR (Status
)) {
1040 Status
= WritePort (
1043 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1045 if (EFI_ERROR (Status
)) {
1049 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1050 if (EFI_ERROR (Status
)) {
1054 Status
= WriteDmaPort (
1056 DmaRegisters
[ChannelNumber
].Address
,
1057 DmaRegisters
[ChannelNumber
].Page
,
1058 DmaRegisters
[ChannelNumber
].Count
,
1062 if (EFI_ERROR (Status
)) {
1066 Status
= WritePort (
1069 (UINT8
) (ChannelNumber
& 0x03)
1071 if (EFI_ERROR (Status
)) {
1080 IsaIoMap_FullSupport (
1081 IN EFI_ISA_IO_PROTOCOL
*This
,
1082 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1083 IN UINT8 ChannelNumber OPTIONAL
,
1084 IN UINT32 ChannelAttributes
,
1085 IN VOID
*HostAddress
,
1086 IN OUT UINTN
*NumberOfBytes
,
1087 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1092 Routine Description:
1094 Maps a memory region for DMA. This implementation implement the
1095 the full mapping support.
1099 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1100 Operation - Indicates the type of DMA (slave or bus master), and if
1101 the DMA operation is going to read or write to system memory.
1102 ChannelNumber - The slave channel number to use for this DMA operation.
1103 If Operation and ChannelAttributes shows that this device
1104 performs bus mastering DMA, then this field is ignored.
1105 The legal range for this field is 0..7.
1106 ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
1107 HostAddress - The system memory address to map to the device.
1108 NumberOfBytes - On input the number of bytes to map. On output the number
1109 of bytes that were mapped.
1110 DeviceAddress - The resulting map address for the bus master device to use
1111 - to access the hosts HostAddress.
1112 Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
1116 EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1117 EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1118 EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1119 EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1120 EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1127 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1128 ISA_MAP_INFO
*IsaMapInfo
;
1130 UINTN MaxNumberOfBytes
;
1136 UINT8 DmaChannelMode
;
1138 if ((NULL
== This
) ||
1139 (NULL
== HostAddress
) ||
1140 (NULL
== NumberOfBytes
) ||
1141 (NULL
== DeviceAddress
) ||
1144 return EFI_INVALID_PARAMETER
;
1149 // Initialize the return values to their defaults
1154 // Make sure the Operation parameter is valid
1156 if (Operation
< 0 || Operation
>= EfiIsaIoOperationMaximum
) {
1157 return EFI_INVALID_PARAMETER
;
1160 // See if this is a Slave DMA Operation
1164 if (Operation
== EfiIsaIoOperationSlaveRead
) {
1165 Operation
= EfiIsaIoOperationBusMasterRead
;
1170 if (Operation
== EfiIsaIoOperationSlaveWrite
) {
1171 Operation
= EfiIsaIoOperationBusMasterWrite
;
1178 // Make sure that ChannelNumber is a valid channel number
1179 // Channel 4 is used to cascade, so it is illegal.
1181 if (ChannelNumber
== 4 || ChannelNumber
> 7) {
1182 return EFI_INVALID_PARAMETER
;
1185 // This implementation only support COMPATIBLE DMA Transfers
1187 if (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE
)) {
1188 return EFI_INVALID_PARAMETER
;
1191 if (ChannelAttributes
&
1193 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A
|
1194 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B
|
1195 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C
1198 return EFI_INVALID_PARAMETER
;
1201 if (ChannelNumber
< 4) {
1203 // If this is Channel 0..3, then the width must be 8 bit
1205 if (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) ||
1206 (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
)
1208 return EFI_INVALID_PARAMETER
;
1212 // If this is Channel 4..7, then the width must be 16 bit
1214 if ((ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8
) ||
1215 (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16
))
1217 return EFI_INVALID_PARAMETER
;
1221 // Either Demand Mode or Single Mode must be selected, but not both
1223 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) {
1224 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) {
1225 return EFI_INVALID_PARAMETER
;
1228 if (!(ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
)) {
1229 return EFI_INVALID_PARAMETER
;
1234 // Map the HostAddress to a DeviceAddress.
1236 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1237 if ((PhysicalAddress
+*NumberOfBytes
) > ISA_MAX_MEMORY_ADDRESS
) {
1239 // Common Buffer operations can not be remapped. If the common buffer
1240 // is above 16MB, then it is not possible to generate a mapping, so return
1243 if (Operation
== EfiIsaIoOperationBusMasterCommonBuffer
) {
1244 return EFI_UNSUPPORTED
;
1247 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1250 IsaMapInfo
= AllocatePool (sizeof (ISA_MAP_INFO
));
1251 if (IsaMapInfo
== NULL
) {
1253 return EFI_OUT_OF_RESOURCES
;
1256 // Return a pointer to the MAP_INFO structure in Mapping
1258 *Mapping
= IsaMapInfo
;
1261 // Initialize the MAP_INFO structure
1263 IsaMapInfo
->Operation
= Operation
;
1264 IsaMapInfo
->NumberOfBytes
= *NumberOfBytes
;
1265 IsaMapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1266 IsaMapInfo
->HostAddress
= PhysicalAddress
;
1267 IsaMapInfo
->MappedHostAddress
= ISA_MAX_MEMORY_ADDRESS
- 1;
1270 // Allocate a buffer below 16MB to map the transfer to.
1272 Status
= gBS
->AllocatePages (
1274 EfiBootServicesData
,
1275 IsaMapInfo
->NumberOfPages
,
1276 &IsaMapInfo
->MappedHostAddress
1278 if (EFI_ERROR (Status
)) {
1279 gBS
->FreePool (IsaMapInfo
);
1285 // If this is a read operation from the DMA agents's point of view,
1286 // then copy the contents of the real buffer into the mapped buffer
1287 // so the DMA agent can read the contents of the real buffer.
1289 if (Operation
== EfiIsaIoOperationBusMasterRead
) {
1291 (VOID
*) (UINTN
) IsaMapInfo
->MappedHostAddress
,
1292 (VOID
*) (UINTN
) IsaMapInfo
->HostAddress
,
1293 IsaMapInfo
->NumberOfBytes
1297 // The DeviceAddress is the address of the maped buffer below 16 MB
1299 *DeviceAddress
= IsaMapInfo
->MappedHostAddress
;
1302 // The transfer is below 16 MB, so the DeviceAddress is simply the
1305 *DeviceAddress
= PhysicalAddress
;
1308 // If this is a Bus Master operation then return
1314 // Figure out what to program into the DMA Channel Mode Register
1316 DmaMode
= (UINT8
) (B_8237_DMA_CHMODE_INCREMENT
| (ChannelNumber
& 0x03));
1318 DmaMode
|= V_8237_DMA_CHMODE_MEM2IO
;
1320 DmaMode
|= V_8237_DMA_CHMODE_IO2MEM
;
1323 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE
) {
1324 DmaMode
|= B_8237_DMA_CHMODE_AE
;
1327 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE
) {
1328 DmaMode
|= V_8237_DMA_CHMODE_DEMAND
;
1331 if (ChannelAttributes
& EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE
) {
1332 DmaMode
|= V_8237_DMA_CHMODE_SINGLE
;
1335 // A Slave DMA transfer can not cross a 64K boundary.
1336 // Compute *NumberOfBytes based on this restriction.
1338 MaxNumberOfBytes
= 0x10000 - ((UINT32
) (*DeviceAddress
) & 0xffff);
1339 if (*NumberOfBytes
> MaxNumberOfBytes
) {
1340 *NumberOfBytes
= MaxNumberOfBytes
;
1343 // Compute the values to program into the BaseAddress and Count registers
1344 // of the Slave DMA controller
1346 if (ChannelNumber
< 4) {
1347 BaseAddress
= (UINT32
) (*DeviceAddress
);
1348 Count
= (UINT16
) (*NumberOfBytes
- 1);
1350 BaseAddress
= (UINT32
) (((UINT32
) (*DeviceAddress
) & 0xff0000) | (((UINT32
) (*DeviceAddress
) & 0xffff) >> 1));
1351 Count
= (UINT16
) ((*NumberOfBytes
- 1) >> 1);
1354 // Program the DMA Write Single Mask Register for ChannelNumber
1355 // Clear the DMA Byte Pointer Register
1357 if (ChannelNumber
< 4) {
1358 DmaMask
= R_8237_DMA_WRSMSK_CH0_3
;
1359 DmaClear
= R_8237_DMA_CBPR_CH0_3
;
1360 DmaChannelMode
= R_8237_DMA_CHMODE_CH0_3
;
1362 DmaMask
= R_8237_DMA_WRSMSK_CH4_7
;
1363 DmaClear
= R_8237_DMA_CBPR_CH4_7
;
1364 DmaChannelMode
= R_8237_DMA_CHMODE_CH4_7
;
1367 Status
= WritePort (
1370 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1372 if (EFI_ERROR (Status
)) {
1376 Status
= WritePort (
1379 (UINT8
) (B_8237_DMA_WRSMSK_CMS
| (ChannelNumber
& 0x03))
1381 if (EFI_ERROR (Status
)) {
1385 Status
= WritePort (This
, DmaChannelMode
, DmaMode
);
1386 if (EFI_ERROR (Status
)) {
1390 Status
= WriteDmaPort (
1392 DmaRegisters
[ChannelNumber
].Address
,
1393 DmaRegisters
[ChannelNumber
].Page
,
1394 DmaRegisters
[ChannelNumber
].Count
,
1398 if (EFI_ERROR (Status
)) {
1402 Status
= WritePort (
1405 (UINT8
) (ChannelNumber
& 0x03)
1407 if (EFI_ERROR (Status
)) {
1417 IN EFI_ISA_IO_PROTOCOL
*This
,
1418 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation
,
1419 IN UINT8 ChannelNumber OPTIONAL
,
1420 IN UINT32 ChannelAttributes
,
1421 IN VOID
*HostAddress
,
1422 IN OUT UINTN
*NumberOfBytes
,
1423 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1428 Routine Description:
1430 Maps a memory region for DMA
1434 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1435 Operation - Indicates the type of DMA (slave or bus master), and if
1436 the DMA operation is going to read or write to system memory.
1437 ChannelNumber - The slave channel number to use for this DMA operation.
1438 If Operation and ChannelAttributes shows that this device
1439 performs bus mastering DMA, then this field is ignored.
1440 The legal range for this field is 0..7.
1441 ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
1442 HostAddress - The system memory address to map to the device.
1443 NumberOfBytes - On input the number of bytes to map. On output the number
1444 of bytes that were mapped.
1445 DeviceAddress - The resulting map address for the bus master device to use
1446 - to access the hosts HostAddress.
1447 Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
1451 EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1452 EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1453 EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1454 EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1455 EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1460 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1462 if (!FeaturePcdGet (PcdIsaBusSupportDma
)) {
1463 return EFI_UNSUPPORTED
;
1466 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1469 // So we just return EFI_UNSUPPORTED for these functions.
1471 if (FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma
)) {
1472 return IsaIoMap_OnlySupportSlaveReadWrite (
1484 return IsaIoMap_FullSupport (
1498 IsaIoAllocateBuffer (
1499 IN EFI_ISA_IO_PROTOCOL
*This
,
1500 IN EFI_ALLOCATE_TYPE Type
,
1501 IN EFI_MEMORY_TYPE MemoryType
,
1503 OUT VOID
**HostAddress
,
1504 IN UINT64 Attributes
1508 Routine Description:
1510 Allocates a common buffer for DMA
1514 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1515 Type - The type allocation to perform.
1516 MemoryType - The type of memory to allocate.
1517 Pages - The number of pages to allocate.
1518 HostAddress - A pointer to store the base address of the allocated range.
1519 Attributes - The requested bit mask of attributes for the allocated range.
1523 EFI_SUCCESS - The requested memory pages were allocated.
1524 EFI_INVALID_PARAMETER - Type is invalid or MemoryType is invalid or HostAddress is NULL
1525 EFI_UNSUPPORTED - Attributes is unsupported or the memory range specified
1526 by HostAddress, Pages, and Type is not available for common buffer use.
1527 EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1532 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1535 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1537 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1539 if (!FeaturePcdGet (PcdIsaBusSupportDma
) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma
)) {
1540 return EFI_UNSUPPORTED
;
1543 if (HostAddress
== NULL
) {
1544 return EFI_INVALID_PARAMETER
;
1547 if (Type
< AllocateAnyPages
|| Type
>= MaxAllocateType
) {
1548 return EFI_INVALID_PARAMETER
;
1551 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1553 if (MemoryType
!= EfiBootServicesData
&& MemoryType
!= EfiRuntimeServicesData
) {
1554 return EFI_INVALID_PARAMETER
;
1557 if (Attributes
&~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
| EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED
)) {
1558 return EFI_UNSUPPORTED
;
1561 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) (ISA_MAX_MEMORY_ADDRESS
- 1);
1562 if (Type
== AllocateAddress
) {
1563 if ((UINTN
) (*HostAddress
) >= ISA_MAX_MEMORY_ADDRESS
) {
1564 return EFI_UNSUPPORTED
;
1566 PhysicalAddress
= (UINTN
) (*HostAddress
);
1570 if (Type
== AllocateAnyPages
) {
1571 Type
= AllocateMaxAddress
;
1574 Status
= gBS
->AllocatePages (Type
, MemoryType
, Pages
, &PhysicalAddress
);
1575 if (EFI_ERROR (Status
)) {
1576 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);
1580 *HostAddress
= (VOID
*) (UINTN
) PhysicalAddress
;
1587 IN EFI_ISA_IO_PROTOCOL
*This
,
1589 IN VOID
*HostAddress
1593 Routine Description:
1595 Frees a common buffer
1599 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1600 Pages - The number of pages to free.
1601 HostAddress - The base address of the allocated range.
1605 EFI_SUCCESS - The requested memory pages were freed.
1606 EFI_INVALID_PARAMETER - The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1611 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1614 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1616 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1618 if (!FeaturePcdGet (PcdIsaBusSupportDma
) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma
)) {
1619 return EFI_UNSUPPORTED
;
1622 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1623 Status
= gBS
->FreePages (
1627 if (EFI_ERROR (Status
)) {
1628 ReportErrorStatusCode (EFI_IO_BUS_LPC
| EFI_IOB_EC_CONTROLLER_ERROR
);