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