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