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