]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/DeviceIoToPciRootBridgeIoThunk/DeviceIoToPciRootBridgeIoThunk.c
clean up the un-suitable ';' location when declaring the functions. The regular is...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / DeviceIoToPciRootBridgeIoThunk / DeviceIoToPciRootBridgeIoThunk.c
1 /** @file
2 Module produces Device I/O on top of PCI Root Bridge I/O for Segment 0 only.
3 This is a valid assumption because many of the EFI 1.02/EFI 1.10 systems that may have provided
4 Device I/O were single segment platforms. The goal of the ECP is to provide compatibility with the
5 drivers/apps that may have used Device I/O.
6
7 Device I/O is on list of deprecated protocols for UEFI 2.0 and later.
8 This module module layers Device I/O on top of PCI Root Bridge I/O (Segment 0)
9 Use if:
10 There are no R8.x modules present that produces Device I/O
11 EFI drivers included that consume Device I/O
12 Platform required to support EFI drivers that consume Device I/O
13 Platform required to support EFI applications that consume Device I/O
14
15 Copyright (c) 2008 Intel Corporation. <BR>
16 All rights reserved. This program and the accompanying materials
17 are licensed and made available under the terms and conditions of the BSD License
18 which accompanies this distribution. The full text of the license may be found at
19 http://opensource.org/licenses/bsd-license.php
20
21 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
22 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23
24 **/
25
26 #include <PiDxe.h>
27 #include <IndustryStandard/Pci22.h>
28 #include <Protocol/DeviceIo.h>
29 #include <Protocol/PciRootBridgeIo.h>
30 #include <Library/BaseLib.h>
31 #include <Library/BaseMemoryLib.h>
32 #include <Library/DebugLib.h>
33 #include <Library/UefiBootServicesTableLib.h>
34 #include <Library/UefiDriverEntryPoint.h>
35 #include <Library/UefiLib.h>
36 #include <Library/MemoryAllocationLib.h>
37 #include <Library/DevicePathLib.h>
38
39
40 /**
41 Perform reading memory mapped I/O space of device.
42
43 @param This A pointer to EFI_DEVICE_IO protocol instance.
44 @param Width Width of I/O operations.
45 @param Address The base address of I/O operations.
46 @param Count The number of I/O operations to perform. Bytes
47 moves is Width size * Count, starting at Address.
48 @param Buffer The destination buffer to store results.
49
50 @retval EFI_SUCCESS The data was read from the device.
51 @retval EFI_INVALID_PARAMETER Width is invalid.
52 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
53 resources.
54
55 **/
56 EFI_STATUS
57 EFIAPI
58 DeviceIoMemRead (
59 IN EFI_DEVICE_IO_PROTOCOL *This,
60 IN EFI_IO_WIDTH Width,
61 IN UINT64 Address,
62 IN UINTN Count,
63 IN OUT VOID *Buffer
64 );
65
66
67 /**
68 Perform writing memory mapped I/O space of device.
69
70 @param This A pointer to EFI_DEVICE_IO protocol instance.
71 @param Width Width of I/O operations.
72 @param Address The base address of I/O operations.
73 @param Count The number of I/O operations to perform. Bytes
74 moves is Width size * Count, starting at Address.
75 @param Buffer The source buffer of data to be written.
76
77 @retval EFI_SUCCESS The data was written to the device.
78 @retval EFI_INVALID_PARAMETER Width is invalid.
79 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
80 resources.
81
82 **/
83 EFI_STATUS
84 EFIAPI
85 DeviceIoMemWrite (
86 IN EFI_DEVICE_IO_PROTOCOL *This,
87 IN EFI_IO_WIDTH Width,
88 IN UINT64 Address,
89 IN UINTN Count,
90 IN OUT VOID *Buffer
91 );
92
93 /**
94 Perform reading I/O space of device.
95
96 @param This A pointer to EFI_DEVICE_IO protocol instance.
97 @param Width Width of I/O operations.
98 @param Address The base address of I/O operations.
99 @param Count The number of I/O operations to perform. Bytes
100 moves is Width size * Count, starting at Address.
101 @param Buffer The destination buffer to store results.
102
103 @retval EFI_SUCCESS The data was read from the device.
104 @retval EFI_INVALID_PARAMETER Width is invalid.
105 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
106 resources.
107
108 **/
109 EFI_STATUS
110 EFIAPI
111 DeviceIoIoRead (
112 IN EFI_DEVICE_IO_PROTOCOL *This,
113 IN EFI_IO_WIDTH Width,
114 IN UINT64 Address,
115 IN UINTN Count,
116 IN OUT VOID *Buffer
117 );
118
119 /**
120 Perform writing I/O space of device.
121
122 @param This A pointer to EFI_DEVICE_IO protocol instance.
123 @param Width Width of I/O operations.
124 @param Address The base address of I/O operations.
125 @param Count The number of I/O operations to perform. Bytes
126 moves is Width size * Count, starting at Address.
127 @param Buffer The source buffer of data to be written.
128
129 @retval EFI_SUCCESS The data was written to the device.
130 @retval EFI_INVALID_PARAMETER Width is invalid.
131 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
132 resources.
133
134 **/
135 EFI_STATUS
136 EFIAPI
137 DeviceIoIoWrite (
138 IN EFI_DEVICE_IO_PROTOCOL *This,
139 IN EFI_IO_WIDTH Width,
140 IN UINT64 Address,
141 IN UINTN Count,
142 IN OUT VOID *Buffer
143 );
144
145 /**
146 Perform reading PCI configuration space of device
147
148 @param This A pointer to EFI_DEVICE_IO protocol instance.
149 @param Width Width of I/O operations.
150 @param Address The base address of I/O operations.
151 @param Count The number of I/O operations to perform. Bytes
152 moves is Width size * Count, starting at Address.
153 @param Buffer The destination buffer to store results.
154
155 @retval EFI_SUCCESS The data was read from the device.
156 @retval EFI_INVALID_PARAMETER Width is invalid.
157 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
158 resources.
159
160 **/
161 EFI_STATUS
162 EFIAPI
163 DeviceIoPciRead (
164 IN EFI_DEVICE_IO_PROTOCOL *This,
165 IN EFI_IO_WIDTH Width,
166 IN UINT64 Address,
167 IN UINTN Count,
168 IN OUT VOID *Buffer
169 );
170
171 /**
172 Perform writing PCI configuration space of device.
173
174 @param This A pointer to EFI_DEVICE_IO protocol instance.
175 @param Width Width of I/O operations.
176 @param Address The base address of I/O operations.
177 @param Count The number of I/O operations to perform. Bytes
178 moves is Width size * Count, starting at Address.
179 @param Buffer The source buffer of data to be written.
180
181 @retval EFI_SUCCESS The data was written to the device.
182 @retval EFI_INVALID_PARAMETER Width is invalid.
183 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
184 resources.
185
186 **/
187 EFI_STATUS
188 EFIAPI
189 DeviceIoPciWrite (
190 IN EFI_DEVICE_IO_PROTOCOL *This,
191 IN EFI_IO_WIDTH Width,
192 IN UINT64 Address,
193 IN UINTN Count,
194 IN OUT VOID *Buffer
195 );
196
197 /**
198 Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
199
200 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
201 @param Address The PCI configuration space address of the device
202 whose Device Path is going to be returned.
203 @param PciDevicePath A pointer to the pointer for the EFI Device Path
204 for PciAddress. Memory for the Device Path is
205 allocated from the pool.
206
207 @retval EFI_SUCCESS The PciDevicePath returns a pointer to a valid EFI
208 Device Path.
209 @retval EFI_UNSUPPORTED The PciAddress does not map to a valid EFI Device
210 Path.
211 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
212 of resources.
213
214 **/
215 EFI_STATUS
216 EFIAPI
217 DeviceIoPciDevicePath (
218 IN EFI_DEVICE_IO_PROTOCOL *This,
219 IN UINT64 Address,
220 IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
221 );
222
223 /**
224 Provides the device-specific addresses needed to access system memory.
225
226 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
227 @param Operation Indicates if the bus master is going to read or
228 write to system memory.
229 @param HostAddress The system memory address to map to the device.
230 @param NumberOfBytes On input the number of bytes to map. On output the
231 number of bytes that were mapped.
232 @param DeviceAddress The resulting map address for the bus master
233 device to use to access the hosts HostAddress.
234 @param Mapping A resulting value to pass to Unmap().
235
236 @retval EFI_SUCCESS The range was mapped for the returned
237 NumberOfBytes.
238 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
239 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
240 buffer.
241 @retval EFI_DEVICE_ERROR The system hardware could not map the requested
242 address.
243 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
244 of resources.
245
246 **/
247 EFI_STATUS
248 EFIAPI
249 DeviceIoMap (
250 IN EFI_DEVICE_IO_PROTOCOL *This,
251 IN EFI_IO_OPERATION_TYPE Operation,
252 IN EFI_PHYSICAL_ADDRESS *HostAddress,
253 IN OUT UINTN *NumberOfBytes,
254 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
255 OUT VOID **Mapping
256 );
257
258 /**
259 Completes the Map() operation and releases any corresponding resources.
260
261 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
262 @param Mapping The mapping value returned from Map().
263
264 @retval EFI_SUCCESS The range was unmapped.
265 @retval EFI_DEVICE_ERROR The data was not committed to the target system
266 memory.
267
268 **/
269 EFI_STATUS
270 EFIAPI
271 DeviceIoUnmap (
272 IN EFI_DEVICE_IO_PROTOCOL *This,
273 IN VOID *Mapping
274 );
275
276 /**
277 Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
278
279 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
280 @param Type The type allocation to perform.
281 @param MemoryType The type of memory to allocate,
282 EfiBootServicesData or EfiRuntimeServicesData.
283 @param Pages The number of pages to allocate.
284 @param PhysicalAddress A pointer to store the base address of the
285 allocated range.
286
287 @retval EFI_SUCCESS The requested memory pages were allocated.
288 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
289 @retval EFI_INVALID_PARAMETER The requested memory type is invalid.
290 @retval EFI_UNSUPPORTED The requested PhysicalAddress is not supported on
291 this platform.
292
293 **/
294 EFI_STATUS
295 EFIAPI
296 DeviceIoAllocateBuffer (
297 IN EFI_DEVICE_IO_PROTOCOL *This,
298 IN EFI_ALLOCATE_TYPE Type,
299 IN EFI_MEMORY_TYPE MemoryType,
300 IN UINTN Pages,
301 IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress
302 );
303
304 /**
305 Flushes any posted write data to the device.
306
307 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
308
309 @retval EFI_SUCCESS The buffers were flushed.
310 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware
311 error.
312
313 **/
314 EFI_STATUS
315 EFIAPI
316 DeviceIoFlush (
317 IN EFI_DEVICE_IO_PROTOCOL *This
318 );
319
320 /**
321 Frees pages that were allocated with AllocateBuffer().
322
323 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
324 @param Pages The number of pages to free.
325 @param HostAddress The base address of the range to free.
326
327 @retval EFI_SUCCESS The requested memory pages were freed.
328 @retval EFI_NOT_FOUND The requested memory pages were not allocated with
329 AllocateBuffer().
330 @retval EFI_INVALID_PARAMETER HostAddress is not page aligned or Pages is
331 invalid.
332
333 **/
334 EFI_STATUS
335 EFIAPI
336 DeviceIoFreeBuffer (
337 IN EFI_DEVICE_IO_PROTOCOL *This,
338 IN UINTN Pages,
339 IN EFI_PHYSICAL_ADDRESS HostAddress
340 );
341
342
343 #define DEVICE_IO_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('D', 'e', 'I', 'O')
344
345 typedef struct {
346 UINTN Signature;
347 EFI_DEVICE_IO_PROTOCOL DeviceIo;
348 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
349 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
350 UINT16 PrimaryBus;
351 UINT16 SubordinateBus;
352 } DEVICE_IO_PRIVATE_DATA;
353
354 #define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)
355
356 #define MAX_COMMON_BUFFER 0x00000000FFFFFFFF
357
358
359 EFI_EVENT mPciRootBridgeIoRegistration;
360
361 //
362 // Device Io Volume Protocol template
363 //
364 DEVICE_IO_PRIVATE_DATA gDeviceIoPrivateDataTemplate = {
365 DEVICE_IO_PRIVATE_DATA_SIGNATURE,
366 {
367 {
368 DeviceIoMemRead,
369 DeviceIoMemWrite
370 },
371 {
372 DeviceIoIoRead,
373 DeviceIoIoWrite
374 },
375 {
376 DeviceIoPciRead,
377 DeviceIoPciWrite,
378 },
379 DeviceIoMap,
380 DeviceIoPciDevicePath,
381 DeviceIoUnmap,
382 DeviceIoAllocateBuffer,
383 DeviceIoFlush,
384 DeviceIoFreeBuffer
385 },
386 NULL, // PciRootBridgeIo
387 NULL, // DevicePath
388 0, // PrimaryBus
389 255 // SubordinateBus
390 };
391
392 VOID
393 EFIAPI
394 PciRootBridgeIoNotificationEvent (
395 IN EFI_EVENT Event,
396 IN VOID *Context
397 )
398 {
399 EFI_STATUS Status;
400 UINTN BufferSize;
401 EFI_HANDLE Handle;
402 DEVICE_IO_PRIVATE_DATA *Private;
403 EFI_DEVICE_IO_PROTOCOL *DeviceIo;
404 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
405
406 while (TRUE) {
407 BufferSize = sizeof (Handle);
408 Status = gBS->LocateHandle (
409 ByRegisterNotify,
410 &gEfiPciRootBridgeIoProtocolGuid,
411 mPciRootBridgeIoRegistration,
412 &BufferSize,
413 &Handle
414 );
415 if (EFI_ERROR (Status)) {
416 //
417 // Exit Path of While Loop....
418 //
419 break;
420 }
421
422 //
423 // Skip this handle if the Device Io Protocol is already installed
424 //
425 Status = gBS->HandleProtocol (
426 Handle,
427 &gEfiDeviceIoProtocolGuid,
428 (VOID **)&DeviceIo
429 );
430 if (!EFI_ERROR (Status)) {
431 continue;
432 }
433
434 //
435 // Retrieve the Pci Root Bridge IO Protocol
436 //
437 Status = gBS->HandleProtocol (
438 Handle,
439 &gEfiPciRootBridgeIoProtocolGuid,
440 (VOID **)&PciRootBridgeIo
441 );
442 ASSERT_EFI_ERROR (Status);
443
444 //
445 // We only install Device IO for PCI bus in Segment 0.
446 // See the file description at @file for details.
447 //
448 if (PciRootBridgeIo->SegmentNumber != 0) {
449 continue;
450 }
451
452 //
453 // Allocate private data structure
454 //
455 Private = AllocateCopyPool (sizeof (DEVICE_IO_PRIVATE_DATA), &gDeviceIoPrivateDataTemplate);
456 if (Private == NULL) {
457 continue;
458 }
459
460 Status = gBS->HandleProtocol (
461 Handle,
462 &gEfiDevicePathProtocolGuid,
463 (VOID **) &Private->DevicePath
464 );
465
466 //
467 // Install Device Io onto same handle
468 //
469 Status = gBS->InstallMultipleProtocolInterfaces (
470 &Handle,
471 &gEfiDeviceIoProtocolGuid,
472 &Private->DeviceIo,
473 NULL
474 );
475 ASSERT_EFI_ERROR (Status);
476 }
477 }
478
479 /**
480 The user Entry Point for DXE driver. The user code starts with this function
481 as the real entry point for the image goes into a library that calls this
482 function.
483
484 @param[in] ImageHandle The firmware allocated handle for the EFI image.
485 @param[in] SystemTable A pointer to the EFI System Table.
486
487 @retval EFI_SUCCESS The entry point is executed successfully.
488 @retval other Some error occurs when executing this entry point.
489
490 **/
491 EFI_STATUS
492 EFIAPI
493 InitializeDeviceIo (
494 IN EFI_HANDLE ImageHandle,
495 IN EFI_SYSTEM_TABLE *SystemTable
496 )
497 {
498 EfiCreateProtocolNotifyEvent (
499 &gEfiPciRootBridgeIoProtocolGuid,
500 TPL_CALLBACK,
501 PciRootBridgeIoNotificationEvent,
502 NULL,
503 &mPciRootBridgeIoRegistration
504 );
505 return EFI_SUCCESS;
506 }
507
508
509 /**
510 Perform reading memory mapped I/O space of device.
511
512 @param This A pointer to EFI_DEVICE_IO protocol instance.
513 @param Width Width of I/O operations.
514 @param Address The base address of I/O operations.
515 @param Count The number of I/O operations to perform. Bytes
516 moves is Width size * Count, starting at Address.
517 @param Buffer The destination buffer to store results.
518
519 @retval EFI_SUCCESS The data was read from the device.
520 @retval EFI_INVALID_PARAMETER Width is invalid.
521 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
522 resources.
523
524 **/
525 EFI_STATUS
526 EFIAPI
527 DeviceIoMemRead (
528 IN EFI_DEVICE_IO_PROTOCOL *This,
529 IN EFI_IO_WIDTH Width,
530 IN UINT64 Address,
531 IN UINTN Count,
532 IN OUT VOID *Buffer
533 )
534 {
535 EFI_STATUS Status;
536 DEVICE_IO_PRIVATE_DATA *Private;
537
538 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
539
540 if (Width > MMIO_COPY_UINT64) {
541 return EFI_INVALID_PARAMETER;
542 }
543 if (Width >= MMIO_COPY_UINT8) {
544 Width = Width - MMIO_COPY_UINT8;
545 Status = Private->PciRootBridgeIo->CopyMem (
546 Private->PciRootBridgeIo,
547 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
548 (UINT64) (UINTN) Buffer,
549 Address,
550 Count
551 );
552 } else {
553 Status = Private->PciRootBridgeIo->Mem.Read (
554 Private->PciRootBridgeIo,
555 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
556 Address,
557 Count,
558 Buffer
559 );
560 }
561
562 return Status;
563 }
564
565
566
567
568 /**
569 Perform writing memory mapped I/O space of device.
570
571 @param This A pointer to EFI_DEVICE_IO protocol instance.
572 @param Width Width of I/O operations.
573 @param Address The base address of I/O operations.
574 @param Count The number of I/O operations to perform. Bytes
575 moves is Width size * Count, starting at Address.
576 @param Buffer The source buffer of data to be written.
577
578 @retval EFI_SUCCESS The data was written to the device.
579 @retval EFI_INVALID_PARAMETER Width is invalid.
580 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
581 resources.
582
583 **/
584 EFI_STATUS
585 EFIAPI
586 DeviceIoMemWrite (
587 IN EFI_DEVICE_IO_PROTOCOL *This,
588 IN EFI_IO_WIDTH Width,
589 IN UINT64 Address,
590 IN UINTN Count,
591 IN OUT VOID *Buffer
592 )
593 {
594 EFI_STATUS Status;
595 DEVICE_IO_PRIVATE_DATA *Private;
596
597 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
598
599 if (Width > MMIO_COPY_UINT64) {
600 return EFI_INVALID_PARAMETER;
601 }
602 if (Width >= MMIO_COPY_UINT8) {
603 Width = Width - MMIO_COPY_UINT8;
604 Status = Private->PciRootBridgeIo->CopyMem (
605 Private->PciRootBridgeIo,
606 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
607 Address,
608 (UINT64) (UINTN) Buffer,
609 Count
610 );
611 } else {
612 Status = Private->PciRootBridgeIo->Mem.Write (
613 Private->PciRootBridgeIo,
614 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
615 Address,
616 Count,
617 Buffer
618 );
619 }
620
621 return Status;
622 }
623
624
625 /**
626 Perform reading I/O space of device.
627
628 @param This A pointer to EFI_DEVICE_IO protocol instance.
629 @param Width Width of I/O operations.
630 @param Address The base address of I/O operations.
631 @param Count The number of I/O operations to perform. Bytes
632 moves is Width size * Count, starting at Address.
633 @param Buffer The destination buffer to store results.
634
635 @retval EFI_SUCCESS The data was read from the device.
636 @retval EFI_INVALID_PARAMETER Width is invalid.
637 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
638 resources.
639
640 **/
641 EFI_STATUS
642 EFIAPI
643 DeviceIoIoRead (
644 IN EFI_DEVICE_IO_PROTOCOL *This,
645 IN EFI_IO_WIDTH Width,
646 IN UINT64 Address,
647 IN UINTN Count,
648 IN OUT VOID *Buffer
649 )
650 {
651 EFI_STATUS Status;
652 DEVICE_IO_PRIVATE_DATA *Private;
653
654 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
655
656 if (Width >= MMIO_COPY_UINT8) {
657 return EFI_INVALID_PARAMETER;
658 }
659
660 Status = Private->PciRootBridgeIo->Io.Read (
661 Private->PciRootBridgeIo,
662 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
663 Address,
664 Count,
665 Buffer
666 );
667
668 return Status;
669 }
670
671
672 /**
673 Perform writing I/O space of device.
674
675 @param This A pointer to EFI_DEVICE_IO protocol instance.
676 @param Width Width of I/O operations.
677 @param Address The base address of I/O operations.
678 @param Count The number of I/O operations to perform. Bytes
679 moves is Width size * Count, starting at Address.
680 @param Buffer The source buffer of data to be written.
681
682 @retval EFI_SUCCESS The data was written to the device.
683 @retval EFI_INVALID_PARAMETER Width is invalid.
684 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
685 resources.
686
687 **/
688 EFI_STATUS
689 EFIAPI
690 DeviceIoIoWrite (
691 IN EFI_DEVICE_IO_PROTOCOL *This,
692 IN EFI_IO_WIDTH Width,
693 IN UINT64 Address,
694 IN UINTN Count,
695 IN OUT VOID *Buffer
696 )
697 {
698 EFI_STATUS Status;
699 DEVICE_IO_PRIVATE_DATA *Private;
700
701 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
702
703 if (Width >= MMIO_COPY_UINT8) {
704 return EFI_INVALID_PARAMETER;
705 }
706
707 Status = Private->PciRootBridgeIo->Io.Write (
708 Private->PciRootBridgeIo,
709 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
710 Address,
711 Count,
712 Buffer
713 );
714
715 return Status;
716 }
717
718
719 /**
720 Perform reading PCI configuration space of device
721
722 @param This A pointer to EFI_DEVICE_IO protocol instance.
723 @param Width Width of I/O operations.
724 @param Address The base address of I/O operations.
725 @param Count The number of I/O operations to perform. Bytes
726 moves is Width size * Count, starting at Address.
727 @param Buffer The destination buffer to store results.
728
729 @retval EFI_SUCCESS The data was read from the device.
730 @retval EFI_INVALID_PARAMETER Width is invalid.
731 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
732 resources.
733
734 **/
735 EFI_STATUS
736 EFIAPI
737 DeviceIoPciRead (
738 IN EFI_DEVICE_IO_PROTOCOL *This,
739 IN EFI_IO_WIDTH Width,
740 IN UINT64 Address,
741 IN UINTN Count,
742 IN OUT VOID *Buffer
743 )
744 {
745 EFI_STATUS Status;
746 DEVICE_IO_PRIVATE_DATA *Private;
747
748 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
749
750 if (Width < 0 || Width >= MMIO_COPY_UINT8) {
751 return EFI_INVALID_PARAMETER;
752 }
753
754 Status = Private->PciRootBridgeIo->Pci.Read (
755 Private->PciRootBridgeIo,
756 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
757 Address,
758 Count,
759 Buffer
760 );
761
762 return Status;
763 }
764
765
766 /**
767 Perform writing PCI configuration space of device.
768
769 @param This A pointer to EFI_DEVICE_IO protocol instance.
770 @param Width Width of I/O operations.
771 @param Address The base address of I/O operations.
772 @param Count The number of I/O operations to perform. Bytes
773 moves is Width size * Count, starting at Address.
774 @param Buffer The source buffer of data to be written.
775
776 @retval EFI_SUCCESS The data was written to the device.
777 @retval EFI_INVALID_PARAMETER Width is invalid.
778 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
779 resources.
780
781 **/
782 EFI_STATUS
783 EFIAPI
784 DeviceIoPciWrite (
785 IN EFI_DEVICE_IO_PROTOCOL *This,
786 IN EFI_IO_WIDTH Width,
787 IN UINT64 Address,
788 IN UINTN Count,
789 IN OUT VOID *Buffer
790 )
791 {
792 EFI_STATUS Status;
793 DEVICE_IO_PRIVATE_DATA *Private;
794
795 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
796
797 if (Width < 0 || Width >= MMIO_COPY_UINT8) {
798 return EFI_INVALID_PARAMETER;
799 }
800
801 Status = Private->PciRootBridgeIo->Pci.Write (
802 Private->PciRootBridgeIo,
803 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
804 Address,
805 Count,
806 Buffer
807 );
808
809 return Status;
810 }
811
812
813 /**
814 Append a PCI device path node to another device path.
815
816 @param Private A pointer to DEVICE_IO_PRIVATE_DATA instance.
817 @param Bus PCI bus number of the device.
818 @param Device PCI device number of the device.
819 @param Function PCI function number of the device.
820 @param DevicePath Original device path which will be appended a PCI
821 device path node.
822 @param BridgePrimaryBus Primary bus number of the bridge.
823 @param BridgeSubordinateBus Subordinate bus number of the bridge.
824
825 @return Pointer to the appended PCI device path.
826
827 **/
828 EFI_DEVICE_PATH_PROTOCOL *
829 AppendPciDevicePath (
830 IN DEVICE_IO_PRIVATE_DATA *Private,
831 IN UINT8 Bus,
832 IN UINT8 Device,
833 IN UINT8 Function,
834 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
835 IN OUT UINT16 *BridgePrimaryBus,
836 IN OUT UINT16 *BridgeSubordinateBus
837 )
838 {
839 UINT16 ThisBus;
840 UINT8 ThisDevice;
841 UINT8 ThisFunc;
842 UINT64 Address;
843 PCI_TYPE01 PciBridge;
844 PCI_TYPE01 *PciPtr;
845 EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
846 PCI_DEVICE_PATH PciNode;
847
848 PciPtr = &PciBridge;
849 for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
850 for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
851 for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
852 Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
853 ZeroMem (PciPtr, sizeof (PCI_TYPE01));
854 Private->DeviceIo.Pci.Read (
855 &Private->DeviceIo,
856 IO_UINT32,
857 Address,
858 1,
859 &(PciPtr->Hdr.VendorId)
860 );
861 if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
862 break;
863 }
864 if (PciPtr->Hdr.VendorId == 0xffff) {
865 continue;
866 } else {
867 Private->DeviceIo.Pci.Read (
868 &Private->DeviceIo,
869 IO_UINT32,
870 Address,
871 sizeof (PCI_TYPE01) / sizeof (UINT32),
872 PciPtr
873 );
874 if (IS_PCI_BRIDGE (PciPtr)) {
875 if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
876
877 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
878 PciNode.Header.SubType = HW_PCI_DP;
879 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
880
881 PciNode.Device = ThisDevice;
882 PciNode.Function = ThisFunc;
883 ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
884
885 *BridgePrimaryBus = PciPtr->Bridge.SecondaryBus;
886 *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
887 return ReturnDevicePath;
888 }
889 }
890 if (ThisFunc == 0 && !(PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
891 //
892 // Skip sub functions, this is not a multi function device
893 //
894 ThisFunc = 8;
895 }
896 }
897 }
898 }
899 }
900
901 ZeroMem (&PciNode, sizeof (PciNode));
902 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
903 PciNode.Header.SubType = HW_PCI_DP;
904 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
905 PciNode.Device = Device;
906 PciNode.Function = Function;
907
908 ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
909
910 *BridgePrimaryBus = 0xffff;
911 *BridgeSubordinateBus = 0xffff;
912 return ReturnDevicePath;
913 }
914
915
916 /**
917 Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
918
919 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
920 @param Address The PCI configuration space address of the device
921 whose Device Path is going to be returned.
922 @param PciDevicePath A pointer to the pointer for the EFI Device Path
923 for PciAddress. Memory for the Device Path is
924 allocated from the pool.
925
926 @retval EFI_SUCCESS The PciDevicePath returns a pointer to a valid EFI
927 Device Path.
928 @retval EFI_UNSUPPORTED The PciAddress does not map to a valid EFI Device
929 Path.
930 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
931 of resources.
932
933 **/
934 EFI_STATUS
935 EFIAPI
936 DeviceIoPciDevicePath (
937 IN EFI_DEVICE_IO_PROTOCOL *This,
938 IN UINT64 Address,
939 IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
940 )
941 {
942 DEVICE_IO_PRIVATE_DATA *Private;
943 UINT16 PrimaryBus;
944 UINT16 SubordinateBus;
945 UINT8 Bus;
946 UINT8 Device;
947 UINT8 Func;
948
949 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
950
951 Bus = (UINT8) (((UINT32) Address >> 24) & 0xff);
952 Device = (UINT8) (((UINT32) Address >> 16) & 0xff);
953 Func = (UINT8) (((UINT32) Address >> 8) & 0xff);
954
955 if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
956 return EFI_UNSUPPORTED;
957 }
958
959 *PciDevicePath = Private->DevicePath;
960 PrimaryBus = Private->PrimaryBus;
961 SubordinateBus = Private->SubordinateBus;
962 do {
963 *PciDevicePath = AppendPciDevicePath (
964 Private,
965 Bus,
966 Device,
967 Func,
968 *PciDevicePath,
969 &PrimaryBus,
970 &SubordinateBus
971 );
972 if (*PciDevicePath == NULL) {
973 return EFI_OUT_OF_RESOURCES;
974 }
975 } while (PrimaryBus != 0xffff);
976
977 return EFI_SUCCESS;
978 }
979
980
981 /**
982 Provides the device-specific addresses needed to access system memory.
983
984 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
985 @param Operation Indicates if the bus master is going to read or
986 write to system memory.
987 @param HostAddress The system memory address to map to the device.
988 @param NumberOfBytes On input the number of bytes to map. On output the
989 number of bytes that were mapped.
990 @param DeviceAddress The resulting map address for the bus master
991 device to use to access the hosts HostAddress.
992 @param Mapping A resulting value to pass to Unmap().
993
994 @retval EFI_SUCCESS The range was mapped for the returned
995 NumberOfBytes.
996 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
997 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
998 buffer.
999 @retval EFI_DEVICE_ERROR The system hardware could not map the requested
1000 address.
1001 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1002 of resources.
1003
1004 **/
1005 EFI_STATUS
1006 EFIAPI
1007 DeviceIoMap (
1008 IN EFI_DEVICE_IO_PROTOCOL *This,
1009 IN EFI_IO_OPERATION_TYPE Operation,
1010 IN EFI_PHYSICAL_ADDRESS *HostAddress,
1011 IN OUT UINTN *NumberOfBytes,
1012 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
1013 OUT VOID **Mapping
1014 )
1015 {
1016 EFI_STATUS Status;
1017 DEVICE_IO_PRIVATE_DATA *Private;
1018
1019 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
1020
1021 if (Operation < 0 || Operation > EfiBusMasterCommonBuffer) {
1022 return EFI_INVALID_PARAMETER;
1023 }
1024
1025 if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
1026 return EFI_UNSUPPORTED;
1027 }
1028
1029 Status = Private->PciRootBridgeIo->Map (
1030 Private->PciRootBridgeIo,
1031 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
1032 (VOID *) (UINTN) (*HostAddress),
1033 NumberOfBytes,
1034 DeviceAddress,
1035 Mapping
1036 );
1037
1038 return Status;
1039 }
1040
1041
1042 /**
1043 Completes the Map() operation and releases any corresponding resources.
1044
1045 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
1046 @param Mapping The mapping value returned from Map().
1047
1048 @retval EFI_SUCCESS The range was unmapped.
1049 @retval EFI_DEVICE_ERROR The data was not committed to the target system
1050 memory.
1051
1052 **/
1053 EFI_STATUS
1054 EFIAPI
1055 DeviceIoUnmap (
1056 IN EFI_DEVICE_IO_PROTOCOL *This,
1057 IN VOID *Mapping
1058 )
1059 {
1060 EFI_STATUS Status;
1061 DEVICE_IO_PRIVATE_DATA *Private;
1062
1063 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
1064
1065 Status = Private->PciRootBridgeIo->Unmap (
1066 Private->PciRootBridgeIo,
1067 Mapping
1068 );
1069
1070 return Status;
1071 }
1072
1073
1074 /**
1075 Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
1076
1077 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
1078 @param Type The type allocation to perform.
1079 @param MemoryType The type of memory to allocate,
1080 EfiBootServicesData or EfiRuntimeServicesData.
1081 @param Pages The number of pages to allocate.
1082 @param PhysicalAddress A pointer to store the base address of the
1083 allocated range.
1084
1085 @retval EFI_SUCCESS The requested memory pages were allocated.
1086 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1087 @retval EFI_INVALID_PARAMETER The requested memory type is invalid.
1088 @retval EFI_UNSUPPORTED The requested PhysicalAddress is not supported on
1089 this platform.
1090
1091 **/
1092 EFI_STATUS
1093 EFIAPI
1094 DeviceIoAllocateBuffer (
1095 IN EFI_DEVICE_IO_PROTOCOL *This,
1096 IN EFI_ALLOCATE_TYPE Type,
1097 IN EFI_MEMORY_TYPE MemoryType,
1098 IN UINTN Pages,
1099 IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress
1100 )
1101 {
1102 EFI_STATUS Status;
1103 EFI_PHYSICAL_ADDRESS HostAddress;
1104 DEVICE_IO_PRIVATE_DATA *Private;
1105 VOID *HostAddress2;
1106
1107 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
1108
1109 HostAddress = *PhysicalAddress;
1110
1111 if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
1112 return EFI_INVALID_PARAMETER;
1113 }
1114
1115 if ((Type >= MaxAllocateType) || (Type < AllocateAnyPages)) {
1116 return EFI_INVALID_PARAMETER;
1117 }
1118
1119 if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
1120 return EFI_UNSUPPORTED;
1121 }
1122
1123 if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
1124 Type = AllocateMaxAddress;
1125 HostAddress = MAX_COMMON_BUFFER;
1126 }
1127
1128 HostAddress2 = (VOID *) (UINTN) (HostAddress);
1129 Status = Private->PciRootBridgeIo->AllocateBuffer (
1130 Private->PciRootBridgeIo,
1131 Type,
1132 MemoryType,
1133 Pages,
1134 &HostAddress2,
1135 EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
1136 EFI_PCI_ATTRIBUTE_MEMORY_CACHED
1137 );
1138
1139 if (EFI_ERROR (Status)) {
1140 return Status;
1141 }
1142
1143
1144 *PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress2;
1145
1146 return EFI_SUCCESS;
1147 }
1148
1149
1150 /**
1151 Flushes any posted write data to the device.
1152
1153 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
1154
1155 @retval EFI_SUCCESS The buffers were flushed.
1156 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware
1157 error.
1158
1159 **/
1160 EFI_STATUS
1161 EFIAPI
1162 DeviceIoFlush (
1163 IN EFI_DEVICE_IO_PROTOCOL *This
1164 )
1165 {
1166 EFI_STATUS Status;
1167 DEVICE_IO_PRIVATE_DATA *Private;
1168
1169 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
1170
1171 Status = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
1172
1173 return Status;
1174 }
1175
1176
1177 /**
1178 Frees pages that were allocated with AllocateBuffer().
1179
1180 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
1181 @param Pages The number of pages to free.
1182 @param HostAddress The base address of the range to free.
1183
1184 @retval EFI_SUCCESS The requested memory pages were freed.
1185 @retval EFI_NOT_FOUND The requested memory pages were not allocated with
1186 AllocateBuffer().
1187 @retval EFI_INVALID_PARAMETER HostAddress is not page aligned or Pages is
1188 invalid.
1189
1190 **/
1191 EFI_STATUS
1192 EFIAPI
1193 DeviceIoFreeBuffer (
1194 IN EFI_DEVICE_IO_PROTOCOL *This,
1195 IN UINTN Pages,
1196 IN EFI_PHYSICAL_ADDRESS HostAddress
1197 )
1198 {
1199 DEVICE_IO_PRIVATE_DATA *Private;
1200
1201 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
1202
1203 if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
1204 return EFI_INVALID_PARAMETER;
1205 }
1206
1207 return Private->PciRootBridgeIo->FreeBuffer (
1208 Private->PciRootBridgeIo,
1209 Pages,
1210 (VOID *) (UINTN) HostAddress
1211 );
1212
1213 }
1214