]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c
ISA Bus code scrub.
[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
6fcb2d91 4Copyright (c) 2006 - 2009, Intel Corporation.<BR>\r
f8cd287b 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
6fcb2d91 18// Module Variables\r
c3902377 19//\r
6fcb2d91 20EFI_ISA_IO_PROTOCOL mIsaIoInterface = {\r
c3902377 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
6fcb2d91 40EFI_ISA_DMA_REGISTERS mDmaRegisters[8] = {\r
c3902377 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
6fcb2d91 84 report a error Status code\r
bcd70414 85\r
6fcb2d91 86 @param Code The error status code.\r
bcd70414 87 \r
6fcb2d91 88 @return EFI_SUCCESS Success to report status code.\r
bcd70414 89**/\r
c3902377 90EFI_STATUS\r
91ReportErrorStatusCode (\r
92 EFI_STATUS_CODE_VALUE Code\r
93 )\r
c3902377 94{\r
95 return REPORT_STATUS_CODE (\r
6fcb2d91 96 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
97 Code\r
98 );\r
c3902377 99}\r
100\r
bcd70414 101/**\r
bcd70414 102 Initializes an ISA I/O Instance\r
c3902377 103\r
6fcb2d91 104 @param[in] IsaIoDevice The iso device to be initialized.\r
105 @param[in] IsaDeviceResourceList The resource list.\r
bcd70414 106 \r
6fcb2d91 107 @retval None\r
bcd70414 108**/\r
6fcb2d91 109VOID\r
c3902377 110InitializeIsaIoInstance (\r
111 IN ISA_IO_DEVICE *IsaIoDevice,\r
112 IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList\r
113 )\r
c3902377 114{\r
115 //\r
6fcb2d91 116 // Use the ISA IO Protocol structure template to initialize the ISA IO instance\r
c3902377 117 //\r
118 CopyMem (\r
119 &IsaIoDevice->IsaIo,\r
6fcb2d91 120 &mIsaIoInterface,\r
c3902377 121 sizeof (EFI_ISA_IO_PROTOCOL)\r
122 );\r
123\r
124 IsaIoDevice->IsaIo.ResourceList = IsaDeviceResourceList;\r
c3902377 125}\r
126\r
bcd70414 127/**\r
128 Performs an ISA I/O Read Cycle\r
129\r
6fcb2d91 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
bcd70414 135\r
6fcb2d91 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
bcd70414 140**/\r
c3902377 141EFI_STATUS\r
142EFIAPI\r
143IsaIoIoRead (\r
6fcb2d91 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
c3902377 149 )\r
c3902377 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
6fcb2d91 164 Offset\r
c3902377 165 );\r
166 if (EFI_ERROR (Status)) {\r
167 return Status;\r
168 }\r
6fcb2d91 169\r
c3902377 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
bcd70414 186/**\r
187 Performs an ISA I/O Write Cycle\r
188\r
6fcb2d91 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
bcd70414 194\r
6fcb2d91 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
bcd70414 199**/\r
c3902377 200EFI_STATUS\r
201EFIAPI\r
202IsaIoIoWrite (\r
6fcb2d91 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
c3902377 208 )\r
c3902377 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
6fcb2d91 223 Offset\r
c3902377 224 );\r
225 if (EFI_ERROR (Status)) {\r
226 return Status;\r
227 }\r
6fcb2d91 228\r
c3902377 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
bcd70414 245/**\r
6fcb2d91 246 Writes an 8-bit I/O Port\r
bcd70414 247\r
6fcb2d91 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
bcd70414 251\r
6fcb2d91 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
bcd70414 256**/\r
c3902377 257EFI_STATUS\r
258WritePort (\r
6fcb2d91 259 IN EFI_ISA_IO_PROTOCOL *This,\r
260 IN UINT32 Offset,\r
261 IN UINT8 Value\r
c3902377 262 )\r
c3902377 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
c3902377 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
bcd70414 287/**\r
288 Writes I/O operation base address and count number to a 8 bit I/O Port.\r
289\r
6fcb2d91 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
bcd70414 296 \r
6fcb2d91 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
bcd70414 301**/\r
c3902377 302EFI_STATUS\r
303WriteDmaPort (\r
6fcb2d91 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
c3902377 310 )\r
c3902377 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
6fcb2d91 335 return Status;\r
c3902377 336}\r
337\r
bcd70414 338/**\r
339 Unmaps a memory region for DMA\r
340\r
6fcb2d91 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
bcd70414 343\r
6fcb2d91 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
bcd70414 346**/\r
c3902377 347EFI_STATUS\r
348EFIAPI\r
349IsaIoUnmap (\r
6fcb2d91 350 IN EFI_ISA_IO_PROTOCOL *This,\r
351 IN VOID *Mapping\r
c3902377 352 )\r
c3902377 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
f423cbf1 390 FreePool (IsaMapInfo);\r
c3902377 391 }\r
392\r
393 return EFI_SUCCESS;\r
394}\r
395\r
bcd70414 396/**\r
6fcb2d91 397 Flushes any posted write data to the system memory.\r
bcd70414 398\r
6fcb2d91 399 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.\r
bcd70414 400\r
6fcb2d91 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
bcd70414 403**/\r
c3902377 404EFI_STATUS\r
405EFIAPI\r
406IsaIoFlush (\r
6fcb2d91 407 IN EFI_ISA_IO_PROTOCOL *This\r
c3902377 408 )\r
c3902377 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
c3902377 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
bcd70414 424/**\r
425 Verifies access to an ISA device\r
426\r
6fcb2d91 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
bcd70414 432 \r
6fcb2d91 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
bcd70414 436**/\r
c3902377 437EFI_STATUS\r
438IsaIoVerifyAccess (\r
6fcb2d91 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
c3902377 444 )\r
c3902377 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
6fcb2d91 462 if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) {\r
c3902377 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
6fcb2d91 472 (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) {\r
473 if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) {\r
c3902377 474 return EFI_SUCCESS;\r
475 }\r
476\r
6fcb2d91 477 if (Offset >= Item->StartRange && Offset <= Item->EndRange) {\r
c3902377 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
bcd70414 488/**\r
bcd70414 489 Performs an ISA Memory Read Cycle\r
490\r
6fcb2d91 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
bcd70414 496 \r
6fcb2d91 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
bcd70414 501**/\r
c3902377 502EFI_STATUS\r
503EFIAPI\r
504IsaIoMemRead (\r
6fcb2d91 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
c3902377 510 )\r
c3902377 511{\r
512 EFI_STATUS Status;\r
513 ISA_IO_DEVICE *IsaIoDevice;\r
514\r
515 //\r
6fcb2d91 516 // Set Feature Flag PcdIsaBusSupportIsaMemory to FALSE to disable support for\r
517 // ISA bus memory read/write operations.\r
c3902377 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
6fcb2d91 533 Offset\r
c3902377 534 );\r
535 if (EFI_ERROR (Status)) {\r
536 return Status;\r
537 }\r
6fcb2d91 538\r
c3902377 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
bcd70414 555/**\r
556 Performs an ISA Memory Write Cycle\r
557\r
6fcb2d91 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
bcd70414 563\r
6fcb2d91 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
bcd70414 568**/\r
c3902377 569EFI_STATUS\r
570EFIAPI\r
571IsaIoMemWrite (\r
6fcb2d91 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
c3902377 577 )\r
c3902377 578{\r
579 EFI_STATUS Status;\r
580 ISA_IO_DEVICE *IsaIoDevice;\r
581\r
582 //\r
6fcb2d91 583 // Set Feature Flag PcdIsaBusSupportIsaMemory to FALSE to disable support for\r
584 // ISA bus memory read/write operations.\r
c3902377 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
6fcb2d91 600 Offset\r
c3902377 601 );\r
602 if (EFI_ERROR (Status)) {\r
603 return Status;\r
604 }\r
6fcb2d91 605\r
c3902377 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
bcd70414 622/**\r
6fcb2d91 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
bcd70414 635**/\r
c3902377 636EFI_STATUS\r
637EFIAPI\r
638IsaIoCopyMem (\r
6fcb2d91 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
c3902377 644 )\r
c3902377 645{\r
646 EFI_STATUS Status;\r
647 ISA_IO_DEVICE *IsaIoDevice;\r
648\r
649 //\r
6fcb2d91 650 // Set Feature Flag PcdIsaBusSupportIsaMemory to FALSE to disable support for\r
651 // ISA bus memory read/write operations.\r
c3902377 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
6fcb2d91 667 DestOffset\r
c3902377 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
6fcb2d91 678 SrcOffset\r
c3902377 679 );\r
680 if (EFI_ERROR (Status)) {\r
681 return Status;\r
682 }\r
6fcb2d91 683\r
c3902377 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
bcd70414 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
6fcb2d91 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
bcd70414 725**/\r
c3902377 726EFI_STATUS\r
6fcb2d91 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
c3902377 736 )\r
c3902377 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
c3902377 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
c3902377 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
6fcb2d91 783 if ((PhysicalAddress + *NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) {\r
c3902377 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
f423cbf1 825 FreePool (IsaMapInfo);\r
c3902377 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
6fcb2d91 915 mDmaRegisters[ChannelNumber].Address,\r
916 mDmaRegisters[ChannelNumber].Page,\r
917 mDmaRegisters[ChannelNumber].Count,\r
c3902377 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
bcd70414 937/**\r
938 Maps a memory region for DMA. This implementation implement the \r
939 the full mapping support.\r
940\r
6fcb2d91 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
bcd70414 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
bcd70414 961**/\r
c3902377 962EFI_STATUS\r
6fcb2d91 963IsaIoMapFullSupport (\r
c3902377 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
c3902377 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
c3902377 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
c3902377 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
aa950314 1007\r
1008 if (ChannelNumber >= 8) {\r
1009 return EFI_INVALID_PARAMETER;\r
1010 }\r
1011\r
c3902377 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
f423cbf1 1132 FreePool (IsaMapInfo);\r
c3902377 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
6fcb2d91 1245 mDmaRegisters[ChannelNumber].Address,\r
1246 mDmaRegisters[ChannelNumber].Page,\r
1247 mDmaRegisters[ChannelNumber].Count,\r
c3902377 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
bcd70414 1267/**\r
1268 Maps a memory region for DMA\r
1269\r
6fcb2d91 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
bcd70414 1290**/\r
c3902377 1291EFI_STATUS\r
1292EFIAPI\r
1293IsaIoMap (\r
6fcb2d91 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
c3902377 1302 )\r
c3902377 1303{\r
1304 //\r
6fcb2d91 1305 // Set Feature Flag PcdIsaBusSupportDma to FALSE to disable support for ISA DMA.\r
c3902377 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
6fcb2d91 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
c3902377 1326 );\r
1327\r
1328 } else {\r
6fcb2d91 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
c3902377 1338 );\r
1339 }\r
1340}\r
bcd70414 1341\r
1342/**\r
6fcb2d91 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
bcd70414 1357**/\r
c3902377 1358EFI_STATUS\r
1359EFIAPI\r
1360IsaIoAllocateBuffer (\r
6fcb2d91 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
c3902377 1367 )\r
c3902377 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
6fcb2d91 1395 if (Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) {\r
c3902377 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
bcd70414 1422/**\r
6fcb2d91 1423 Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). \r
c3902377 1424\r
6fcb2d91 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
c3902377 1428\r
6fcb2d91 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
bcd70414 1431**/\r
bcd70414 1432EFI_STATUS\r
1433EFIAPI\r
1434IsaIoFreeBuffer (\r
6fcb2d91 1435 IN EFI_ISA_IO_PROTOCOL *This,\r
1436 IN UINTN Pages,\r
1437 IN VOID *HostAddress\r
bcd70414 1438 )\r
c3902377 1439{\r
6fcb2d91 1440 EFI_STATUS Status;\r
c3902377 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
c3902377 1451 Status = gBS->FreePages (\r
6fcb2d91 1452 (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,\r
c3902377 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