1 /** @file
2 The implementation for EFI_ISA_IO_PROTOCOL.
3
4 Copyright (c) 2006 - 2012, 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
InitializeIsaIoInstance(IN ISA_IO_DEVICE * IsaIoDevice,IN EFI_ISA_ACPI_RESOURCE_LIST * IsaDeviceResourceList)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
IsaIoIoRead(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINT32 Offset,IN UINTN Count,OUT VOID * Buffer)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
IsaIoIoWrite(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINT32 Offset,IN UINTN Count,IN VOID * Buffer)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
WritePort(IN EFI_ISA_IO_PROTOCOL * This,IN UINT32 Offset,IN UINT8 Value)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
WriteDmaPort(IN EFI_ISA_IO_PROTOCOL * This,IN UINT32 AddrOffset,IN UINT32 PageOffset,IN UINT32 CountOffset,IN UINT32 BaseAddress,IN UINT16 Count)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
IsaIoUnmap(IN EFI_ISA_IO_PROTOCOL * This,IN VOID * Mapping)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
IsaIoFlush(IN EFI_ISA_IO_PROTOCOL * This)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
IsaIoVerifyAccess(IN ISA_IO_DEVICE * IsaIoDevice,IN ISA_ACCESS_TYPE Type,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINTN Count,IN UINT32 Offset)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 ((UINT32)Width >= EfiIsaIoWidthMaximum ||
443 Width == EfiIsaIoWidthReserved ||
444 Width == EfiIsaIoWidthFifoReserved ||
445 Width == EfiIsaIoWidthFillReserved
446 ) {
447 return EFI_INVALID_PARAMETER;
448 }
449
450 //
451 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX
452 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX
453 //
454 if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) {
455 Count = 1;
456 }
457
458 Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03);
459
460 Status = EFI_UNSUPPORTED;
461 Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem;
462 while (Item->Type != EfiIsaAcpiResourceEndOfList) {
463 if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) ||
464 (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) {
465 if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) {
466 return EFI_SUCCESS;
467 }
468
469 if (Offset >= Item->StartRange && Offset <= Item->EndRange) {
470 Status = EFI_INVALID_PARAMETER;
471 }
472 }
473
474 Item++;
475 }
476
477 return Status;
478 }
479
480 /**
481 Performs an ISA Memory Read Cycle
482
483 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
484 @param[in] Width Specifies the width of the memory operation.
485 @param[in] Offset The offset in ISA memory space to start the memory operation.
486 @param[in] Count The number of memory operations to perform.
487 @param[out] Buffer The destination buffer to store the results
488
489 @retval EFI_SUCCESS The data was read from the device successfully.
490 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
491 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
492 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
493 **/
494 EFI_STATUS
495 EFIAPI
IsaIoMemRead(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINT32 Offset,IN UINTN Count,OUT VOID * Buffer)496 IsaIoMemRead (
497 IN EFI_ISA_IO_PROTOCOL *This,
498 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
499 IN UINT32 Offset,
500 IN UINTN Count,
501 OUT VOID *Buffer
502 )
503 {
504 EFI_STATUS Status;
505 ISA_IO_DEVICE *IsaIoDevice;
506
507 //
508 // Check if ISA memory is supported.
509 //
510 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
511 return EFI_UNSUPPORTED;
512 }
513
514 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
515
516 //
517 // Verify the Isa Io Access
518 //
519 Status = IsaIoVerifyAccess (
520 IsaIoDevice,
521 IsaAccessTypeMem,
522 Width,
523 Count,
524 Offset
525 );
526 if (EFI_ERROR (Status)) {
527 return Status;
528 }
529
530 Status = IsaIoDevice->PciIo->Mem.Read (
531 IsaIoDevice->PciIo,
532 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
533 EFI_PCI_IO_PASS_THROUGH_BAR,
534 Offset,
535 Count,
536 Buffer
537 );
538
539 if (EFI_ERROR (Status)) {
540 REPORT_STATUS_CODE (
541 EFI_ERROR_CODE | EFI_ERROR_MINOR,
542 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
543 );
544 }
545
546 return Status;
547 }
548
549 /**
550 Performs an ISA Memory Write Cycle
551
552 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
553 @param[in] Width Specifies the width of the memory operation.
554 @param[in] Offset The offset in ISA memory space to start the memory operation.
555 @param[in] Count The number of memory operations to perform.
556 @param[in] Buffer The source buffer to write data from
557
558 @retval EFI_SUCCESS The data was written to the device sucessfully.
559 @retval EFI_UNSUPPORTED The Offset is not valid for this device.
560 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
561 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
562 **/
563 EFI_STATUS
564 EFIAPI
IsaIoMemWrite(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINT32 Offset,IN UINTN Count,IN VOID * Buffer)565 IsaIoMemWrite (
566 IN EFI_ISA_IO_PROTOCOL *This,
567 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
568 IN UINT32 Offset,
569 IN UINTN Count,
570 IN VOID *Buffer
571 )
572 {
573 EFI_STATUS Status;
574 ISA_IO_DEVICE *IsaIoDevice;
575
576 //
577 // Check if ISA memory is supported.
578 //
579 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
580 return EFI_UNSUPPORTED;
581 }
582
583 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
584
585 //
586 // Verify Isa IO Access
587 //
588 Status = IsaIoVerifyAccess (
589 IsaIoDevice,
590 IsaAccessTypeMem,
591 Width,
592 Count,
593 Offset
594 );
595 if (EFI_ERROR (Status)) {
596 return Status;
597 }
598
599 Status = IsaIoDevice->PciIo->Mem.Write (
600 IsaIoDevice->PciIo,
601 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
602 EFI_PCI_IO_PASS_THROUGH_BAR,
603 Offset,
604 Count,
605 Buffer
606 );
607
608 if (EFI_ERROR (Status)) {
609 REPORT_STATUS_CODE (
610 EFI_ERROR_CODE | EFI_ERROR_MINOR,
611 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
612 );
613 }
614
615 return Status;
616 }
617
618 /**
619 Copy one region of ISA memory space to another region of ISA memory space on the ISA controller.
620
621 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
622 @param[in] Width Specifies the width of the memory copy operation.
623 @param[in] DestOffset The offset of the destination
624 @param[in] SrcOffset The offset of the source
625 @param[in] Count The number of memory copy operations to perform
626
627 @retval EFI_SUCCESS The data was copied sucessfully.
628 @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device.
629 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
630 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
631 **/
632 EFI_STATUS
633 EFIAPI
IsaIoCopyMem(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_WIDTH Width,IN UINT32 DestOffset,IN UINT32 SrcOffset,IN UINTN Count)634 IsaIoCopyMem (
635 IN EFI_ISA_IO_PROTOCOL *This,
636 IN EFI_ISA_IO_PROTOCOL_WIDTH Width,
637 IN UINT32 DestOffset,
638 IN UINT32 SrcOffset,
639 IN UINTN Count
640 )
641 {
642 EFI_STATUS Status;
643 ISA_IO_DEVICE *IsaIoDevice;
644
645 //
646 // Check if ISA memory is supported.
647 //
648 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) {
649 return EFI_UNSUPPORTED;
650 }
651
652 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This);
653
654 //
655 // Verify Isa IO Access for destination and source
656 //
657 Status = IsaIoVerifyAccess (
658 IsaIoDevice,
659 IsaAccessTypeMem,
660 Width,
661 Count,
662 DestOffset
663 );
664 if (EFI_ERROR (Status)) {
665 return Status;
666 }
667
668 Status = IsaIoVerifyAccess (
669 IsaIoDevice,
670 IsaAccessTypeMem,
671 Width,
672 Count,
673 SrcOffset
674 );
675 if (EFI_ERROR (Status)) {
676 return Status;
677 }
678
679 Status = IsaIoDevice->PciIo->CopyMem (
680 IsaIoDevice->PciIo,
681 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
682 EFI_PCI_IO_PASS_THROUGH_BAR,
683 DestOffset,
684 EFI_PCI_IO_PASS_THROUGH_BAR,
685 SrcOffset,
686 Count
687 );
688
689 if (EFI_ERROR (Status)) {
690 REPORT_STATUS_CODE (
691 EFI_ERROR_CODE | EFI_ERROR_MINOR,
692 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
693 );
694 }
695
696 return Status;
697 }
698
699 /**
700 Maps a memory region for DMA, note this implementation
701 only supports slave read/write operation to save code size.
702
703 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
704 @param Operation Indicates the type of DMA (slave or bus master), and if
705 the DMA operation is going to read or write to system memory.
706 @param ChannelNumber The slave channel number to use for this DMA operation.
707 If Operation and ChannelAttributes shows that this device
708 performs bus mastering DMA, then this field is ignored.
709 The legal range for this field is 0..7.
710 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
711 @param HostAddress The system memory address to map to the device.
712 @param NumberOfBytes On input the number of bytes to map. On output the number
713 of bytes that were mapped.
714 @param DeviceAddress The resulting map address for the bus master device to use
715 to access the hosts HostAddress.
716 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
717
718 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
719 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
720 @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.
721 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
722 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
723 **/
724 EFI_STATUS
IsaIoMapOnlySupportSlaveReadWrite(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,IN UINT8 ChannelNumber OPTIONAL,IN UINT32 ChannelAttributes,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)725 IsaIoMapOnlySupportSlaveReadWrite (
726 IN EFI_ISA_IO_PROTOCOL *This,
727 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,
728 IN UINT8 ChannelNumber OPTIONAL,
729 IN UINT32 ChannelAttributes,
730 IN VOID *HostAddress,
731 IN OUT UINTN *NumberOfBytes,
732 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
733 OUT VOID **Mapping
734 )
735 {
736 EFI_STATUS Status;
737 EFI_PHYSICAL_ADDRESS PhysicalAddress;
738 ISA_MAP_INFO *IsaMapInfo;
739 UINT8 DmaMode;
740 UINTN MaxNumberOfBytes;
741 UINT32 BaseAddress;
742 UINT16 Count;
743 UINT8 DmaMask;
744 UINT8 DmaClear;
745 UINT8 DmaChannelMode;
746
747 if ((NULL == This) ||
748 (NULL == HostAddress) ||
749 (NULL == NumberOfBytes) ||
750 (NULL == DeviceAddress) ||
751 (NULL == Mapping)
752 ) {
753 return EFI_INVALID_PARAMETER;
754 }
755
756 //
757 // Initialize the return values to their defaults
758 //
759 *Mapping = NULL;
760
761 //
762 // Make sure the Operation parameter is valid.
763 // Light IsaIo only supports two operations.
764 //
765 if (!(Operation == EfiIsaIoOperationSlaveRead ||
766 Operation == EfiIsaIoOperationSlaveWrite)) {
767 return EFI_INVALID_PARAMETER;
768 }
769
770 if (ChannelNumber >= 4) {
771 //
772 // The Light IsaIo doesn't support channelNumber larger than 4.
773 //
774 return EFI_INVALID_PARAMETER;
775 }
776
777 //
778 // Map the HostAddress to a DeviceAddress.
779 //
780 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
781 if ((PhysicalAddress + *NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) {
782 //
783 // Common Buffer operations can not be remapped. If the common buffer
784 // is above 16MB, then it is not possible to generate a mapping, so return
785 // an error.
786 //
787 if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {
788 return EFI_UNSUPPORTED;
789 }
790 //
791 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
792 // is called later.
793 //
794 IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));
795 if (IsaMapInfo == NULL) {
796 *NumberOfBytes = 0;
797 return EFI_OUT_OF_RESOURCES;
798 }
799 //
800 // Return a pointer to the MAP_INFO structure in Mapping
801 //
802 *Mapping = IsaMapInfo;
803
804 //
805 // Initialize the MAP_INFO structure
806 //
807 IsaMapInfo->Operation = Operation;
808 IsaMapInfo->NumberOfBytes = *NumberOfBytes;
809 IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);
810 IsaMapInfo->HostAddress = PhysicalAddress;
811 IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1;
812
813 //
814 // Allocate a buffer below 16MB to map the transfer to.
815 //
816 Status = gBS->AllocatePages (
817 AllocateMaxAddress,
818 EfiBootServicesData,
819 IsaMapInfo->NumberOfPages,
820 &IsaMapInfo->MappedHostAddress
821 );
822 if (EFI_ERROR (Status)) {
823 FreePool (IsaMapInfo);
824 *NumberOfBytes = 0;
825 *Mapping = NULL;
826 return Status;
827 }
828 //
829 // If this is a read operation from the DMA agents's point of view,
830 // then copy the contents of the real buffer into the mapped buffer
831 // so the DMA agent can read the contents of the real buffer.
832 //
833 if (Operation == EfiIsaIoOperationSlaveRead) {
834 CopyMem (
835 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
836 (VOID *) (UINTN) IsaMapInfo->HostAddress,
837 IsaMapInfo->NumberOfBytes
838 );
839 }
840 //
841 // The DeviceAddress is the address of the maped buffer below 16 MB
842 //
843 *DeviceAddress = IsaMapInfo->MappedHostAddress;
844 } else {
845 //
846 // The transfer is below 16 MB, so the DeviceAddress is simply the
847 // HostAddress
848 //
849 *DeviceAddress = PhysicalAddress;
850 }
851
852 //
853 // Figure out what to program into the DMA Channel Mode Register
854 //
855 DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));
856 if (Operation == EfiIsaIoOperationSlaveRead) {
857 DmaMode |= V_8237_DMA_CHMODE_MEM2IO;
858 } else {
859 DmaMode |= V_8237_DMA_CHMODE_IO2MEM;
860 }
861 //
862 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo
863 //
864 DmaMode |= V_8237_DMA_CHMODE_SINGLE;
865
866 //
867 // A Slave DMA transfer can not cross a 64K boundary.
868 // Compute *NumberOfBytes based on this restriction.
869 //
870 MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);
871 if (*NumberOfBytes > MaxNumberOfBytes) {
872 *NumberOfBytes = MaxNumberOfBytes;
873 }
874 //
875 // Compute the values to program into the BaseAddress and Count registers
876 // of the Slave DMA controller
877 //
878 BaseAddress = (UINT32) (*DeviceAddress);
879 Count = (UINT16) (*NumberOfBytes - 1);
880 //
881 // Program the DMA Write Single Mask Register for ChannelNumber
882 // Clear the DMA Byte Pointer Register
883 //
884 DmaMask = R_8237_DMA_WRSMSK_CH0_3;
885 DmaClear = R_8237_DMA_CBPR_CH0_3;
886 DmaChannelMode = R_8237_DMA_CHMODE_CH0_3;
887
888 Status = WritePort (
889 This,
890 DmaMask,
891 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
892 );
893 if (EFI_ERROR (Status)) {
894 return Status;
895 }
896
897 Status = WritePort (
898 This,
899 DmaClear,
900 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
901 );
902 if (EFI_ERROR (Status)) {
903 return Status;
904 }
905
906 Status = WritePort (This, DmaChannelMode, DmaMode);
907 if (EFI_ERROR (Status)) {
908 return Status;
909 }
910
911 Status = WriteDmaPort (
912 This,
913 mDmaRegisters[ChannelNumber].Address,
914 mDmaRegisters[ChannelNumber].Page,
915 mDmaRegisters[ChannelNumber].Count,
916 BaseAddress,
917 Count
918 );
919 if (EFI_ERROR (Status)) {
920 return Status;
921 }
922
923 Status = WritePort (
924 This,
925 DmaMask,
926 (UINT8) (ChannelNumber & 0x03)
927 );
928 if (EFI_ERROR (Status)) {
929 return Status;
930 }
931
932 return EFI_SUCCESS;
933 }
934
935 /**
936 Maps a memory region for DMA. This implementation implement the
937 the full mapping support.
938
939 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
940 @param Operation Indicates the type of DMA (slave or bus master), and if
941 the DMA operation is going to read or write to system memory.
942 @param ChannelNumber The slave channel number to use for this DMA operation.
943 If Operation and ChannelAttributes shows that this device
944 performs bus mastering DMA, then this field is ignored.
945 The legal range for this field is 0..7.
946 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
947 @param HostAddress The system memory address to map to the device.
948 @param NumberOfBytes On input the number of bytes to map. On output the number
949 of bytes that were mapped.
950 @param DeviceAddress The resulting map address for the bus master device to use
951 to access the hosts HostAddress.
952 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
953
954 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
955 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
956 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer.
957 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address.
958 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
959 **/
960 EFI_STATUS
IsaIoMapFullSupport(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,IN UINT8 ChannelNumber OPTIONAL,IN UINT32 ChannelAttributes,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)961 IsaIoMapFullSupport (
962 IN EFI_ISA_IO_PROTOCOL *This,
963 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,
964 IN UINT8 ChannelNumber OPTIONAL,
965 IN UINT32 ChannelAttributes,
966 IN VOID *HostAddress,
967 IN OUT UINTN *NumberOfBytes,
968 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
969 OUT VOID **Mapping
970 )
971 {
972 EFI_STATUS Status;
973 BOOLEAN Master;
974 BOOLEAN Read;
975 EFI_PHYSICAL_ADDRESS PhysicalAddress;
976 ISA_MAP_INFO *IsaMapInfo;
977 UINT8 DmaMode;
978 UINTN MaxNumberOfBytes;
979 UINT32 BaseAddress;
980 UINT16 Count;
981 UINT8 DmaMask;
982 UINT8 DmaClear;
983 UINT8 DmaChannelMode;
984
985 if ((NULL == This) ||
986 (NULL == HostAddress) ||
987 (NULL == NumberOfBytes) ||
988 (NULL == DeviceAddress) ||
989 (NULL == Mapping)
990 ) {
991 return EFI_INVALID_PARAMETER;
992 }
993
994 //
995 // Initialize the return values to their defaults
996 //
997 *Mapping = NULL;
998
999 //
1000 // Make sure the Operation parameter is valid
1001 //
1002 if ((UINT32)Operation >= EfiIsaIoOperationMaximum) {
1003 return EFI_INVALID_PARAMETER;
1004 }
1005
1006 if (ChannelNumber >= 8) {
1007 return EFI_INVALID_PARAMETER;
1008 }
1009
1010 //
1011 // See if this is a Slave DMA Operation
1012 //
1013 Master = TRUE;
1014 Read = FALSE;
1015 if (Operation == EfiIsaIoOperationSlaveRead) {
1016 Operation = EfiIsaIoOperationBusMasterRead;
1017 Master = FALSE;
1018 Read = TRUE;
1019 }
1020
1021 if (Operation == EfiIsaIoOperationSlaveWrite) {
1022 Operation = EfiIsaIoOperationBusMasterWrite;
1023 Master = FALSE;
1024 Read = FALSE;
1025 }
1026
1027 if (!Master) {
1028 //
1029 // Make sure that ChannelNumber is a valid channel number
1030 // Channel 4 is used to cascade, so it is illegal.
1031 //
1032 if (ChannelNumber == 4 || ChannelNumber > 7) {
1033 return EFI_INVALID_PARAMETER;
1034 }
1035 //
1036 // This implementation only support COMPATIBLE DMA Transfers
1037 //
1038 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE) == 0) {
1039 return EFI_INVALID_PARAMETER;
1040 }
1041
1042 if ((ChannelAttributes &
1043 (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A |
1044 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B |
1045 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C)) != 0) {
1046 return EFI_INVALID_PARAMETER;
1047 }
1048
1049 if (ChannelNumber < 4) {
1050 //
1051 // If this is Channel 0..3, then the width must be 8 bit
1052 //
1053 if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) == 0) ||
1054 ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) != 0)
1055 ) {
1056 return EFI_INVALID_PARAMETER;
1057 }
1058 } else {
1059 //
1060 // If this is Channel 4..7, then the width must be 16 bit
1061 //
1062 if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) != 0) ||
1063 ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) == 0)) {
1064 return EFI_INVALID_PARAMETER;
1065 }
1066 }
1067 //
1068 // Either Demand Mode or Single Mode must be selected, but not both
1069 //
1070 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) {
1071 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) {
1072 return EFI_INVALID_PARAMETER;
1073 }
1074 } else {
1075 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) == 0) {
1076 return EFI_INVALID_PARAMETER;
1077 }
1078 }
1079 }
1080 //
1081 // Map the HostAddress to a DeviceAddress.
1082 //
1083 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1084 if ((PhysicalAddress +*NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) {
1085 //
1086 // Common Buffer operations can not be remapped. If the common buffer
1087 // is above 16MB, then it is not possible to generate a mapping, so return
1088 // an error.
1089 //
1090 if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) {
1091 return EFI_UNSUPPORTED;
1092 }
1093 //
1094 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap()
1095 // is called later.
1096 //
1097 IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO));
1098 if (IsaMapInfo == NULL) {
1099 *NumberOfBytes = 0;
1100 return EFI_OUT_OF_RESOURCES;
1101 }
1102 //
1103 // Return a pointer to the MAP_INFO structure in Mapping
1104 //
1105 *Mapping = IsaMapInfo;
1106
1107 //
1108 // Initialize the MAP_INFO structure
1109 //
1110 IsaMapInfo->Operation = Operation;
1111 IsaMapInfo->NumberOfBytes = *NumberOfBytes;
1112 IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);
1113 IsaMapInfo->HostAddress = PhysicalAddress;
1114 IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1;
1115
1116 //
1117 // Allocate a buffer below 16MB to map the transfer to.
1118 //
1119 Status = gBS->AllocatePages (
1120 AllocateMaxAddress,
1121 EfiBootServicesData,
1122 IsaMapInfo->NumberOfPages,
1123 &IsaMapInfo->MappedHostAddress
1124 );
1125 if (EFI_ERROR (Status)) {
1126 FreePool (IsaMapInfo);
1127 *NumberOfBytes = 0;
1128 *Mapping = NULL;
1129 return Status;
1130 }
1131 //
1132 // If this is a read operation from the DMA agents's point of view,
1133 // then copy the contents of the real buffer into the mapped buffer
1134 // so the DMA agent can read the contents of the real buffer.
1135 //
1136 if (Operation == EfiIsaIoOperationBusMasterRead) {
1137 CopyMem (
1138 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress,
1139 (VOID *) (UINTN) IsaMapInfo->HostAddress,
1140 IsaMapInfo->NumberOfBytes
1141 );
1142 }
1143 //
1144 // The DeviceAddress is the address of the maped buffer below 16 MB
1145 //
1146 *DeviceAddress = IsaMapInfo->MappedHostAddress;
1147 } else {
1148 //
1149 // The transfer is below 16 MB, so the DeviceAddress is simply the
1150 // HostAddress
1151 //
1152 *DeviceAddress = PhysicalAddress;
1153 }
1154 //
1155 // If this is a Bus Master operation then return
1156 //
1157 if (Master) {
1158 return EFI_SUCCESS;
1159 }
1160 //
1161 // Figure out what to program into the DMA Channel Mode Register
1162 //
1163 DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03));
1164 if (Read) {
1165 DmaMode |= V_8237_DMA_CHMODE_MEM2IO;
1166 } else {
1167 DmaMode |= V_8237_DMA_CHMODE_IO2MEM;
1168 }
1169
1170 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) != 0) {
1171 DmaMode |= B_8237_DMA_CHMODE_AE;
1172 }
1173
1174 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) {
1175 DmaMode |= V_8237_DMA_CHMODE_DEMAND;
1176 }
1177
1178 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) {
1179 DmaMode |= V_8237_DMA_CHMODE_SINGLE;
1180 }
1181 //
1182 // A Slave DMA transfer can not cross a 64K boundary.
1183 // Compute *NumberOfBytes based on this restriction.
1184 //
1185 MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff);
1186 if (*NumberOfBytes > MaxNumberOfBytes) {
1187 *NumberOfBytes = MaxNumberOfBytes;
1188 }
1189 //
1190 // Compute the values to program into the BaseAddress and Count registers
1191 // of the Slave DMA controller
1192 //
1193 if (ChannelNumber < 4) {
1194 BaseAddress = (UINT32) (*DeviceAddress);
1195 Count = (UINT16) (*NumberOfBytes - 1);
1196 } else {
1197 BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1));
1198 Count = (UINT16) ((*NumberOfBytes - 1) >> 1);
1199 }
1200 //
1201 // Program the DMA Write Single Mask Register for ChannelNumber
1202 // Clear the DMA Byte Pointer Register
1203 //
1204 if (ChannelNumber < 4) {
1205 DmaMask = R_8237_DMA_WRSMSK_CH0_3;
1206 DmaClear = R_8237_DMA_CBPR_CH0_3;
1207 DmaChannelMode = R_8237_DMA_CHMODE_CH0_3;
1208 } else {
1209 DmaMask = R_8237_DMA_WRSMSK_CH4_7;
1210 DmaClear = R_8237_DMA_CBPR_CH4_7;
1211 DmaChannelMode = R_8237_DMA_CHMODE_CH4_7;
1212 }
1213
1214 Status = WritePort (
1215 This,
1216 DmaMask,
1217 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1218 );
1219 if (EFI_ERROR (Status)) {
1220 return Status;
1221 }
1222
1223 Status = WritePort (
1224 This,
1225 DmaClear,
1226 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03))
1227 );
1228 if (EFI_ERROR (Status)) {
1229 return Status;
1230 }
1231
1232 Status = WritePort (This, DmaChannelMode, DmaMode);
1233 if (EFI_ERROR (Status)) {
1234 return Status;
1235 }
1236
1237 Status = WriteDmaPort (
1238 This,
1239 mDmaRegisters[ChannelNumber].Address,
1240 mDmaRegisters[ChannelNumber].Page,
1241 mDmaRegisters[ChannelNumber].Count,
1242 BaseAddress,
1243 Count
1244 );
1245 if (EFI_ERROR (Status)) {
1246 return Status;
1247 }
1248
1249 Status = WritePort (
1250 This,
1251 DmaMask,
1252 (UINT8) (ChannelNumber & 0x03)
1253 );
1254 if (EFI_ERROR (Status)) {
1255 return Status;
1256 }
1257
1258 return EFI_SUCCESS;
1259 }
1260
1261 /**
1262 Maps a memory region for DMA
1263
1264 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1265 @param Operation Indicates the type of DMA (slave or bus master), and if
1266 the DMA operation is going to read or write to system memory.
1267 @param ChannelNumber The slave channel number to use for this DMA operation.
1268 If Operation and ChannelAttributes shows that this device
1269 performs bus mastering DMA, then this field is ignored.
1270 The legal range for this field is 0..7.
1271 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation
1272 @param HostAddress The system memory address to map to the device.
1273 @param NumberOfBytes On input the number of bytes to map. On output the number
1274 of bytes that were mapped.
1275 @param DeviceAddress The resulting map address for the bus master device to use
1276 to access the hosts HostAddress.
1277 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap().
1278
1279 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
1280 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
1281 @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer.
1282 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1283 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1284 **/
1285 EFI_STATUS
1286 EFIAPI
IsaIoMap(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,IN UINT8 ChannelNumber OPTIONAL,IN UINT32 ChannelAttributes,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)1287 IsaIoMap (
1288 IN EFI_ISA_IO_PROTOCOL *This,
1289 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation,
1290 IN UINT8 ChannelNumber OPTIONAL,
1291 IN UINT32 ChannelAttributes,
1292 IN VOID *HostAddress,
1293 IN OUT UINTN *NumberOfBytes,
1294 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
1295 OUT VOID **Mapping
1296 )
1297 {
1298 //
1299 // Check if DMA is supported.
1300 //
1301 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) {
1302 return EFI_UNSUPPORTED;
1303 }
1304 //
1305 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for
1306 // ISA Bus Master.
1307 //
1308 // So we just return EFI_UNSUPPORTED for these functions.
1309 //
1310 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) {
1311 return IsaIoMapOnlySupportSlaveReadWrite (
1312 This,
1313 Operation,
1314 ChannelNumber,
1315 ChannelAttributes,
1316 HostAddress,
1317 NumberOfBytes,
1318 DeviceAddress,
1319 Mapping
1320 );
1321
1322 } else {
1323 return IsaIoMapFullSupport (
1324 This,
1325 Operation,
1326 ChannelNumber,
1327 ChannelAttributes,
1328 HostAddress,
1329 NumberOfBytes,
1330 DeviceAddress,
1331 Mapping
1332 );
1333 }
1334 }
1335
1336 /**
1337 Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping.
1338
1339 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1340 @param[in] Type The type allocation to perform.
1341 @param[in] MemoryType The type of memory to allocate.
1342 @param[in] Pages The number of pages to allocate.
1343 @param[out] HostAddress A pointer to store the base address of the allocated range.
1344 @param[in] Attributes The requested bit mask of attributes for the allocated range.
1345
1346 @retval EFI_SUCCESS The requested memory pages were allocated.
1347 @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL
1348 @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified
1349 by HostAddress, Pages, and Type is not available for common buffer use.
1350 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1351 **/
1352 EFI_STATUS
1353 EFIAPI
IsaIoAllocateBuffer(IN EFI_ISA_IO_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,OUT VOID ** HostAddress,IN UINT64 Attributes)1354 IsaIoAllocateBuffer (
1355 IN EFI_ISA_IO_PROTOCOL *This,
1356 IN EFI_ALLOCATE_TYPE Type,
1357 IN EFI_MEMORY_TYPE MemoryType,
1358 IN UINTN Pages,
1359 OUT VOID **HostAddress,
1360 IN UINT64 Attributes
1361 )
1362 {
1363 EFI_STATUS Status;
1364 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1365
1366 //
1367 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1368 // ISA Bus Master.
1369 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1370 //
1371 if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) ||
1372 ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) {
1373 return EFI_UNSUPPORTED;
1374 }
1375
1376 if (HostAddress == NULL) {
1377 return EFI_INVALID_PARAMETER;
1378 }
1379
1380 if ((UINT32)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 REPORT_STATUS_CODE (
1410 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1411 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
1412 );
1413 return Status;
1414 }
1415
1416 *HostAddress = (VOID *) (UINTN) PhysicalAddress;
1417 return Status;
1418 }
1419
1420 /**
1421 Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer().
1422
1423 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance.
1424 @param[in] Pages The number of pages to free.
1425 @param[in] HostAddress The base address of the allocated range.
1426
1427 @retval EFI_SUCCESS The requested memory pages were freed.
1428 @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer().
1429 **/
1430 EFI_STATUS
1431 EFIAPI
IsaIoFreeBuffer(IN EFI_ISA_IO_PROTOCOL * This,IN UINTN Pages,IN VOID * HostAddress)1432 IsaIoFreeBuffer (
1433 IN EFI_ISA_IO_PROTOCOL *This,
1434 IN UINTN Pages,
1435 IN VOID *HostAddress
1436 )
1437 {
1438 EFI_STATUS Status;
1439
1440 //
1441 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for
1442 // ISA Bus Master.
1443 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA.
1444 //
1445 if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) ||
1446 ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) {
1447 return EFI_UNSUPPORTED;
1448 }
1449
1450 Status = gBS->FreePages (
1451 (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,
1452 Pages
1453 );
1454 if (EFI_ERROR (Status)) {
1455 REPORT_STATUS_CODE (
1456 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1457 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR
1458 );
1459 }
1460
1461 return Status;
1462 }
1463
1464