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