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