]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c
1a3497dfdacb0b6f5fbebc7cc1ea325be82c7c67
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaBusDxe / IsaIo.c
1 /*++
2
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
10 Intel Corporation.
11
12
13 Module Name:
14
15 IsaIo.c
16
17 Abstract:
18
19 The implementation for EFI_ISA_IO_PROTOCOL.
20
21 --*/
22
23 //
24 // Include common header file for this module.
25 //
26 #include "InternalIsaIo.h"
27
28 #include <IndustryStandard/Pcat.h>
29
30 //
31 // Driver Support Global Variables
32 //
33 EFI_ISA_IO_PROTOCOL IsaIoInterface = {
34 {
35 IsaIoMemRead,
36 IsaIoMemWrite
37 },
38 {
39 IsaIoIoRead,
40 IsaIoIoWrite
41 },
42 IsaIoCopyMem,
43 IsaIoMap,
44 IsaIoUnmap,
45 IsaIoAllocateBuffer,
46 IsaIoFreeBuffer,
47 IsaIoFlush,
48 NULL,
49 0,
50 NULL
51 };
52
53 static EFI_ISA_DMA_REGISTERS DmaRegisters[8] = {
54 {
55 0x00,
56 0x87,
57 0x01
58 },
59 {
60 0x02,
61 0x83,
62 0x03
63 },
64 {
65 0x04,
66 0x81,
67 0x05
68 },
69 {
70 0x06,
71 0x82,
72 0x07
73 },
74 {
75 0x00,
76 0x00,
77 0x00
78 }, // Channel 4 is invalid
79 {
80 0xC4,
81 0x8B,
82 0xC6
83 },
84 {
85 0xC8,
86 0x89,
87 0xCA
88 },
89 {
90 0xCC,
91 0x8A,
92 0xCE
93 },
94 };
95
96 EFI_STATUS
97 ReportErrorStatusCode (
98 EFI_STATUS_CODE_VALUE Code
99 )
100 /*++
101
102 Routine Description:
103
104 report a error Status code of PCI bus driver controller
105
106 Arguments:
107
108 Code - The error status code.
109
110 Returns:
111
112 EFI_SUCCESS - Success to report status code.
113
114
115 --*/
116 {
117 return REPORT_STATUS_CODE (
118 EFI_ERROR_CODE | EFI_ERROR_MINOR,
119 Code
120 );
121 }
122
123 //
124 // Driver Support Functions
125 //
126
127 EFI_STATUS
128 InitializeIsaIoInstance (
129 IN ISA_IO_DEVICE *IsaIoDevice,
130 IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList
131 )
132 /*++
133
134 Routine Description:
135
136 Initializes an ISA I/O Instance
137
138 Arguments:
139
140 IsaIoDevice - The iso device to be initialized.
141 IsaDeviceResourceList - The resource list.
142
143 Returns:
144
145 EFI_SUCCESS - Initial success.
146
147 --*/
148 {
149 //
150 // Initializes an ISA I/O Instance
151 //
152 CopyMem (
153 &IsaIoDevice->IsaIo,
154 &IsaIoInterface,
155 sizeof (EFI_ISA_IO_PROTOCOL)
156 );
157
158 IsaIoDevice->IsaIo.ResourceList = IsaDeviceResourceList;
159
160 return EFI_SUCCESS;
161 }
162
163 EFI_STATUS
164 EFIAPI
165 IsaIoIoRead (
166 IN EFI_ISA_IO_PROTOCOL *This,
167 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
168 IN UINT32 Offset,
169 IN UINTN Count,
170 IN OUT VOID *Buffer
171 )
172 /*++
173
174 Routine Description:
175
176 Performs an ISA I/O Read Cycle
177
178 Arguments:
179
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
185
186 Returns:
187
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.
192
193 --*/
194 {
195 EFI_STATUS Status;
196 ISA_IO_DEVICE *IsaIoDevice;
197
198 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
199
200 //
201 // Verify Isa IO Access
202 //
203 Status = IsaIoVerifyAccess (
204 IsaIoDevice,
205 IsaAccessTypeIo,
206 Width,
207 Count,
208 &Offset
209 );
210 if (EFI_ERROR (Status)) {
211 return Status;
212 }
213 //
214 // Call PciIo->Io.Read
215 //
216 Status = IsaIoDevice->PciIo->Io.Read (
217 IsaIoDevice->PciIo,
218 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
219 EFI_PCI_IO_PASS_THROUGH_BAR,
220 Offset,
221 Count,
222 Buffer
223 );
224
225 if (EFI_ERROR (Status)) {
226 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
227 }
228
229 return Status;
230 }
231
232 EFI_STATUS
233 EFIAPI
234 IsaIoIoWrite (
235 IN EFI_ISA_IO_PROTOCOL *This,
236 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
237 IN UINT32 Offset,
238 IN UINTN Count,
239 IN OUT VOID *Buffer
240 )
241 /*++
242
243 Routine Description:
244
245 Performs an ISA I/O Write Cycle
246
247 Arguments:
248
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
254
255 Returns:
256
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.
261
262 --*/
263 {
264 EFI_STATUS Status;
265 ISA_IO_DEVICE *IsaIoDevice;
266
267 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
268
269 //
270 // Verify Isa IO Access
271 //
272 Status = IsaIoVerifyAccess (
273 IsaIoDevice,
274 IsaAccessTypeIo,
275 Width,
276 Count,
277 &Offset
278 );
279 if (EFI_ERROR (Status)) {
280 return Status;
281 }
282 //
283 // Call PciIo->Io.Write
284 //
285 Status = IsaIoDevice->PciIo->Io.Write (
286 IsaIoDevice->PciIo,
287 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
288 EFI_PCI_IO_PASS_THROUGH_BAR,
289 Offset,
290 Count,
291 Buffer
292 );
293
294 if (EFI_ERROR (Status)) {
295 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
296 }
297
298 return Status;
299 }
300
301 EFI_STATUS
302 WritePort (
303 IN EFI_ISA_IO_PROTOCOL *This,
304 IN UINT32 Offset,
305 IN UINT8 Value
306 )
307 /*++
308
309 Routine Description:
310
311 Writes an 8 bit I/O Port
312
313 Arguments:
314
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.
318
319 Returns:
320
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.
325
326 --*/
327 {
328 EFI_STATUS Status;
329 ISA_IO_DEVICE *IsaIoDevice;
330
331 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
332
333 //
334 // Call PciIo->Io.Write
335 //
336 Status = IsaIoDevice->PciIo->Io.Write (
337 IsaIoDevice->PciIo,
338 EfiPciIoWidthUint8,
339 EFI_PCI_IO_PASS_THROUGH_BAR,
340 Offset,
341 1,
342 &Value
343 );
344 if (EFI_ERROR (Status)) {
345 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
346 return Status;
347 }
348
349 gBS->Stall (50);
350
351 return EFI_SUCCESS;
352 }
353
354 EFI_STATUS
355 WriteDmaPort (
356 IN EFI_ISA_IO_PROTOCOL *This,
357 IN UINT32 AddrOffset,
358 IN UINT32 PageOffset,
359 IN UINT32 CountOffset,
360 IN UINT32 BaseAddress,
361 IN UINT16 Count
362 )
363 /*++
364
365 Routine Description:
366
367 Writes I/O operation base address and count number to a 8 bit I/O Port.
368
369 Arguments:
370
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.
377
378 Returns:
379
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.
384
385 --*/
386 {
387 EFI_STATUS Status;
388
389 Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff));
390 if (EFI_ERROR (Status)) {
391 return Status;
392 }
393
394 Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff));
395 if (EFI_ERROR (Status)) {
396 return Status;
397 }
398
399 Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff));
400 if (EFI_ERROR (Status)) {
401 return Status;
402 }
403
404 Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff));
405 if (EFI_ERROR (Status)) {
406 return Status;
407 }
408
409 Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff));
410 if (EFI_ERROR (Status)) {
411 return Status;
412 }
413
414 return EFI_SUCCESS;
415 }
416
417 EFI_STATUS
418 EFIAPI
419 IsaIoUnmap (
420 IN EFI_ISA_IO_PROTOCOL *This,
421 IN VOID *Mapping
422 )
423 /*++
424
425 Routine Description:
426
427 Unmaps a memory region for DMA
428
429 Arguments:
430
431 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
432 Mapping - The mapping value returned from EFI_ISA_IO.Map().
433
434 Returns:
435
436 EFI_SUCCESS - The range was unmapped.
437 EFI_DEVICE_ERROR - The data was not committed to the target system memory.
438
439 --*/
440 {
441 ISA_MAP_INFO *IsaMapInfo;
442
443 //
444 // Unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
445 //
446 if (!FeaturePcdGet (PcdIsaBusSupportDma)) {
447 return EFI_UNSUPPORTED;
448 }
449
450 //
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.
454 //
455 if (Mapping != NULL) {
456 //
457 // Get the MAP_INFO structure from Mapping
458 //
459 IsaMapInfo = (ISA_MAP_INFO *) Mapping;
460
461 //
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.
465 //
466 if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) {
467 CopyMem (
468 (VOID *) (UINTN) IsaMapInfo->HostAddress,
469 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
470 IsaMapInfo->NumberOfBytes
471 );
472 }
473 //
474 // Free the mapped buffer and the MAP_INFO structure.
475 //
476 gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages);
477 gBS->FreePool (IsaMapInfo);
478 }
479
480 return EFI_SUCCESS;
481 }
482
483 EFI_STATUS
484 EFIAPI
485 IsaIoFlush (
486 IN EFI_ISA_IO_PROTOCOL *This
487 )
488 /*++
489
490 Routine Description:
491
492 Flushes a DMA buffer
493
494 Arguments:
495
496 This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
497
498 Returns:
499
500 EFI_SUCCESS - The buffers were flushed.
501 EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
502
503 --*/
504 {
505 EFI_STATUS Status;
506 ISA_IO_DEVICE *IsaIoDevice;
507
508 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
509
510 //
511 // Call PciIo->Flush
512 //
513 Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo);
514
515 if (EFI_ERROR (Status)) {
516 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
517 }
518
519 return Status;
520 }
521
522 EFI_STATUS
523 IsaIoVerifyAccess (
524 IN ISA_IO_DEVICE *IsaIoDevice,
525 IN ISA_ACCESS_TYPE Type,
526 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
527 IN UINTN Count,
528 IN OUT UINT32 *Offset
529 )
530 /*++
531
532 Routine Description:
533
534 Verifies access to an ISA device
535
536 Arguments:
537
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.
543
544 Returns:
545
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.
549
550 --*/
551 {
552 EFI_ISA_ACPI_RESOURCE *Item;
553 EFI_STATUS Status;
554
555 if (Width < EfiIsaIoWidthUint8 ||
556 Width >= EfiIsaIoWidthMaximum ||
557 Width == EfiIsaIoWidthReserved ||
558 Width == EfiIsaIoWidthFifoReserved ||
559 Width == EfiIsaIoWidthFillReserved
560 ) {
561 return EFI_INVALID_PARAMETER;
562 }
563
564 //
565 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
566 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
567 //
568 if (Width >= EfiIsaIoWidthFifoUint8 && Width <= EfiIsaIoWidthFifoReserved) {
569 Count = 1;
570 }
571
572 Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03);
573
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)
579 ) {
580 if (*Offset >= Item->StartRange && (*Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) {
581 return EFI_SUCCESS;
582 }
583
584 if (*Offset >= Item->StartRange && *Offset <= Item->EndRange) {
585 Status = EFI_INVALID_PARAMETER;
586 }
587 }
588
589 Item++;
590 }
591
592 return Status;
593 }
594
595 EFI_STATUS
596 EFIAPI
597 IsaIoMemRead (
598 IN EFI_ISA_IO_PROTOCOL *This,
599 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
600 IN UINT32 Offset,
601 IN UINTN Count,
602 IN OUT VOID *Buffer
603 )
604 /*++
605
606 Routine Description:
607
608 Performs an ISA Memory Read Cycle
609
610 Arguments:
611
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
617
618 Returns:
619
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.
624
625 --*/
626 {
627 EFI_STATUS Status;
628 ISA_IO_DEVICE *IsaIoDevice;
629
630 //
631 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
632 // ISA Bus Master.
633 //
634 // So we just return EFI_UNSUPPORTED for these functions.
635 //
636 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory)) {
637 return EFI_UNSUPPORTED;
638 }
639
640 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
641
642 //
643 // Verify the Isa Io Access
644 //
645 Status = IsaIoVerifyAccess (
646 IsaIoDevice,
647 IsaAccessTypeMem,
648 Width,
649 Count,
650 &Offset
651 );
652 if (EFI_ERROR (Status)) {
653 return Status;
654 }
655 //
656 // Call PciIo->Mem.Read
657 //
658 Status = IsaIoDevice->PciIo->Mem.Read (
659 IsaIoDevice->PciIo,
660 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
661 EFI_PCI_IO_PASS_THROUGH_BAR,
662 Offset,
663 Count,
664 Buffer
665 );
666
667 if (EFI_ERROR (Status)) {
668 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
669 }
670
671 return Status;
672 }
673
674 EFI_STATUS
675 EFIAPI
676 IsaIoMemWrite (
677 IN EFI_ISA_IO_PROTOCOL *This,
678 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
679 IN UINT32 Offset,
680 IN UINTN Count,
681 IN OUT VOID *Buffer
682 )
683 /*++
684
685 Routine Description:
686
687 Performs an ISA Memory Write Cycle
688
689 Arguments:
690
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
696
697 Returns:
698
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.
703
704 --*/
705 {
706 EFI_STATUS Status;
707 ISA_IO_DEVICE *IsaIoDevice;
708
709 //
710 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
711 // ISA Bus Master.
712 //
713 // So we just return EFI_UNSUPPORTED for these functions.
714 //
715 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory)) {
716 return EFI_UNSUPPORTED;
717 }
718
719 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
720
721 //
722 // Verify Isa IO Access
723 //
724 Status = IsaIoVerifyAccess (
725 IsaIoDevice,
726 IsaAccessTypeMem,
727 Width,
728 Count,
729 &Offset
730 );
731 if (EFI_ERROR (Status)) {
732 return Status;
733 }
734 //
735 // Call PciIo->Mem.Write
736 //
737 Status = IsaIoDevice->PciIo->Mem.Write (
738 IsaIoDevice->PciIo,
739 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
740 EFI_PCI_IO_PASS_THROUGH_BAR,
741 Offset,
742 Count,
743 Buffer
744 );
745
746 if (EFI_ERROR (Status)) {
747 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
748 }
749
750 return Status;
751 }
752
753 EFI_STATUS
754 EFIAPI
755 IsaIoCopyMem (
756 IN EFI_ISA_IO_PROTOCOL *This,
757 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
758 IN UINT32 DestOffset,
759 IN UINT32 SrcOffset,
760 IN UINTN Count
761 )
762 /*++
763
764 Routine Description:
765
766 Performs an ISA I/O Copy Memory
767
768 Arguments:
769
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
775
776 Returns:
777
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.
782
783 --*/
784 {
785 EFI_STATUS Status;
786 ISA_IO_DEVICE *IsaIoDevice;
787
788 //
789 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
790 // ISA Bus Master.
791 //
792 // So we just return EFI_UNSUPPORTED for these functions.
793 //
794 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory)) {
795 return EFI_UNSUPPORTED;
796 }
797
798 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
799
800 //
801 // Verify Isa IO Access for destination and source
802 //
803 Status = IsaIoVerifyAccess (
804 IsaIoDevice,
805 IsaAccessTypeMem,
806 Width,
807 Count,
808 &DestOffset
809 );
810 if (EFI_ERROR (Status)) {
811 return Status;
812 }
813
814 Status = IsaIoVerifyAccess (
815 IsaIoDevice,
816 IsaAccessTypeMem,
817 Width,
818 Count,
819 &SrcOffset
820 );
821 if (EFI_ERROR (Status)) {
822 return Status;
823 }
824 //
825 // Call PciIo->CopyMem
826 //
827 Status = IsaIoDevice->PciIo->CopyMem (
828 IsaIoDevice->PciIo,
829 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
830 EFI_PCI_IO_PASS_THROUGH_BAR,
831 DestOffset,
832 EFI_PCI_IO_PASS_THROUGH_BAR,
833 SrcOffset,
834 Count
835 );
836
837 if (EFI_ERROR (Status)) {
838 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
839 }
840
841 return Status;
842 }
843
844 STATIC
845 EFI_STATUS
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,
854 OUT VOID **Mapping
855 )
856 /*++
857
858 Routine Description:
859
860 Maps a memory region for DMA, note this implementation
861 only supports slave read/write operation to save code size.
862
863 Arguments:
864
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().
879
880 Returns:
881
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.
887
888 --*/
889 {
890 EFI_STATUS Status;
891 EFI_PHYSICAL_ADDRESS PhysicalAddress;
892 ISA_MAP_INFO *IsaMapInfo;
893 UINT8 DmaMode;
894 UINTN MaxNumberOfBytes;
895 UINT32 BaseAddress;
896 UINT16 Count;
897
898 UINT8 DmaMask;
899 UINT8 DmaClear;
900 UINT8 DmaChannelMode;
901
902 if ((NULL == This) ||
903 (NULL == HostAddress) ||
904 (NULL == NumberOfBytes) ||
905 (NULL == DeviceAddress) ||
906 (NULL == Mapping)
907 ) {
908 return EFI_INVALID_PARAMETER;
909 }
910
911
912 //
913 // Initialize the return values to their defaults
914 //
915 *Mapping = NULL;
916
917 //
918 // Make sure the Operation parameter is valid.
919 // Light IsaIo only supports two operations.
920 //
921 if (!(Operation == EfiIsaIoOperationSlaveRead ||
922 Operation == EfiIsaIoOperationSlaveWrite)) {
923 return EFI_INVALID_PARAMETER;
924 }
925
926 if (ChannelNumber >= 4) {
927 //
928 // The Light IsaIo doesn't support channelNumber larger than 4.
929 //
930 return EFI_INVALID_PARAMETER;
931 }
932
933 //
934 // Map the HostAddress to a DeviceAddress.
935 //
936 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
937 if ((PhysicalAddress +*NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) {
938 //
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
941 // an error.
942 //
943 if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {
944 return EFI_UNSUPPORTED;
945 }
946 //
947 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
948 // is called later.
949 //
950 IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));
951 if (IsaMapInfo == NULL) {
952 *NumberOfBytes = 0;
953 return EFI_OUT_OF_RESOURCES;
954 }
955 //
956 // Return a pointer to the MAP_INFO structure in Mapping
957 //
958 *Mapping = IsaMapInfo;
959
960 //
961 // Initialize the MAP_INFO structure
962 //
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;
968
969 //
970 // Allocate a buffer below 16MB to map the transfer to.
971 //
972 Status = gBS->AllocatePages (
973 AllocateMaxAddress,
974 EfiBootServicesData,
975 IsaMapInfo->NumberOfPages,
976 &IsaMapInfo->MappedHostAddress
977 );
978 if (EFI_ERROR (Status)) {
979 gBS->FreePool (IsaMapInfo);
980 *NumberOfBytes = 0;
981 *Mapping = NULL;
982 return Status;
983 }
984 //
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.
988 //
989 if (Operation == EfiIsaIoOperationSlaveRead) {
990 CopyMem (
991 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
992 (VOID *) (UINTN) IsaMapInfo->HostAddress,
993 IsaMapInfo->NumberOfBytes
994 );
995 }
996 //
997 // The DeviceAddress is the address of the maped buffer below 16 MB
998 //
999 *DeviceAddress = IsaMapInfo->MappedHostAddress;
1000 } else {
1001 //
1002 // The transfer is below 16 MB, so the DeviceAddress is simply the
1003 // HostAddress
1004 //
1005 *DeviceAddress = PhysicalAddress;
1006 }
1007
1008 //
1009 // Figure out what to program into the DMA Channel Mode Register
1010 //
1011 DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));
1012 if (Operation == EfiIsaIoOperationSlaveRead) {
1013 DmaMode |= V_8237_DMA_CHMODE_MEM2IO;
1014 } else {
1015 DmaMode |= V_8237_DMA_CHMODE_IO2MEM;
1016 }
1017 //
1018 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
1019 //
1020 DmaMode |= V_8237_DMA_CHMODE_SINGLE;
1021
1022 //
1023 // A Slave DMA transfer can not cross a 64K boundary.
1024 // Compute *NumberOfBytes based on this restriction.
1025 //
1026 MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);
1027 if (*NumberOfBytes > MaxNumberOfBytes) {
1028 *NumberOfBytes = MaxNumberOfBytes;
1029 }
1030 //
1031 // Compute the values to program into the BaseAddress and Count registers
1032 // of the Slave DMA controller
1033 //
1034 BaseAddress = (UINT32) (*DeviceAddress);
1035 Count = (UINT16) (*NumberOfBytes - 1);
1036 //
1037 // Program the DMA Write Single Mask Register for ChannelNumber
1038 // Clear the DMA Byte Pointer Register
1039 //
1040 DmaMask = R_8237_DMA_WRSMSK_CH0_3;
1041 DmaClear = R_8237_DMA_CBPR_CH0_3;
1042 DmaChannelMode = R_8237_DMA_CHMODE_CH0_3;
1043
1044 Status = WritePort (
1045 This,
1046 DmaMask,
1047 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1048 );
1049 if (EFI_ERROR (Status)) {
1050 return Status;
1051 }
1052
1053 Status = WritePort (
1054 This,
1055 DmaClear,
1056 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1057 );
1058 if (EFI_ERROR (Status)) {
1059 return Status;
1060 }
1061
1062 Status = WritePort (This, DmaChannelMode, DmaMode);
1063 if (EFI_ERROR (Status)) {
1064 return Status;
1065 }
1066
1067 Status = WriteDmaPort (
1068 This,
1069 DmaRegisters[ChannelNumber].Address,
1070 DmaRegisters[ChannelNumber].Page,
1071 DmaRegisters[ChannelNumber].Count,
1072 BaseAddress,
1073 Count
1074 );
1075 if (EFI_ERROR (Status)) {
1076 return Status;
1077 }
1078
1079 Status = WritePort (
1080 This,
1081 DmaMask,
1082 (UINT8) (ChannelNumber & 0x03)
1083 );
1084 if (EFI_ERROR (Status)) {
1085 return Status;
1086 }
1087
1088 return EFI_SUCCESS;
1089 }
1090
1091 STATIC
1092 EFI_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,
1101 OUT VOID **Mapping
1102 )
1103 /*++
1104
1105 Routine Description:
1106
1107 Maps a memory region for DMA. This implementation implement the
1108 the full mapping support.
1109
1110 Arguments:
1111
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().
1126
1127 Returns:
1128
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.
1134
1135 --*/
1136 {
1137 EFI_STATUS Status;
1138 BOOLEAN Master;
1139 BOOLEAN Read;
1140 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1141 ISA_MAP_INFO *IsaMapInfo;
1142 UINT8 DmaMode;
1143 UINTN MaxNumberOfBytes;
1144 UINT32 BaseAddress;
1145 UINT16 Count;
1146
1147 UINT8 DmaMask;
1148 UINT8 DmaClear;
1149 UINT8 DmaChannelMode;
1150
1151 if ((NULL == This) ||
1152 (NULL == HostAddress) ||
1153 (NULL == NumberOfBytes) ||
1154 (NULL == DeviceAddress) ||
1155 (NULL == Mapping)
1156 ) {
1157 return EFI_INVALID_PARAMETER;
1158 }
1159
1160
1161 //
1162 // Initialize the return values to their defaults
1163 //
1164 *Mapping = NULL;
1165
1166 //
1167 // Make sure the Operation parameter is valid
1168 //
1169 if (Operation < 0 || Operation >= EfiIsaIoOperationMaximum) {
1170 return EFI_INVALID_PARAMETER;
1171 }
1172 //
1173 // See if this is a Slave DMA Operation
1174 //
1175 Master = TRUE;
1176 Read = FALSE;
1177 if (Operation == EfiIsaIoOperationSlaveRead) {
1178 Operation = EfiIsaIoOperationBusMasterRead;
1179 Master = FALSE;
1180 Read = TRUE;
1181 }
1182
1183 if (Operation == EfiIsaIoOperationSlaveWrite) {
1184 Operation = EfiIsaIoOperationBusMasterWrite;
1185 Master = FALSE;
1186 Read = FALSE;
1187 }
1188
1189 if (!Master) {
1190 //
1191 // Make sure that ChannelNumber is a valid channel number
1192 // Channel 4 is used to cascade, so it is illegal.
1193 //
1194 if (ChannelNumber == 4 || ChannelNumber > 7) {
1195 return EFI_INVALID_PARAMETER;
1196 }
1197 //
1198 // This implementation only support COMPATIBLE DMA Transfers
1199 //
1200 if (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE)) {
1201 return EFI_INVALID_PARAMETER;
1202 }
1203
1204 if (ChannelAttributes &
1205 (
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
1209 )
1210 ) {
1211 return EFI_INVALID_PARAMETER;
1212 }
1213
1214 if (ChannelNumber < 4) {
1215 //
1216 // If this is Channel 0..3, then the width must be 8 bit
1217 //
1218 if (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) ||
1219 (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16)
1220 ) {
1221 return EFI_INVALID_PARAMETER;
1222 }
1223 } else {
1224 //
1225 // If this is Channel 4..7, then the width must be 16 bit
1226 //
1227 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) ||
1228 (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16))
1229 ) {
1230 return EFI_INVALID_PARAMETER;
1231 }
1232 }
1233 //
1234 // Either Demand Mode or Single Mode must be selected, but not both
1235 //
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;
1239 }
1240 } else {
1241 if (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE)) {
1242 return EFI_INVALID_PARAMETER;
1243 }
1244 }
1245 }
1246 //
1247 // Map the HostAddress to a DeviceAddress.
1248 //
1249 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1250 if ((PhysicalAddress +*NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) {
1251 //
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
1254 // an error.
1255 //
1256 if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {
1257 return EFI_UNSUPPORTED;
1258 }
1259 //
1260 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1261 // is called later.
1262 //
1263 IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));
1264 if (IsaMapInfo == NULL) {
1265 *NumberOfBytes = 0;
1266 return EFI_OUT_OF_RESOURCES;
1267 }
1268 //
1269 // Return a pointer to the MAP_INFO structure in Mapping
1270 //
1271 *Mapping = IsaMapInfo;
1272
1273 //
1274 // Initialize the MAP_INFO structure
1275 //
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;
1281
1282 //
1283 // Allocate a buffer below 16MB to map the transfer to.
1284 //
1285 Status = gBS->AllocatePages (
1286 AllocateMaxAddress,
1287 EfiBootServicesData,
1288 IsaMapInfo->NumberOfPages,
1289 &IsaMapInfo->MappedHostAddress
1290 );
1291 if (EFI_ERROR (Status)) {
1292 gBS->FreePool (IsaMapInfo);
1293 *NumberOfBytes = 0;
1294 *Mapping = NULL;
1295 return Status;
1296 }
1297 //
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.
1301 //
1302 if (Operation == EfiIsaIoOperationBusMasterRead) {
1303 CopyMem (
1304 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
1305 (VOID *) (UINTN) IsaMapInfo->HostAddress,
1306 IsaMapInfo->NumberOfBytes
1307 );
1308 }
1309 //
1310 // The DeviceAddress is the address of the maped buffer below 16 MB
1311 //
1312 *DeviceAddress = IsaMapInfo->MappedHostAddress;
1313 } else {
1314 //
1315 // The transfer is below 16 MB, so the DeviceAddress is simply the
1316 // HostAddress
1317 //
1318 *DeviceAddress = PhysicalAddress;
1319 }
1320 //
1321 // If this is a Bus Master operation then return
1322 //
1323 if (Master) {
1324 return EFI_SUCCESS;
1325 }
1326 //
1327 // Figure out what to program into the DMA Channel Mode Register
1328 //
1329 DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));
1330 if (Read) {
1331 DmaMode |= V_8237_DMA_CHMODE_MEM2IO;
1332 } else {
1333 DmaMode |= V_8237_DMA_CHMODE_IO2MEM;
1334 }
1335
1336 if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) {
1337 DmaMode |= B_8237_DMA_CHMODE_AE;
1338 }
1339
1340 if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) {
1341 DmaMode |= V_8237_DMA_CHMODE_DEMAND;
1342 }
1343
1344 if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) {
1345 DmaMode |= V_8237_DMA_CHMODE_SINGLE;
1346 }
1347 //
1348 // A Slave DMA transfer can not cross a 64K boundary.
1349 // Compute *NumberOfBytes based on this restriction.
1350 //
1351 MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);
1352 if (*NumberOfBytes > MaxNumberOfBytes) {
1353 *NumberOfBytes = MaxNumberOfBytes;
1354 }
1355 //
1356 // Compute the values to program into the BaseAddress and Count registers
1357 // of the Slave DMA controller
1358 //
1359 if (ChannelNumber < 4) {
1360 BaseAddress = (UINT32) (*DeviceAddress);
1361 Count = (UINT16) (*NumberOfBytes - 1);
1362 } else {
1363 BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1));
1364 Count = (UINT16) ((*NumberOfBytes - 1) >> 1);
1365 }
1366 //
1367 // Program the DMA Write Single Mask Register for ChannelNumber
1368 // Clear the DMA Byte Pointer Register
1369 //
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;
1374 } else {
1375 DmaMask = R_8237_DMA_WRSMSK_CH4_7;
1376 DmaClear = R_8237_DMA_CBPR_CH4_7;
1377 DmaChannelMode = R_8237_DMA_CHMODE_CH4_7;
1378 }
1379
1380 Status = WritePort (
1381 This,
1382 DmaMask,
1383 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1384 );
1385 if (EFI_ERROR (Status)) {
1386 return Status;
1387 }
1388
1389 Status = WritePort (
1390 This,
1391 DmaClear,
1392 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1393 );
1394 if (EFI_ERROR (Status)) {
1395 return Status;
1396 }
1397
1398 Status = WritePort (This, DmaChannelMode, DmaMode);
1399 if (EFI_ERROR (Status)) {
1400 return Status;
1401 }
1402
1403 Status = WriteDmaPort (
1404 This,
1405 DmaRegisters[ChannelNumber].Address,
1406 DmaRegisters[ChannelNumber].Page,
1407 DmaRegisters[ChannelNumber].Count,
1408 BaseAddress,
1409 Count
1410 );
1411 if (EFI_ERROR (Status)) {
1412 return Status;
1413 }
1414
1415 Status = WritePort (
1416 This,
1417 DmaMask,
1418 (UINT8) (ChannelNumber & 0x03)
1419 );
1420 if (EFI_ERROR (Status)) {
1421 return Status;
1422 }
1423
1424 return EFI_SUCCESS;
1425 }
1426
1427 EFI_STATUS
1428 EFIAPI
1429 IsaIoMap (
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,
1437 OUT VOID **Mapping
1438 )
1439 /*++
1440
1441 Routine Description:
1442
1443 Maps a memory region for DMA
1444
1445 Arguments:
1446
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().
1461
1462 Returns:
1463
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.
1469
1470 --*/
1471 {
1472 //
1473 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1474 //
1475 if (!FeaturePcdGet (PcdIsaBusSupportDma)) {
1476 return EFI_UNSUPPORTED;
1477 }
1478 //
1479 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1480 // ISA Bus Master.
1481 //
1482 // So we just return EFI_UNSUPPORTED for these functions.
1483 //
1484 if (FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma)) {
1485 return IsaIoMap_OnlySupportSlaveReadWrite (
1486 This,
1487 Operation,
1488 ChannelNumber,
1489 ChannelAttributes,
1490 HostAddress,
1491 NumberOfBytes,
1492 DeviceAddress,
1493 Mapping
1494 );
1495
1496 } else {
1497 return IsaIoMap_FullSupport (
1498 This,
1499 Operation,
1500 ChannelNumber,
1501 ChannelAttributes,
1502 HostAddress,
1503 NumberOfBytes,
1504 DeviceAddress,
1505 Mapping
1506 );
1507 }
1508 }
1509 EFI_STATUS
1510 EFIAPI
1511 IsaIoAllocateBuffer (
1512 IN EFI_ISA_IO_PROTOCOL *This,
1513 IN EFI_ALLOCATE_TYPE Type,
1514 IN EFI_MEMORY_TYPE MemoryType,
1515 IN UINTN Pages,
1516 OUT VOID **HostAddress,
1517 IN UINT64 Attributes
1518 )
1519 /*++
1520
1521 Routine Description:
1522
1523 Allocates a common buffer for DMA
1524
1525 Arguments:
1526
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.
1533
1534 Returns:
1535
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.
1541
1542 --*/
1543 {
1544 EFI_STATUS Status;
1545 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1546
1547 //
1548 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1549 // ISA Bus Master.
1550 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1551 //
1552 if (!FeaturePcdGet (PcdIsaBusSupportDma) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma)) {
1553 return EFI_UNSUPPORTED;
1554 }
1555
1556 if (HostAddress == NULL) {
1557 return EFI_INVALID_PARAMETER;
1558 }
1559
1560 if (Type < AllocateAnyPages || Type >= MaxAllocateType) {
1561 return EFI_INVALID_PARAMETER;
1562 }
1563 //
1564 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1565 //
1566 if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
1567 return EFI_INVALID_PARAMETER;
1568 }
1569
1570 if (Attributes &~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) {
1571 return EFI_UNSUPPORTED;
1572 }
1573
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;
1578 } else {
1579 PhysicalAddress = (UINTN) (*HostAddress);
1580 }
1581 }
1582
1583 if (Type == AllocateAnyPages) {
1584 Type = AllocateMaxAddress;
1585 }
1586
1587 Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress);
1588 if (EFI_ERROR (Status)) {
1589 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
1590 return Status;
1591 }
1592
1593 *HostAddress = (VOID *) (UINTN) PhysicalAddress;
1594 return Status;
1595 }
1596
1597 EFI_STATUS
1598 EFIAPI
1599 IsaIoFreeBuffer (
1600 IN EFI_ISA_IO_PROTOCOL *This,
1601 IN UINTN Pages,
1602 IN VOID *HostAddress
1603 )
1604 /*++
1605
1606 Routine Description:
1607
1608 Frees a common buffer
1609
1610 Arguments:
1611
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.
1615
1616 Returns:
1617
1618 EFI_SUCCESS - The requested memory pages were freed.
1619 EFI_INVALID_PARAMETER - The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1620
1621 --*/
1622 {
1623 EFI_STATUS Status;
1624 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1625
1626 //
1627 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1628 // ISA Bus Master.
1629 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1630 //
1631 if (!FeaturePcdGet (PcdIsaBusSupportDma) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma)) {
1632 return EFI_UNSUPPORTED;
1633 }
1634
1635 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1636 Status = gBS->FreePages (
1637 PhysicalAddress,
1638 Pages
1639 );
1640 if (EFI_ERROR (Status)) {
1641 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
1642 }
1643
1644 return Status;
1645 }
1646