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