e4715383eacf4442b6df6a7c01fd1af7ba89fd05
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaBusDxe / IsaIo.c
1 /** @file
2 The implementation for EFI_ISA_IO_PROTOCOL.
3
4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
5 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 Initializes an ISA I/O Instance
85
86 @param[in] IsaIoDevice The iso device to be initialized.
87 @param[in] IsaDeviceResourceList The resource list.
88
89 **/
90 VOID
91 InitializeIsaIoInstance (
92 IN ISA_IO_DEVICE *IsaIoDevice,
93 IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList
94 )
95 {
96 //
97 // Use the ISA IO Protocol structure template to initialize the ISA IO instance
98 //
99 CopyMem (
100 &IsaIoDevice->IsaIo,
101 &mIsaIoInterface,
102 sizeof (EFI_ISA_IO_PROTOCOL)
103 );
104
105 IsaIoDevice->IsaIo.ResourceList = IsaDeviceResourceList;
106 }
107
108 /**
109 Performs an ISA I/O Read Cycle
110
111 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
112 @param[in] Width Specifies the width of the I/O operation.
113 @param[in] Offset The offset in ISA I/O space to start the I/O operation.
114 @param[in] Count The number of I/O operations to perform.
115 @param[out] Buffer The destination buffer to store the results
116
117 @retval EFI_SUCCESS The data was read from the device sucessfully.
118 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
119 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
120 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
121 **/
122 EFI_STATUS
123 EFIAPI
124 IsaIoIoRead (
125 IN EFI_ISA_IO_PROTOCOL *This,
126 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
127 IN UINT32 Offset,
128 IN UINTN Count,
129 OUT VOID *Buffer
130 )
131 {
132 EFI_STATUS Status;
133 ISA_IO_DEVICE *IsaIoDevice;
134
135 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
136
137 //
138 // Verify Isa IO Access
139 //
140 Status = IsaIoVerifyAccess (
141 IsaIoDevice,
142 IsaAccessTypeIo,
143 Width,
144 Count,
145 Offset
146 );
147 if (EFI_ERROR (Status)) {
148 return Status;
149 }
150
151 Status = IsaIoDevice->PciIo->Io.Read (
152 IsaIoDevice->PciIo,
153 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
154 EFI_PCI_IO_PASS_THROUGH_BAR,
155 Offset,
156 Count,
157 Buffer
158 );
159
160 if (EFI_ERROR (Status)) {
161 REPORT_STATUS_CODE (
162 EFI_ERROR_CODE | EFI_ERROR_MINOR,
163 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
164 );
165 }
166
167 return Status;
168 }
169
170 /**
171 Performs an ISA I/O Write Cycle
172
173 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
174 @param[in] Width Specifies the width of the I/O operation.
175 @param[in] Offset The offset in ISA I/O space to start the I/O operation.
176 @param[in] Count The number of I/O operations to perform.
177 @param[in] Buffer The source buffer to write data from
178
179 @retval EFI_SUCCESS The data was writen to the device sucessfully.
180 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
181 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
182 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
183 **/
184 EFI_STATUS
185 EFIAPI
186 IsaIoIoWrite (
187 IN EFI_ISA_IO_PROTOCOL *This,
188 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
189 IN UINT32 Offset,
190 IN UINTN Count,
191 IN VOID *Buffer
192 )
193 {
194 EFI_STATUS Status;
195 ISA_IO_DEVICE *IsaIoDevice;
196
197 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
198
199 //
200 // Verify Isa IO Access
201 //
202 Status = IsaIoVerifyAccess (
203 IsaIoDevice,
204 IsaAccessTypeIo,
205 Width,
206 Count,
207 Offset
208 );
209 if (EFI_ERROR (Status)) {
210 return Status;
211 }
212
213 Status = IsaIoDevice->PciIo->Io.Write (
214 IsaIoDevice->PciIo,
215 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
216 EFI_PCI_IO_PASS_THROUGH_BAR,
217 Offset,
218 Count,
219 Buffer
220 );
221
222 if (EFI_ERROR (Status)) {
223 REPORT_STATUS_CODE (
224 EFI_ERROR_CODE | EFI_ERROR_MINOR,
225 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
226 );
227 }
228
229 return Status;
230 }
231
232 /**
233 Writes an 8-bit I/O Port
234
235 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
236 @param[in] Offset The offset in ISA IO space to start the IO operation.
237 @param[in] Value The data to write port.
238
239 @retval EFI_SUCCESS Success.
240 @retval EFI_INVALID_PARAMETER Parameter is invalid.
241 @retval EFI_UNSUPPORTED The address range specified by Offset is not valid.
242 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
243 **/
244 EFI_STATUS
245 WritePort (
246 IN EFI_ISA_IO_PROTOCOL *This,
247 IN UINT32 Offset,
248 IN UINT8 Value
249 )
250 {
251 EFI_STATUS Status;
252 ISA_IO_DEVICE *IsaIoDevice;
253
254 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
255
256 Status = IsaIoDevice->PciIo->Io.Write (
257 IsaIoDevice->PciIo,
258 EfiPciIoWidthUint8,
259 EFI_PCI_IO_PASS_THROUGH_BAR,
260 Offset,
261 1,
262 &Value
263 );
264 if (EFI_ERROR (Status)) {
265 REPORT_STATUS_CODE (
266 EFI_ERROR_CODE | EFI_ERROR_MINOR,
267 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
268 );
269 return Status;
270 }
271
272 gBS->Stall (50);
273
274 return EFI_SUCCESS;
275 }
276
277 /**
278 Writes I/O operation base address and count number to a 8 bit I/O Port.
279
280 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
281 @param[in] AddrOffset The address' offset.
282 @param[in] PageOffset The page's offest.
283 @param[in] CountOffset The count's offset.
284 @param[in] BaseAddress The base address.
285 @param[in] Count The number of I/O operations to perform.
286
287 @retval EFI_SUCCESS Success.
288 @retval EFI_INVALID_PARAMETER Parameter is invalid.
289 @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid.
290 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
291 **/
292 EFI_STATUS
293 WriteDmaPort (
294 IN EFI_ISA_IO_PROTOCOL *This,
295 IN UINT32 AddrOffset,
296 IN UINT32 PageOffset,
297 IN UINT32 CountOffset,
298 IN UINT32 BaseAddress,
299 IN UINT16 Count
300 )
301 {
302 EFI_STATUS Status;
303
304 Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff));
305 if (EFI_ERROR (Status)) {
306 return Status;
307 }
308
309 Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff));
310 if (EFI_ERROR (Status)) {
311 return Status;
312 }
313
314 Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff));
315 if (EFI_ERROR (Status)) {
316 return Status;
317 }
318
319 Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff));
320 if (EFI_ERROR (Status)) {
321 return Status;
322 }
323
324 Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff));
325 return Status;
326 }
327
328 /**
329 Unmaps a memory region for DMA
330
331 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
332 @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map().
333
334 @retval EFI_SUCCESS The range was unmapped.
335 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
336 **/
337 EFI_STATUS
338 EFIAPI
339 IsaIoUnmap (
340 IN EFI_ISA_IO_PROTOCOL *This,
341 IN VOID *Mapping
342 )
343 {
344 ISA_MAP_INFO *IsaMapInfo;
345
346 //
347 // Check if DMA is supported.
348 //
349 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) {
350 return EFI_UNSUPPORTED;
351 }
352
353 //
354 // See if the Map() operation associated with this Unmap() required a mapping
355 // buffer.If a mapping buffer was not required, then this function simply
356 // returns EFI_SUCCESS.
357 //
358 if (Mapping != NULL) {
359 //
360 // Get the MAP_INFO structure from Mapping
361 //
362 IsaMapInfo = (ISA_MAP_INFO *) Mapping;
363
364 //
365 // If this is a write operation from the Agent's point of view,
366 // then copy the contents of the mapped buffer into the real buffer
367 // so the processor can read the contents of the real buffer.
368 //
369 if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) {
370 CopyMem (
371 (VOID *) (UINTN) IsaMapInfo->HostAddress,
372 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
373 IsaMapInfo->NumberOfBytes
374 );
375 }
376 //
377 // Free the mapped buffer and the MAP_INFO structure.
378 //
379 gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages);
380 FreePool (IsaMapInfo);
381 }
382
383 return EFI_SUCCESS;
384 }
385
386 /**
387 Flushes any posted write data to the system memory.
388
389 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
390
391 @retval EFI_SUCCESS The buffers were flushed.
392 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error.
393 **/
394 EFI_STATUS
395 EFIAPI
396 IsaIoFlush (
397 IN EFI_ISA_IO_PROTOCOL *This
398 )
399 {
400 EFI_STATUS Status;
401 ISA_IO_DEVICE *IsaIoDevice;
402
403 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
404
405 Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo);
406
407 if (EFI_ERROR (Status)) {
408 REPORT_STATUS_CODE (
409 EFI_ERROR_CODE | EFI_ERROR_MINOR,
410 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
411 );
412 }
413
414 return Status;
415 }
416
417 /**
418 Verifies access to an ISA device
419
420 @param[in] IsaIoDevice The ISA device to be verified.
421 @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo.
422 @param[in] Width The width of the memory operation.
423 @param[in] Count The number of memory operations to perform.
424 @param[in] Offset The offset in ISA memory space to start the memory operation.
425
426 @retval EFI_SUCCESS Verify success.
427 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
428 @retval EFI_UNSUPPORTED The device ont support the access type.
429 **/
430 EFI_STATUS
431 IsaIoVerifyAccess (
432 IN ISA_IO_DEVICE *IsaIoDevice,
433 IN ISA_ACCESS_TYPE Type,
434 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
435 IN UINTN Count,
436 IN UINT32 Offset
437 )
438 {
439 EFI_ISA_ACPI_RESOURCE *Item;
440 EFI_STATUS Status;
441
442 if (Width < EfiIsaIoWidthUint8 ||
443 Width >= EfiIsaIoWidthMaximum ||
444 Width == EfiIsaIoWidthReserved ||
445 Width == EfiIsaIoWidthFifoReserved ||
446 Width == EfiIsaIoWidthFillReserved
447 ) {
448 return EFI_INVALID_PARAMETER;
449 }
450
451 //
452 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
453 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
454 //
455 if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) {
456 Count = 1;
457 }
458
459 Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03);
460
461 Status = EFI_UNSUPPORTED;
462 Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem;
463 while (Item->Type != EfiIsaAcpiResourceEndOfList) {
464 if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) ||
465 (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) {
466 if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) {
467 return EFI_SUCCESS;
468 }
469
470 if (Offset >= Item->StartRange && Offset <= Item->EndRange) {
471 Status = EFI_INVALID_PARAMETER;
472 }
473 }
474
475 Item++;
476 }
477
478 return Status;
479 }
480
481 /**
482 Performs an ISA Memory Read Cycle
483
484 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
485 @param[in] Width Specifies the width of the memory operation.
486 @param[in] Offset The offset in ISA memory space to start the memory operation.
487 @param[in] Count The number of memory operations to perform.
488 @param[out] Buffer The destination buffer to store the results
489
490 @retval EFI_SUCCESS The data was read from the device successfully.
491 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
492 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
493 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
494 **/
495 EFI_STATUS
496 EFIAPI
497 IsaIoMemRead (
498 IN EFI_ISA_IO_PROTOCOL *This,
499 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
500 IN UINT32 Offset,
501 IN UINTN Count,
502 OUT VOID *Buffer
503 )
504 {
505 EFI_STATUS Status;
506 ISA_IO_DEVICE *IsaIoDevice;
507
508 //
509 // Check if ISA memory is supported.
510 //
511 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
512 return EFI_UNSUPPORTED;
513 }
514
515 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
516
517 //
518 // Verify the Isa Io Access
519 //
520 Status = IsaIoVerifyAccess (
521 IsaIoDevice,
522 IsaAccessTypeMem,
523 Width,
524 Count,
525 Offset
526 );
527 if (EFI_ERROR (Status)) {
528 return Status;
529 }
530
531 Status = IsaIoDevice->PciIo->Mem.Read (
532 IsaIoDevice->PciIo,
533 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
534 EFI_PCI_IO_PASS_THROUGH_BAR,
535 Offset,
536 Count,
537 Buffer
538 );
539
540 if (EFI_ERROR (Status)) {
541 REPORT_STATUS_CODE (
542 EFI_ERROR_CODE | EFI_ERROR_MINOR,
543 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
544 );
545 }
546
547 return Status;
548 }
549
550 /**
551 Performs an ISA Memory Write Cycle
552
553 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
554 @param[in] Width Specifies the width of the memory operation.
555 @param[in] Offset The offset in ISA memory space to start the memory operation.
556 @param[in] Count The number of memory operations to perform.
557 @param[in] Buffer The source buffer to write data from
558
559 @retval EFI_SUCCESS The data was written to the device sucessfully.
560 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
561 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
562 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
563 **/
564 EFI_STATUS
565 EFIAPI
566 IsaIoMemWrite (
567 IN EFI_ISA_IO_PROTOCOL *This,
568 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
569 IN UINT32 Offset,
570 IN UINTN Count,
571 IN VOID *Buffer
572 )
573 {
574 EFI_STATUS Status;
575 ISA_IO_DEVICE *IsaIoDevice;
576
577 //
578 // Check if ISA memory is supported.
579 //
580 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
581 return EFI_UNSUPPORTED;
582 }
583
584 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
585
586 //
587 // Verify Isa IO Access
588 //
589 Status = IsaIoVerifyAccess (
590 IsaIoDevice,
591 IsaAccessTypeMem,
592 Width,
593 Count,
594 Offset
595 );
596 if (EFI_ERROR (Status)) {
597 return Status;
598 }
599
600 Status = IsaIoDevice->PciIo->Mem.Write (
601 IsaIoDevice->PciIo,
602 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
603 EFI_PCI_IO_PASS_THROUGH_BAR,
604 Offset,
605 Count,
606 Buffer
607 );
608
609 if (EFI_ERROR (Status)) {
610 REPORT_STATUS_CODE (
611 EFI_ERROR_CODE | EFI_ERROR_MINOR,
612 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
613 );
614 }
615
616 return Status;
617 }
618
619 /**
620 Copy one region of ISA memory space to another region of ISA memory space on the ISA controller.
621
622 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
623 @param[in] Width Specifies the width of the memory copy operation.
624 @param[in] DestOffset The offset of the destination
625 @param[in] SrcOffset The offset of the source
626 @param[in] Count The number of memory copy operations to perform
627
628 @retval EFI_SUCCESS The data was copied sucessfully.
629 @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device.
630 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
631 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
632 **/
633 EFI_STATUS
634 EFIAPI
635 IsaIoCopyMem (
636 IN EFI_ISA_IO_PROTOCOL *This,
637 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
638 IN UINT32 DestOffset,
639 IN UINT32 SrcOffset,
640 IN UINTN Count
641 )
642 {
643 EFI_STATUS Status;
644 ISA_IO_DEVICE *IsaIoDevice;
645
646 //
647 // Check if ISA memory is supported.
648 //
649 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
650 return EFI_UNSUPPORTED;
651 }
652
653 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
654
655 //
656 // Verify Isa IO Access for destination and source
657 //
658 Status = IsaIoVerifyAccess (
659 IsaIoDevice,
660 IsaAccessTypeMem,
661 Width,
662 Count,
663 DestOffset
664 );
665 if (EFI_ERROR (Status)) {
666 return Status;
667 }
668
669 Status = IsaIoVerifyAccess (
670 IsaIoDevice,
671 IsaAccessTypeMem,
672 Width,
673 Count,
674 SrcOffset
675 );
676 if (EFI_ERROR (Status)) {
677 return Status;
678 }
679
680 Status = IsaIoDevice->PciIo->CopyMem (
681 IsaIoDevice->PciIo,
682 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
683 EFI_PCI_IO_PASS_THROUGH_BAR,
684 DestOffset,
685 EFI_PCI_IO_PASS_THROUGH_BAR,
686 SrcOffset,
687 Count
688 );
689
690 if (EFI_ERROR (Status)) {
691 REPORT_STATUS_CODE (
692 EFI_ERROR_CODE | EFI_ERROR_MINOR,
693 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
694 );
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 // Check if DMA is supported.
1301 //
1302 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) {
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 ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) {
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 (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) ||
1373 ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) {
1374 return EFI_UNSUPPORTED;
1375 }
1376
1377 if (HostAddress == NULL) {
1378 return EFI_INVALID_PARAMETER;
1379 }
1380
1381 if (Type < AllocateAnyPages || Type >= MaxAllocateType) {
1382 return EFI_INVALID_PARAMETER;
1383 }
1384 //
1385 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1386 //
1387 if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
1388 return EFI_INVALID_PARAMETER;
1389 }
1390
1391 if ((Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) != 0) {
1392 return EFI_UNSUPPORTED;
1393 }
1394
1395 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (ISA_MAX_MEMORY_ADDRESS - 1);
1396 if (Type == AllocateAddress) {
1397 if ((UINTN) (*HostAddress) >= ISA_MAX_MEMORY_ADDRESS) {
1398 return EFI_UNSUPPORTED;
1399 } else {
1400 PhysicalAddress = (UINTN) (*HostAddress);
1401 }
1402 }
1403
1404 if (Type == AllocateAnyPages) {
1405 Type = AllocateMaxAddress;
1406 }
1407
1408 Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress);
1409 if (EFI_ERROR (Status)) {
1410 REPORT_STATUS_CODE (
1411 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1412 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
1413 );
1414 return Status;
1415 }
1416
1417 *HostAddress = (VOID *) (UINTN) PhysicalAddress;
1418 return Status;
1419 }
1420
1421 /**
1422 Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer().
1423
1424 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1425 @param[in] Pages The number of pages to free.
1426 @param[in] HostAddress The base address of the allocated range.
1427
1428 @retval EFI_SUCCESS The requested memory pages were freed.
1429 @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1430 **/
1431 EFI_STATUS
1432 EFIAPI
1433 IsaIoFreeBuffer (
1434 IN EFI_ISA_IO_PROTOCOL *This,
1435 IN UINTN Pages,
1436 IN VOID *HostAddress
1437 )
1438 {
1439 EFI_STATUS Status;
1440
1441 //
1442 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1443 // ISA Bus Master.
1444 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1445 //
1446 if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) ||
1447 ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) {
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 REPORT_STATUS_CODE (
1457 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1458 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
1459 );
1460 }
1461
1462 return Status;
1463 }
1464