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