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