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