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