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