]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c
Fix K8 report bugs.
[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 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 /**
84 report a error Status code of PCI bus driver controller
85
86 @param Code - The error status code.
87
88 @return EFI_SUCCESS - Success to report status code.
89 **/
90 EFI_STATUS
91 ReportErrorStatusCode (
92 EFI_STATUS_CODE_VALUE Code
93 )
94
95 {
96 return REPORT_STATUS_CODE (
97 EFI_ERROR_CODE | EFI_ERROR_MINOR,
98 Code
99 );
100 }
101
102 //
103 // Driver Support Functions
104 //
105 /**
106
107 Initializes an ISA I/O Instance
108
109 @param IsaIoDevice - The iso device to be initialized.
110 @param IsaDeviceResourceList - The resource list.
111
112 @retval EFI_SUCCESS - Initial success.
113
114 **/
115 EFI_STATUS
116 InitializeIsaIoInstance (
117 IN ISA_IO_DEVICE *IsaIoDevice,
118 IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList
119 )
120 {
121 //
122 // Initializes an ISA I/O Instance
123 //
124 CopyMem (
125 &IsaIoDevice->IsaIo,
126 &IsaIoInterface,
127 sizeof (EFI_ISA_IO_PROTOCOL)
128 );
129
130 IsaIoDevice->IsaIo.ResourceList = IsaDeviceResourceList;
131
132 return EFI_SUCCESS;
133 }
134
135 /**
136 Performs an ISA I/O Read Cycle
137
138 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
139 @param Width - Signifies the width of the I/O operation.
140 @param Offset - The offset in ISA I/O space to start the I/O operation.
141 @param Count - The number of I/O operations to perform.
142 @param Buffer - The destination buffer to store the results
143
144 @retval EFI_SUCCESS - The data was read from the device sucessfully.
145 @retval EFI_UNSUPPORTED - The Offset is not valid for this device.
146 @retval EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
147 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
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 EFI_STATUS Status;
162 ISA_IO_DEVICE *IsaIoDevice;
163
164 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
165
166 //
167 // Verify Isa IO Access
168 //
169 Status = IsaIoVerifyAccess (
170 IsaIoDevice,
171 IsaAccessTypeIo,
172 Width,
173 Count,
174 &Offset
175 );
176 if (EFI_ERROR (Status)) {
177 return Status;
178 }
179 //
180 // Call PciIo->Io.Read
181 //
182 Status = IsaIoDevice->PciIo->Io.Read (
183 IsaIoDevice->PciIo,
184 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
185 EFI_PCI_IO_PASS_THROUGH_BAR,
186 Offset,
187 Count,
188 Buffer
189 );
190
191 if (EFI_ERROR (Status)) {
192 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
193 }
194
195 return Status;
196 }
197
198 /**
199 Performs an ISA I/O Write Cycle
200
201 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
202 @param Width - Signifies the width of the I/O operation.
203 @param Offset - The offset in ISA I/O space to start the I/O operation.
204 @param Count - The number of I/O operations to perform.
205 @param Buffer - The source buffer to write data from
206
207 @retval EFI_SUCCESS - The data was writen to the device sucessfully.
208 @retval EFI_UNSUPPORTED - The Offset is not valid for this device.
209 @retval EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
210 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
211
212 **/
213 EFI_STATUS
214 EFIAPI
215 IsaIoIoWrite (
216 IN EFI_ISA_IO_PROTOCOL *This,
217 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
218 IN UINT32 Offset,
219 IN UINTN Count,
220 IN OUT VOID *Buffer
221 )
222 {
223 EFI_STATUS Status;
224 ISA_IO_DEVICE *IsaIoDevice;
225
226 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
227
228 //
229 // Verify Isa IO Access
230 //
231 Status = IsaIoVerifyAccess (
232 IsaIoDevice,
233 IsaAccessTypeIo,
234 Width,
235 Count,
236 &Offset
237 );
238 if (EFI_ERROR (Status)) {
239 return Status;
240 }
241 //
242 // Call PciIo->Io.Write
243 //
244 Status = IsaIoDevice->PciIo->Io.Write (
245 IsaIoDevice->PciIo,
246 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
247 EFI_PCI_IO_PASS_THROUGH_BAR,
248 Offset,
249 Count,
250 Buffer
251 );
252
253 if (EFI_ERROR (Status)) {
254 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
255 }
256
257 return Status;
258 }
259
260 /**
261 Writes an 8 bit I/O Port
262
263 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
264 @param Offset - The offset in ISA IO space to start the IO operation.
265 @param Value - The data to write port.
266
267 @retval EFI_SUCCESS - Success.
268 @retval EFI_INVALID_PARAMETER - Parameter is invalid.
269 @retval EFI_UNSUPPORTED - The address range specified by Offset is not valid.
270 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
271
272 **/
273 EFI_STATUS
274 WritePort (
275 IN EFI_ISA_IO_PROTOCOL *This,
276 IN UINT32 Offset,
277 IN UINT8 Value
278 )
279
280 {
281 EFI_STATUS Status;
282 ISA_IO_DEVICE *IsaIoDevice;
283
284 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
285
286 //
287 // Call PciIo->Io.Write
288 //
289 Status = IsaIoDevice->PciIo->Io.Write (
290 IsaIoDevice->PciIo,
291 EfiPciIoWidthUint8,
292 EFI_PCI_IO_PASS_THROUGH_BAR,
293 Offset,
294 1,
295 &Value
296 );
297 if (EFI_ERROR (Status)) {
298 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
299 return Status;
300 }
301
302 gBS->Stall (50);
303
304 return EFI_SUCCESS;
305 }
306
307 /**
308 Writes I/O operation base address and count number to a 8 bit I/O Port.
309
310 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
311 @param AddrOffset - The address' offset.
312 @param PageOffset - The page's offest.
313 @param CountOffset - The count's offset.
314 @param BaseAddress - The base address.
315 @param Count - The number of I/O operations to perform.
316
317 @retval EFI_SUCCESS - Success.
318 @retval EFI_INVALID_PARAMETER - Parameter is invalid.
319 @retval EFI_UNSUPPORTED - The address range specified by these Offsets and Count is not valid.
320 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
321
322 **/
323 EFI_STATUS
324 WriteDmaPort (
325 IN EFI_ISA_IO_PROTOCOL *This,
326 IN UINT32 AddrOffset,
327 IN UINT32 PageOffset,
328 IN UINT32 CountOffset,
329 IN UINT32 BaseAddress,
330 IN UINT16 Count
331 )
332
333 {
334 EFI_STATUS Status;
335
336 Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff));
337 if (EFI_ERROR (Status)) {
338 return Status;
339 }
340
341 Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff));
342 if (EFI_ERROR (Status)) {
343 return Status;
344 }
345
346 Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff));
347 if (EFI_ERROR (Status)) {
348 return Status;
349 }
350
351 Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff));
352 if (EFI_ERROR (Status)) {
353 return Status;
354 }
355
356 Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff));
357 if (EFI_ERROR (Status)) {
358 return Status;
359 }
360
361 return EFI_SUCCESS;
362 }
363
364 /**
365 Unmaps a memory region for DMA
366
367 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
368 @param Mapping - The mapping value returned from EFI_ISA_IO.Map().
369
370 @retval EFI_SUCCESS - The range was unmapped.
371 @retval EFI_DEVICE_ERROR - The data was not committed to the target system memory.
372
373 **/
374 EFI_STATUS
375 EFIAPI
376 IsaIoUnmap (
377 IN EFI_ISA_IO_PROTOCOL *This,
378 IN VOID *Mapping
379 )
380 {
381 ISA_MAP_INFO *IsaMapInfo;
382
383 //
384 // Unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
385 //
386 if (!FeaturePcdGet (PcdIsaBusSupportDma)) {
387 return EFI_UNSUPPORTED;
388 }
389
390 //
391 // See if the Map() operation associated with this Unmap() required a mapping
392 // buffer.If a mapping buffer was not required, then this function simply
393 // returns EFI_SUCCESS.
394 //
395 if (Mapping != NULL) {
396 //
397 // Get the MAP_INFO structure from Mapping
398 //
399 IsaMapInfo = (ISA_MAP_INFO *) Mapping;
400
401 //
402 // If this is a write operation from the Agent's point of view,
403 // then copy the contents of the mapped buffer into the real buffer
404 // so the processor can read the contents of the real buffer.
405 //
406 if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) {
407 CopyMem (
408 (VOID *) (UINTN) IsaMapInfo->HostAddress,
409 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
410 IsaMapInfo->NumberOfBytes
411 );
412 }
413 //
414 // Free the mapped buffer and the MAP_INFO structure.
415 //
416 gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages);
417 gBS->FreePool (IsaMapInfo);
418 }
419
420 return EFI_SUCCESS;
421 }
422
423 /**
424 Flushes a DMA buffer
425
426 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
427
428 @retval EFI_SUCCESS - The buffers were flushed.
429 @retval EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
430
431 **/
432 EFI_STATUS
433 EFIAPI
434 IsaIoFlush (
435 IN EFI_ISA_IO_PROTOCOL *This
436 )
437
438 {
439 EFI_STATUS Status;
440 ISA_IO_DEVICE *IsaIoDevice;
441
442 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
443
444 //
445 // Call PciIo->Flush
446 //
447 Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo);
448
449 if (EFI_ERROR (Status)) {
450 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
451 }
452
453 return Status;
454 }
455
456 /**
457 Verifies access to an ISA device
458
459 @param IsaIoDevice - The ISA device to be verified.
460 @param Type - The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo.
461 @param Width - Signifies the width of the memory operation.
462 @param Count - The number of memory operations to perform.
463 @param Offset - The offset in ISA memory space to start the memory operation.
464
465 @retval EFI_SUCCESS - Verify success.
466 @retval EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
467 @retval EFI_UNSUPPORTED - The device ont support the access type.
468
469 **/
470 EFI_STATUS
471 IsaIoVerifyAccess (
472 IN ISA_IO_DEVICE *IsaIoDevice,
473 IN ISA_ACCESS_TYPE Type,
474 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
475 IN UINTN Count,
476 IN OUT UINT32 *Offset
477 )
478
479 {
480 EFI_ISA_ACPI_RESOURCE *Item;
481 EFI_STATUS Status;
482
483 if (Width < EfiIsaIoWidthUint8 ||
484 Width >= EfiIsaIoWidthMaximum ||
485 Width == EfiIsaIoWidthReserved ||
486 Width == EfiIsaIoWidthFifoReserved ||
487 Width == EfiIsaIoWidthFillReserved
488 ) {
489 return EFI_INVALID_PARAMETER;
490 }
491
492 //
493 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
494 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
495 //
496 if (Width >= EfiIsaIoWidthFifoUint8 && Width <= EfiIsaIoWidthFifoReserved) {
497 Count = 1;
498 }
499
500 Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03);
501
502 Status = EFI_UNSUPPORTED;
503 Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem;
504 while (Item->Type != EfiIsaAcpiResourceEndOfList) {
505 if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) ||
506 (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)
507 ) {
508 if (*Offset >= Item->StartRange && (*Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) {
509 return EFI_SUCCESS;
510 }
511
512 if (*Offset >= Item->StartRange && *Offset <= Item->EndRange) {
513 Status = EFI_INVALID_PARAMETER;
514 }
515 }
516
517 Item++;
518 }
519
520 return Status;
521 }
522
523 /**
524
525 Performs an ISA Memory Read Cycle
526
527 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
528 @param Width - Signifies the width of the memory operation.
529 @param Offset - The offset in ISA memory space to start the memory operation.
530 @param Count - The number of memory operations to perform.
531 @param Buffer - The destination buffer to store the results
532
533 @retval EFI_SUCCESS - The data was read from the device successfully.
534 @retval EFI_UNSUPPORTED - The Offset is not valid for this device.
535 @retval EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
536 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
537
538 **/
539 EFI_STATUS
540 EFIAPI
541 IsaIoMemRead (
542 IN EFI_ISA_IO_PROTOCOL *This,
543 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
544 IN UINT32 Offset,
545 IN UINTN Count,
546 IN OUT VOID *Buffer
547 )
548
549 {
550 EFI_STATUS Status;
551 ISA_IO_DEVICE *IsaIoDevice;
552
553 //
554 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
555 // ISA Bus Master.
556 //
557 // So we just return EFI_UNSUPPORTED for these functions.
558 //
559 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory)) {
560 return EFI_UNSUPPORTED;
561 }
562
563 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
564
565 //
566 // Verify the Isa Io Access
567 //
568 Status = IsaIoVerifyAccess (
569 IsaIoDevice,
570 IsaAccessTypeMem,
571 Width,
572 Count,
573 &Offset
574 );
575 if (EFI_ERROR (Status)) {
576 return Status;
577 }
578 //
579 // Call PciIo->Mem.Read
580 //
581 Status = IsaIoDevice->PciIo->Mem.Read (
582 IsaIoDevice->PciIo,
583 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
584 EFI_PCI_IO_PASS_THROUGH_BAR,
585 Offset,
586 Count,
587 Buffer
588 );
589
590 if (EFI_ERROR (Status)) {
591 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
592 }
593
594 return Status;
595 }
596
597 /**
598 Performs an ISA Memory Write Cycle
599
600 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
601 @param Width - Signifies the width of the memory operation.
602 @param Offset - The offset in ISA memory space to start the memory operation.
603 @param Count - The number of memory operations to perform.
604 @param Buffer - The source buffer to write data from
605
606 @retval EFI_SUCCESS - The data was written to the device sucessfully.
607 @retval EFI_UNSUPPORTED - The Offset is not valid for this device.
608 @retval EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
609 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
610
611 **/
612 EFI_STATUS
613 EFIAPI
614 IsaIoMemWrite (
615 IN EFI_ISA_IO_PROTOCOL *This,
616 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
617 IN UINT32 Offset,
618 IN UINTN Count,
619 IN OUT VOID *Buffer
620 )
621 {
622 EFI_STATUS Status;
623 ISA_IO_DEVICE *IsaIoDevice;
624
625 //
626 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
627 // ISA Bus Master.
628 //
629 // So we just return EFI_UNSUPPORTED for these functions.
630 //
631 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory)) {
632 return EFI_UNSUPPORTED;
633 }
634
635 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
636
637 //
638 // Verify Isa IO Access
639 //
640 Status = IsaIoVerifyAccess (
641 IsaIoDevice,
642 IsaAccessTypeMem,
643 Width,
644 Count,
645 &Offset
646 );
647 if (EFI_ERROR (Status)) {
648 return Status;
649 }
650 //
651 // Call PciIo->Mem.Write
652 //
653 Status = IsaIoDevice->PciIo->Mem.Write (
654 IsaIoDevice->PciIo,
655 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
656 EFI_PCI_IO_PASS_THROUGH_BAR,
657 Offset,
658 Count,
659 Buffer
660 );
661
662 if (EFI_ERROR (Status)) {
663 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
664 }
665
666 return Status;
667 }
668
669 /**
670 Performs an ISA I/O Copy Memory
671
672 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
673 @param Width - Signifies the width of the memory copy operation.
674 @param DestOffset - The offset of the destination
675 @param SrcOffset - The offset of the source
676 @param Count - The number of memory copy operations to perform
677
678 @retval EFI_SUCCESS - The data was copied sucessfully.
679 @retval EFI_UNSUPPORTED - The DestOffset or SrcOffset is not valid for this device.
680 @retval EFI_INVALID_PARAMETER - Width or Count, or both, were invalid.
681 @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
682
683 **/
684 EFI_STATUS
685 EFIAPI
686 IsaIoCopyMem (
687 IN EFI_ISA_IO_PROTOCOL *This,
688 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
689 IN UINT32 DestOffset,
690 IN UINT32 SrcOffset,
691 IN UINTN Count
692 )
693
694 {
695 EFI_STATUS Status;
696 ISA_IO_DEVICE *IsaIoDevice;
697
698 //
699 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
700 // ISA Bus Master.
701 //
702 // So we just return EFI_UNSUPPORTED for these functions.
703 //
704 if (!FeaturePcdGet (PcdIsaBusSupportIsaMemory)) {
705 return EFI_UNSUPPORTED;
706 }
707
708 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
709
710 //
711 // Verify Isa IO Access for destination and source
712 //
713 Status = IsaIoVerifyAccess (
714 IsaIoDevice,
715 IsaAccessTypeMem,
716 Width,
717 Count,
718 &DestOffset
719 );
720 if (EFI_ERROR (Status)) {
721 return Status;
722 }
723
724 Status = IsaIoVerifyAccess (
725 IsaIoDevice,
726 IsaAccessTypeMem,
727 Width,
728 Count,
729 &SrcOffset
730 );
731 if (EFI_ERROR (Status)) {
732 return Status;
733 }
734 //
735 // Call PciIo->CopyMem
736 //
737 Status = IsaIoDevice->PciIo->CopyMem (
738 IsaIoDevice->PciIo,
739 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
740 EFI_PCI_IO_PASS_THROUGH_BAR,
741 DestOffset,
742 EFI_PCI_IO_PASS_THROUGH_BAR,
743 SrcOffset,
744 Count
745 );
746
747 if (EFI_ERROR (Status)) {
748 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
749 }
750
751 return Status;
752 }
753
754 /**
755 Maps a memory region for DMA, note this implementation
756 only supports slave read/write operation to save code size.
757
758 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
759 @param Operation - Indicates the type of DMA (slave or bus master), and if
760 the DMA operation is going to read or write to system memory.
761 @param ChannelNumber - The slave channel number to use for this DMA operation.
762 If Operation and ChannelAttributes shows that this device
763 performs bus mastering DMA, then this field is ignored.
764 The legal range for this field is 0..7.
765 @param ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
766 @param HostAddress - The system memory address to map to the device.
767 @param NumberOfBytes - On input the number of bytes to map. On output the number
768 of bytes that were mapped.
769 @param DeviceAddress - The resulting map address for the bus master device to use
770 to access the hosts HostAddress.
771 @param Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
772
773 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
774 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
775 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
776 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.
777 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
778
779 **/
780 EFI_STATUS
781 IsaIoMap_OnlySupportSlaveReadWrite (
782 IN EFI_ISA_IO_PROTOCOL *This,
783 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,
784 IN UINT8 ChannelNumber OPTIONAL,
785 IN UINT32 ChannelAttributes,
786 IN VOID *HostAddress,
787 IN OUT UINTN *NumberOfBytes,
788 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
789 OUT VOID **Mapping
790 )
791
792 {
793 EFI_STATUS Status;
794 EFI_PHYSICAL_ADDRESS PhysicalAddress;
795 ISA_MAP_INFO *IsaMapInfo;
796 UINT8 DmaMode;
797 UINTN MaxNumberOfBytes;
798 UINT32 BaseAddress;
799 UINT16 Count;
800
801 UINT8 DmaMask;
802 UINT8 DmaClear;
803 UINT8 DmaChannelMode;
804
805 if ((NULL == This) ||
806 (NULL == HostAddress) ||
807 (NULL == NumberOfBytes) ||
808 (NULL == DeviceAddress) ||
809 (NULL == Mapping)
810 ) {
811 return EFI_INVALID_PARAMETER;
812 }
813
814
815 //
816 // Initialize the return values to their defaults
817 //
818 *Mapping = NULL;
819
820 //
821 // Make sure the Operation parameter is valid.
822 // Light IsaIo only supports two operations.
823 //
824 if (!(Operation == EfiIsaIoOperationSlaveRead ||
825 Operation == EfiIsaIoOperationSlaveWrite)) {
826 return EFI_INVALID_PARAMETER;
827 }
828
829 if (ChannelNumber >= 4) {
830 //
831 // The Light IsaIo doesn't support channelNumber larger than 4.
832 //
833 return EFI_INVALID_PARAMETER;
834 }
835
836 //
837 // Map the HostAddress to a DeviceAddress.
838 //
839 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
840 if ((PhysicalAddress +*NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) {
841 //
842 // Common Buffer operations can not be remapped. If the common buffer
843 // is above 16MB, then it is not possible to generate a mapping, so return
844 // an error.
845 //
846 if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {
847 return EFI_UNSUPPORTED;
848 }
849 //
850 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
851 // is called later.
852 //
853 IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));
854 if (IsaMapInfo == NULL) {
855 *NumberOfBytes = 0;
856 return EFI_OUT_OF_RESOURCES;
857 }
858 //
859 // Return a pointer to the MAP_INFO structure in Mapping
860 //
861 *Mapping = IsaMapInfo;
862
863 //
864 // Initialize the MAP_INFO structure
865 //
866 IsaMapInfo->Operation = Operation;
867 IsaMapInfo->NumberOfBytes = *NumberOfBytes;
868 IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);
869 IsaMapInfo->HostAddress = PhysicalAddress;
870 IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1;
871
872 //
873 // Allocate a buffer below 16MB to map the transfer to.
874 //
875 Status = gBS->AllocatePages (
876 AllocateMaxAddress,
877 EfiBootServicesData,
878 IsaMapInfo->NumberOfPages,
879 &IsaMapInfo->MappedHostAddress
880 );
881 if (EFI_ERROR (Status)) {
882 gBS->FreePool (IsaMapInfo);
883 *NumberOfBytes = 0;
884 *Mapping = NULL;
885 return Status;
886 }
887 //
888 // If this is a read operation from the DMA agents's point of view,
889 // then copy the contents of the real buffer into the mapped buffer
890 // so the DMA agent can read the contents of the real buffer.
891 //
892 if (Operation == EfiIsaIoOperationSlaveRead) {
893 CopyMem (
894 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
895 (VOID *) (UINTN) IsaMapInfo->HostAddress,
896 IsaMapInfo->NumberOfBytes
897 );
898 }
899 //
900 // The DeviceAddress is the address of the maped buffer below 16 MB
901 //
902 *DeviceAddress = IsaMapInfo->MappedHostAddress;
903 } else {
904 //
905 // The transfer is below 16 MB, so the DeviceAddress is simply the
906 // HostAddress
907 //
908 *DeviceAddress = PhysicalAddress;
909 }
910
911 //
912 // Figure out what to program into the DMA Channel Mode Register
913 //
914 DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));
915 if (Operation == EfiIsaIoOperationSlaveRead) {
916 DmaMode |= V_8237_DMA_CHMODE_MEM2IO;
917 } else {
918 DmaMode |= V_8237_DMA_CHMODE_IO2MEM;
919 }
920 //
921 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
922 //
923 DmaMode |= V_8237_DMA_CHMODE_SINGLE;
924
925 //
926 // A Slave DMA transfer can not cross a 64K boundary.
927 // Compute *NumberOfBytes based on this restriction.
928 //
929 MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);
930 if (*NumberOfBytes > MaxNumberOfBytes) {
931 *NumberOfBytes = MaxNumberOfBytes;
932 }
933 //
934 // Compute the values to program into the BaseAddress and Count registers
935 // of the Slave DMA controller
936 //
937 BaseAddress = (UINT32) (*DeviceAddress);
938 Count = (UINT16) (*NumberOfBytes - 1);
939 //
940 // Program the DMA Write Single Mask Register for ChannelNumber
941 // Clear the DMA Byte Pointer Register
942 //
943 DmaMask = R_8237_DMA_WRSMSK_CH0_3;
944 DmaClear = R_8237_DMA_CBPR_CH0_3;
945 DmaChannelMode = R_8237_DMA_CHMODE_CH0_3;
946
947 Status = WritePort (
948 This,
949 DmaMask,
950 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
951 );
952 if (EFI_ERROR (Status)) {
953 return Status;
954 }
955
956 Status = WritePort (
957 This,
958 DmaClear,
959 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
960 );
961 if (EFI_ERROR (Status)) {
962 return Status;
963 }
964
965 Status = WritePort (This, DmaChannelMode, DmaMode);
966 if (EFI_ERROR (Status)) {
967 return Status;
968 }
969
970 Status = WriteDmaPort (
971 This,
972 DmaRegisters[ChannelNumber].Address,
973 DmaRegisters[ChannelNumber].Page,
974 DmaRegisters[ChannelNumber].Count,
975 BaseAddress,
976 Count
977 );
978 if (EFI_ERROR (Status)) {
979 return Status;
980 }
981
982 Status = WritePort (
983 This,
984 DmaMask,
985 (UINT8) (ChannelNumber & 0x03)
986 );
987 if (EFI_ERROR (Status)) {
988 return Status;
989 }
990
991 return EFI_SUCCESS;
992 }
993
994 /**
995 Maps a memory region for DMA. This implementation implement the
996 the full mapping support.
997
998 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
999 @param Operation - Indicates the type of DMA (slave or bus master), and if
1000 the DMA operation is going to read or write to system memory.
1001 @param ChannelNumber - The slave channel number to use for this DMA operation.
1002 If Operation and ChannelAttributes shows that this device
1003 performs bus mastering DMA, then this field is ignored.
1004 The legal range for this field is 0..7.
1005 @param ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
1006 @param HostAddress - The system memory address to map to the device.
1007 @param NumberOfBytes - On input the number of bytes to map. On output the number
1008 of bytes that were mapped.
1009 @param DeviceAddress - The resulting map address for the bus master device to use
1010 - to access the hosts HostAddress.
1011 @param Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
1012
1013 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1014 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1015 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1016 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1017 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1018
1019 **/
1020 EFI_STATUS
1021 IsaIoMap_FullSupport (
1022 IN EFI_ISA_IO_PROTOCOL *This,
1023 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,
1024 IN UINT8 ChannelNumber OPTIONAL,
1025 IN UINT32 ChannelAttributes,
1026 IN VOID *HostAddress,
1027 IN OUT UINTN *NumberOfBytes,
1028 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
1029 OUT VOID **Mapping
1030 )
1031
1032 {
1033 EFI_STATUS Status;
1034 BOOLEAN Master;
1035 BOOLEAN Read;
1036 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1037 ISA_MAP_INFO *IsaMapInfo;
1038 UINT8 DmaMode;
1039 UINTN MaxNumberOfBytes;
1040 UINT32 BaseAddress;
1041 UINT16 Count;
1042
1043 UINT8 DmaMask;
1044 UINT8 DmaClear;
1045 UINT8 DmaChannelMode;
1046
1047 if ((NULL == This) ||
1048 (NULL == HostAddress) ||
1049 (NULL == NumberOfBytes) ||
1050 (NULL == DeviceAddress) ||
1051 (NULL == Mapping)
1052 ) {
1053 return EFI_INVALID_PARAMETER;
1054 }
1055
1056
1057 //
1058 // Initialize the return values to their defaults
1059 //
1060 *Mapping = NULL;
1061
1062 //
1063 // Make sure the Operation parameter is valid
1064 //
1065 if (Operation < 0 || Operation >= EfiIsaIoOperationMaximum) {
1066 return EFI_INVALID_PARAMETER;
1067 }
1068
1069 if (ChannelNumber >= 8) {
1070 return EFI_INVALID_PARAMETER;
1071 }
1072
1073 //
1074 // See if this is a Slave DMA Operation
1075 //
1076 Master = TRUE;
1077 Read = FALSE;
1078 if (Operation == EfiIsaIoOperationSlaveRead) {
1079 Operation = EfiIsaIoOperationBusMasterRead;
1080 Master = FALSE;
1081 Read = TRUE;
1082 }
1083
1084 if (Operation == EfiIsaIoOperationSlaveWrite) {
1085 Operation = EfiIsaIoOperationBusMasterWrite;
1086 Master = FALSE;
1087 Read = FALSE;
1088 }
1089
1090 if (!Master) {
1091 //
1092 // Make sure that ChannelNumber is a valid channel number
1093 // Channel 4 is used to cascade, so it is illegal.
1094 //
1095 if (ChannelNumber == 4 || ChannelNumber > 7) {
1096 return EFI_INVALID_PARAMETER;
1097 }
1098 //
1099 // This implementation only support COMPATIBLE DMA Transfers
1100 //
1101 if (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE)) {
1102 return EFI_INVALID_PARAMETER;
1103 }
1104
1105 if (ChannelAttributes &
1106 (
1107 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A |
1108 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B |
1109 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C
1110 )
1111 ) {
1112 return EFI_INVALID_PARAMETER;
1113 }
1114
1115 if (ChannelNumber < 4) {
1116 //
1117 // If this is Channel 0..3, then the width must be 8 bit
1118 //
1119 if (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) ||
1120 (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16)
1121 ) {
1122 return EFI_INVALID_PARAMETER;
1123 }
1124 } else {
1125 //
1126 // If this is Channel 4..7, then the width must be 16 bit
1127 //
1128 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) ||
1129 (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16))
1130 ) {
1131 return EFI_INVALID_PARAMETER;
1132 }
1133 }
1134 //
1135 // Either Demand Mode or Single Mode must be selected, but not both
1136 //
1137 if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) {
1138 if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) {
1139 return EFI_INVALID_PARAMETER;
1140 }
1141 } else {
1142 if (!(ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE)) {
1143 return EFI_INVALID_PARAMETER;
1144 }
1145 }
1146 }
1147 //
1148 // Map the HostAddress to a DeviceAddress.
1149 //
1150 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1151 if ((PhysicalAddress +*NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) {
1152 //
1153 // Common Buffer operations can not be remapped. If the common buffer
1154 // is above 16MB, then it is not possible to generate a mapping, so return
1155 // an error.
1156 //
1157 if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {
1158 return EFI_UNSUPPORTED;
1159 }
1160 //
1161 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1162 // is called later.
1163 //
1164 IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));
1165 if (IsaMapInfo == NULL) {
1166 *NumberOfBytes = 0;
1167 return EFI_OUT_OF_RESOURCES;
1168 }
1169 //
1170 // Return a pointer to the MAP_INFO structure in Mapping
1171 //
1172 *Mapping = IsaMapInfo;
1173
1174 //
1175 // Initialize the MAP_INFO structure
1176 //
1177 IsaMapInfo->Operation = Operation;
1178 IsaMapInfo->NumberOfBytes = *NumberOfBytes;
1179 IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);
1180 IsaMapInfo->HostAddress = PhysicalAddress;
1181 IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1;
1182
1183 //
1184 // Allocate a buffer below 16MB to map the transfer to.
1185 //
1186 Status = gBS->AllocatePages (
1187 AllocateMaxAddress,
1188 EfiBootServicesData,
1189 IsaMapInfo->NumberOfPages,
1190 &IsaMapInfo->MappedHostAddress
1191 );
1192 if (EFI_ERROR (Status)) {
1193 gBS->FreePool (IsaMapInfo);
1194 *NumberOfBytes = 0;
1195 *Mapping = NULL;
1196 return Status;
1197 }
1198 //
1199 // If this is a read operation from the DMA agents's point of view,
1200 // then copy the contents of the real buffer into the mapped buffer
1201 // so the DMA agent can read the contents of the real buffer.
1202 //
1203 if (Operation == EfiIsaIoOperationBusMasterRead) {
1204 CopyMem (
1205 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
1206 (VOID *) (UINTN) IsaMapInfo->HostAddress,
1207 IsaMapInfo->NumberOfBytes
1208 );
1209 }
1210 //
1211 // The DeviceAddress is the address of the maped buffer below 16 MB
1212 //
1213 *DeviceAddress = IsaMapInfo->MappedHostAddress;
1214 } else {
1215 //
1216 // The transfer is below 16 MB, so the DeviceAddress is simply the
1217 // HostAddress
1218 //
1219 *DeviceAddress = PhysicalAddress;
1220 }
1221 //
1222 // If this is a Bus Master operation then return
1223 //
1224 if (Master) {
1225 return EFI_SUCCESS;
1226 }
1227 //
1228 // Figure out what to program into the DMA Channel Mode Register
1229 //
1230 DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));
1231 if (Read) {
1232 DmaMode |= V_8237_DMA_CHMODE_MEM2IO;
1233 } else {
1234 DmaMode |= V_8237_DMA_CHMODE_IO2MEM;
1235 }
1236
1237 if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) {
1238 DmaMode |= B_8237_DMA_CHMODE_AE;
1239 }
1240
1241 if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) {
1242 DmaMode |= V_8237_DMA_CHMODE_DEMAND;
1243 }
1244
1245 if (ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) {
1246 DmaMode |= V_8237_DMA_CHMODE_SINGLE;
1247 }
1248 //
1249 // A Slave DMA transfer can not cross a 64K boundary.
1250 // Compute *NumberOfBytes based on this restriction.
1251 //
1252 MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);
1253 if (*NumberOfBytes > MaxNumberOfBytes) {
1254 *NumberOfBytes = MaxNumberOfBytes;
1255 }
1256 //
1257 // Compute the values to program into the BaseAddress and Count registers
1258 // of the Slave DMA controller
1259 //
1260 if (ChannelNumber < 4) {
1261 BaseAddress = (UINT32) (*DeviceAddress);
1262 Count = (UINT16) (*NumberOfBytes - 1);
1263 } else {
1264 BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1));
1265 Count = (UINT16) ((*NumberOfBytes - 1) >> 1);
1266 }
1267 //
1268 // Program the DMA Write Single Mask Register for ChannelNumber
1269 // Clear the DMA Byte Pointer Register
1270 //
1271 if (ChannelNumber < 4) {
1272 DmaMask = R_8237_DMA_WRSMSK_CH0_3;
1273 DmaClear = R_8237_DMA_CBPR_CH0_3;
1274 DmaChannelMode = R_8237_DMA_CHMODE_CH0_3;
1275 } else {
1276 DmaMask = R_8237_DMA_WRSMSK_CH4_7;
1277 DmaClear = R_8237_DMA_CBPR_CH4_7;
1278 DmaChannelMode = R_8237_DMA_CHMODE_CH4_7;
1279 }
1280
1281 Status = WritePort (
1282 This,
1283 DmaMask,
1284 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1285 );
1286 if (EFI_ERROR (Status)) {
1287 return Status;
1288 }
1289
1290 Status = WritePort (
1291 This,
1292 DmaClear,
1293 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1294 );
1295 if (EFI_ERROR (Status)) {
1296 return Status;
1297 }
1298
1299 Status = WritePort (This, DmaChannelMode, DmaMode);
1300 if (EFI_ERROR (Status)) {
1301 return Status;
1302 }
1303
1304 Status = WriteDmaPort (
1305 This,
1306 DmaRegisters[ChannelNumber].Address,
1307 DmaRegisters[ChannelNumber].Page,
1308 DmaRegisters[ChannelNumber].Count,
1309 BaseAddress,
1310 Count
1311 );
1312 if (EFI_ERROR (Status)) {
1313 return Status;
1314 }
1315
1316 Status = WritePort (
1317 This,
1318 DmaMask,
1319 (UINT8) (ChannelNumber & 0x03)
1320 );
1321 if (EFI_ERROR (Status)) {
1322 return Status;
1323 }
1324
1325 return EFI_SUCCESS;
1326 }
1327
1328 /**
1329 Maps a memory region for DMA
1330
1331 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1332 @param Operation - Indicates the type of DMA (slave or bus master), and if
1333 the DMA operation is going to read or write to system memory.
1334 @param ChannelNumber - The slave channel number to use for this DMA operation.
1335 If Operation and ChannelAttributes shows that this device
1336 performs bus mastering DMA, then this field is ignored.
1337 The legal range for this field is 0..7.
1338 @param ChannelAttributes - The attributes of the DMA channel to use for this DMA operation
1339 @param HostAddress - The system memory address to map to the device.
1340 @param NumberOfBytes - On input the number of bytes to map. On output the number
1341 of bytes that were mapped.
1342 @param DeviceAddress - The resulting map address for the bus master device to use
1343 - to access the hosts HostAddress.
1344 @param Mapping - A resulting value to pass to EFI_ISA_IO.Unmap().
1345
1346
1347 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
1348 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
1349 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
1350 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.
1351 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1352
1353 **/
1354 EFI_STATUS
1355 EFIAPI
1356 IsaIoMap (
1357 IN EFI_ISA_IO_PROTOCOL *This,
1358 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,
1359 IN UINT8 ChannelNumber OPTIONAL,
1360 IN UINT32 ChannelAttributes,
1361 IN VOID *HostAddress,
1362 IN OUT UINTN *NumberOfBytes,
1363 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
1364 OUT VOID **Mapping
1365 )
1366
1367 {
1368 //
1369 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1370 //
1371 if (!FeaturePcdGet (PcdIsaBusSupportDma)) {
1372 return EFI_UNSUPPORTED;
1373 }
1374 //
1375 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1376 // ISA Bus Master.
1377 //
1378 // So we just return EFI_UNSUPPORTED for these functions.
1379 //
1380 if (FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma)) {
1381 return IsaIoMap_OnlySupportSlaveReadWrite (
1382 This,
1383 Operation,
1384 ChannelNumber,
1385 ChannelAttributes,
1386 HostAddress,
1387 NumberOfBytes,
1388 DeviceAddress,
1389 Mapping
1390 );
1391
1392 } else {
1393 return IsaIoMap_FullSupport (
1394 This,
1395 Operation,
1396 ChannelNumber,
1397 ChannelAttributes,
1398 HostAddress,
1399 NumberOfBytes,
1400 DeviceAddress,
1401 Mapping
1402 );
1403 }
1404 }
1405
1406 /**
1407 Allocates a common buffer for DMA
1408
1409 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1410 @param Type - The type allocation to perform.
1411 @param MemoryType - The type of memory to allocate.
1412 @param Pages - The number of pages to allocate.
1413 @param HostAddress - A pointer to store the base address of the allocated range.
1414 @param Attributes - The requested bit mask of attributes for the allocated range.
1415
1416 @retval EFI_SUCCESS - The requested memory pages were allocated.
1417 @retval EFI_INVALID_PARAMETER - Type is invalid or MemoryType is invalid or HostAddress is NULL
1418 @retval EFI_UNSUPPORTED - Attributes is unsupported or the memory range specified
1419 by HostAddress, Pages, and Type is not available for common buffer use.
1420 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
1421
1422 **/
1423 EFI_STATUS
1424 EFIAPI
1425 IsaIoAllocateBuffer (
1426 IN EFI_ISA_IO_PROTOCOL *This,
1427 IN EFI_ALLOCATE_TYPE Type,
1428 IN EFI_MEMORY_TYPE MemoryType,
1429 IN UINTN Pages,
1430 OUT VOID **HostAddress,
1431 IN UINT64 Attributes
1432 )
1433 {
1434 EFI_STATUS Status;
1435 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1436
1437 //
1438 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1439 // ISA Bus Master.
1440 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1441 //
1442 if (!FeaturePcdGet (PcdIsaBusSupportDma) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma)) {
1443 return EFI_UNSUPPORTED;
1444 }
1445
1446 if (HostAddress == NULL) {
1447 return EFI_INVALID_PARAMETER;
1448 }
1449
1450 if (Type < AllocateAnyPages || Type >= MaxAllocateType) {
1451 return EFI_INVALID_PARAMETER;
1452 }
1453 //
1454 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1455 //
1456 if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
1457 return EFI_INVALID_PARAMETER;
1458 }
1459
1460 if (Attributes &~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) {
1461 return EFI_UNSUPPORTED;
1462 }
1463
1464 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (ISA_MAX_MEMORY_ADDRESS - 1);
1465 if (Type == AllocateAddress) {
1466 if ((UINTN) (*HostAddress) >= ISA_MAX_MEMORY_ADDRESS) {
1467 return EFI_UNSUPPORTED;
1468 } else {
1469 PhysicalAddress = (UINTN) (*HostAddress);
1470 }
1471 }
1472
1473 if (Type == AllocateAnyPages) {
1474 Type = AllocateMaxAddress;
1475 }
1476
1477 Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress);
1478 if (EFI_ERROR (Status)) {
1479 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
1480 return Status;
1481 }
1482
1483 *HostAddress = (VOID *) (UINTN) PhysicalAddress;
1484 return Status;
1485 }
1486
1487 /**
1488
1489 Frees a common buffer
1490
1491 @param This - A pointer to the EFI_ISA_IO_PROTOCOL instance.
1492 @param Pages - The number of pages to free.
1493 @param HostAddress - The base address of the allocated range.
1494
1495
1496 @retval EFI_SUCCESS - The requested memory pages were freed.
1497 @retval EFI_INVALID_PARAMETER - The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1498
1499 **/
1500
1501 EFI_STATUS
1502 EFIAPI
1503 IsaIoFreeBuffer (
1504 IN EFI_ISA_IO_PROTOCOL *This,
1505 IN UINTN Pages,
1506 IN VOID *HostAddress
1507 )
1508 {
1509 EFI_STATUS Status;
1510 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1511
1512 //
1513 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1514 // ISA Bus Master.
1515 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1516 //
1517 if (!FeaturePcdGet (PcdIsaBusSupportDma) || FeaturePcdGet (PcdIsaBusOnlySupportSlaveDma)) {
1518 return EFI_UNSUPPORTED;
1519 }
1520
1521 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1522 Status = gBS->FreePages (
1523 PhysicalAddress,
1524 Pages
1525 );
1526 if (EFI_ERROR (Status)) {
1527 ReportErrorStatusCode (EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR);
1528 }
1529
1530 return Status;
1531 }
1532