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