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