]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/DeviceIoToPciRootBridgeIoThunk/DeviceIoToPciRootBridgeIoThunk.c
Correct FeatureFlagExpress PCD format based on INF spec.
[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 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 Private->PciRootBridgeIo = PciRootBridgeIo;
461
462 Status = gBS->HandleProtocol (
463 Handle,
464 &gEfiDevicePathProtocolGuid,
465 (VOID **) &Private->DevicePath
466 );
467
468 //
469 // Install Device Io onto same handle
470 //
471 Status = gBS->InstallMultipleProtocolInterfaces (
472 &Handle,
473 &gEfiDeviceIoProtocolGuid,
474 &Private->DeviceIo,
475 NULL
476 );
477 ASSERT_EFI_ERROR (Status);
478 }
479 }
480
481 /**
482 The user Entry Point for DXE driver. The user code starts with this function
483 as the real entry point for the image goes into a library that calls this
484 function.
485
486 @param[in] ImageHandle The firmware allocated handle for the EFI image.
487 @param[in] SystemTable A pointer to the EFI System Table.
488
489 @retval EFI_SUCCESS The entry point is executed successfully.
490 @retval other Some error occurs when executing this entry point.
491
492 **/
493 EFI_STATUS
494 EFIAPI
495 InitializeDeviceIo (
496 IN EFI_HANDLE ImageHandle,
497 IN EFI_SYSTEM_TABLE *SystemTable
498 )
499 {
500 EfiCreateProtocolNotifyEvent (
501 &gEfiPciRootBridgeIoProtocolGuid,
502 TPL_CALLBACK,
503 PciRootBridgeIoNotificationEvent,
504 NULL,
505 &mPciRootBridgeIoRegistration
506 );
507 return EFI_SUCCESS;
508 }
509
510
511 /**
512 Perform reading memory mapped I/O space of device.
513
514 @param This A pointer to EFI_DEVICE_IO protocol instance.
515 @param Width Width of I/O operations.
516 @param Address The base address of I/O operations.
517 @param Count The number of I/O operations to perform. Bytes
518 moves is Width size * Count, starting at Address.
519 @param Buffer The destination buffer to store results.
520
521 @retval EFI_SUCCESS The data was read from the device.
522 @retval EFI_INVALID_PARAMETER Width is invalid.
523 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
524 resources.
525
526 **/
527 EFI_STATUS
528 EFIAPI
529 DeviceIoMemRead (
530 IN EFI_DEVICE_IO_PROTOCOL *This,
531 IN EFI_IO_WIDTH Width,
532 IN UINT64 Address,
533 IN UINTN Count,
534 IN OUT VOID *Buffer
535 )
536 {
537 EFI_STATUS Status;
538 DEVICE_IO_PRIVATE_DATA *Private;
539
540 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
541
542 if (Width > MMIO_COPY_UINT64) {
543 return EFI_INVALID_PARAMETER;
544 }
545 if (Width >= MMIO_COPY_UINT8) {
546 Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
547 Status = Private->PciRootBridgeIo->CopyMem (
548 Private->PciRootBridgeIo,
549 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
550 (UINT64) (UINTN) Buffer,
551 Address,
552 Count
553 );
554 } else {
555 Status = Private->PciRootBridgeIo->Mem.Read (
556 Private->PciRootBridgeIo,
557 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
558 Address,
559 Count,
560 Buffer
561 );
562 }
563
564 return Status;
565 }
566
567
568
569
570 /**
571 Perform writing memory mapped I/O space of device.
572
573 @param This A pointer to EFI_DEVICE_IO protocol instance.
574 @param Width Width of I/O operations.
575 @param Address The base address of I/O operations.
576 @param Count The number of I/O operations to perform. Bytes
577 moves is Width size * Count, starting at Address.
578 @param Buffer The source buffer of data to be written.
579
580 @retval EFI_SUCCESS The data was written to the device.
581 @retval EFI_INVALID_PARAMETER Width is invalid.
582 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
583 resources.
584
585 **/
586 EFI_STATUS
587 EFIAPI
588 DeviceIoMemWrite (
589 IN EFI_DEVICE_IO_PROTOCOL *This,
590 IN EFI_IO_WIDTH Width,
591 IN UINT64 Address,
592 IN UINTN Count,
593 IN OUT VOID *Buffer
594 )
595 {
596 EFI_STATUS Status;
597 DEVICE_IO_PRIVATE_DATA *Private;
598
599 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
600
601 if (Width > MMIO_COPY_UINT64) {
602 return EFI_INVALID_PARAMETER;
603 }
604 if (Width >= MMIO_COPY_UINT8) {
605 Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
606 Status = Private->PciRootBridgeIo->CopyMem (
607 Private->PciRootBridgeIo,
608 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
609 Address,
610 (UINT64) (UINTN) Buffer,
611 Count
612 );
613 } else {
614 Status = Private->PciRootBridgeIo->Mem.Write (
615 Private->PciRootBridgeIo,
616 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
617 Address,
618 Count,
619 Buffer
620 );
621 }
622
623 return Status;
624 }
625
626
627 /**
628 Perform reading I/O space of device.
629
630 @param This A pointer to EFI_DEVICE_IO protocol instance.
631 @param Width Width of I/O operations.
632 @param Address The base address of I/O operations.
633 @param Count The number of I/O operations to perform. Bytes
634 moves is Width size * Count, starting at Address.
635 @param Buffer The destination buffer to store results.
636
637 @retval EFI_SUCCESS The data was read from the device.
638 @retval EFI_INVALID_PARAMETER Width is invalid.
639 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
640 resources.
641
642 **/
643 EFI_STATUS
644 EFIAPI
645 DeviceIoIoRead (
646 IN EFI_DEVICE_IO_PROTOCOL *This,
647 IN EFI_IO_WIDTH Width,
648 IN UINT64 Address,
649 IN UINTN Count,
650 IN OUT VOID *Buffer
651 )
652 {
653 EFI_STATUS Status;
654 DEVICE_IO_PRIVATE_DATA *Private;
655
656 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
657
658 if (Width >= MMIO_COPY_UINT8) {
659 return EFI_INVALID_PARAMETER;
660 }
661
662 Status = Private->PciRootBridgeIo->Io.Read (
663 Private->PciRootBridgeIo,
664 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
665 Address,
666 Count,
667 Buffer
668 );
669
670 return Status;
671 }
672
673
674 /**
675 Perform writing I/O space of device.
676
677 @param This A pointer to EFI_DEVICE_IO protocol instance.
678 @param Width Width of I/O operations.
679 @param Address The base address of I/O operations.
680 @param Count The number of I/O operations to perform. Bytes
681 moves is Width size * Count, starting at Address.
682 @param Buffer The source buffer of data to be written.
683
684 @retval EFI_SUCCESS The data was written to the device.
685 @retval EFI_INVALID_PARAMETER Width is invalid.
686 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
687 resources.
688
689 **/
690 EFI_STATUS
691 EFIAPI
692 DeviceIoIoWrite (
693 IN EFI_DEVICE_IO_PROTOCOL *This,
694 IN EFI_IO_WIDTH Width,
695 IN UINT64 Address,
696 IN UINTN Count,
697 IN OUT VOID *Buffer
698 )
699 {
700 EFI_STATUS Status;
701 DEVICE_IO_PRIVATE_DATA *Private;
702
703 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
704
705 if (Width >= MMIO_COPY_UINT8) {
706 return EFI_INVALID_PARAMETER;
707 }
708
709 Status = Private->PciRootBridgeIo->Io.Write (
710 Private->PciRootBridgeIo,
711 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
712 Address,
713 Count,
714 Buffer
715 );
716
717 return Status;
718 }
719
720
721 /**
722 Perform reading PCI configuration space of device
723
724 @param This A pointer to EFI_DEVICE_IO protocol instance.
725 @param Width Width of I/O operations.
726 @param Address The base address of I/O operations.
727 @param Count The number of I/O operations to perform. Bytes
728 moves is Width size * Count, starting at Address.
729 @param Buffer The destination buffer to store results.
730
731 @retval EFI_SUCCESS The data was read from the device.
732 @retval EFI_INVALID_PARAMETER Width is invalid.
733 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
734 resources.
735
736 **/
737 EFI_STATUS
738 EFIAPI
739 DeviceIoPciRead (
740 IN EFI_DEVICE_IO_PROTOCOL *This,
741 IN EFI_IO_WIDTH Width,
742 IN UINT64 Address,
743 IN UINTN Count,
744 IN OUT VOID *Buffer
745 )
746 {
747 EFI_STATUS Status;
748 DEVICE_IO_PRIVATE_DATA *Private;
749
750 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
751
752 if (Width < 0 || Width >= MMIO_COPY_UINT8) {
753 return EFI_INVALID_PARAMETER;
754 }
755
756 Status = Private->PciRootBridgeIo->Pci.Read (
757 Private->PciRootBridgeIo,
758 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
759 Address,
760 Count,
761 Buffer
762 );
763
764 return Status;
765 }
766
767
768 /**
769 Perform writing PCI configuration space of device.
770
771 @param This A pointer to EFI_DEVICE_IO protocol instance.
772 @param Width Width of I/O operations.
773 @param Address The base address of I/O operations.
774 @param Count The number of I/O operations to perform. Bytes
775 moves is Width size * Count, starting at Address.
776 @param Buffer The source buffer of data to be written.
777
778 @retval EFI_SUCCESS The data was written to the device.
779 @retval EFI_INVALID_PARAMETER Width is invalid.
780 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of
781 resources.
782
783 **/
784 EFI_STATUS
785 EFIAPI
786 DeviceIoPciWrite (
787 IN EFI_DEVICE_IO_PROTOCOL *This,
788 IN EFI_IO_WIDTH Width,
789 IN UINT64 Address,
790 IN UINTN Count,
791 IN OUT VOID *Buffer
792 )
793 {
794 EFI_STATUS Status;
795 DEVICE_IO_PRIVATE_DATA *Private;
796
797 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
798
799 if (Width < 0 || Width >= MMIO_COPY_UINT8) {
800 return EFI_INVALID_PARAMETER;
801 }
802
803 Status = Private->PciRootBridgeIo->Pci.Write (
804 Private->PciRootBridgeIo,
805 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
806 Address,
807 Count,
808 Buffer
809 );
810
811 return Status;
812 }
813
814
815 /**
816 Append a PCI device path node to another device path.
817
818 @param Private A pointer to DEVICE_IO_PRIVATE_DATA instance.
819 @param Bus PCI bus number of the device.
820 @param Device PCI device number of the device.
821 @param Function PCI function number of the device.
822 @param DevicePath Original device path which will be appended a PCI
823 device path node.
824 @param BridgePrimaryBus Primary bus number of the bridge.
825 @param BridgeSubordinateBus Subordinate bus number of the bridge.
826
827 @return Pointer to the appended PCI device path.
828
829 **/
830 EFI_DEVICE_PATH_PROTOCOL *
831 AppendPciDevicePath (
832 IN DEVICE_IO_PRIVATE_DATA *Private,
833 IN UINT8 Bus,
834 IN UINT8 Device,
835 IN UINT8 Function,
836 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
837 IN OUT UINT16 *BridgePrimaryBus,
838 IN OUT UINT16 *BridgeSubordinateBus
839 )
840 {
841 UINT16 ThisBus;
842 UINT8 ThisDevice;
843 UINT8 ThisFunc;
844 UINT64 Address;
845 PCI_TYPE01 PciBridge;
846 PCI_TYPE01 *PciPtr;
847 EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
848 PCI_DEVICE_PATH PciNode;
849
850 PciPtr = &PciBridge;
851 for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
852 for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
853 for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
854 Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
855 ZeroMem (PciPtr, sizeof (PCI_TYPE01));
856 Private->DeviceIo.Pci.Read (
857 &Private->DeviceIo,
858 IO_UINT32,
859 Address,
860 1,
861 &(PciPtr->Hdr.VendorId)
862 );
863 if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
864 break;
865 }
866 if (PciPtr->Hdr.VendorId == 0xffff) {
867 continue;
868 } else {
869 Private->DeviceIo.Pci.Read (
870 &Private->DeviceIo,
871 IO_UINT32,
872 Address,
873 sizeof (PCI_TYPE01) / sizeof (UINT32),
874 PciPtr
875 );
876 if (IS_PCI_BRIDGE (PciPtr)) {
877 if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
878
879 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
880 PciNode.Header.SubType = HW_PCI_DP;
881 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
882
883 PciNode.Device = ThisDevice;
884 PciNode.Function = ThisFunc;
885 ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
886
887 *BridgePrimaryBus = PciPtr->Bridge.SecondaryBus;
888 *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
889 return ReturnDevicePath;
890 }
891 }
892 if (ThisFunc == 0 && !(PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
893 //
894 // Skip sub functions, this is not a multi function device
895 //
896 ThisFunc = 8;
897 }
898 }
899 }
900 }
901 }
902
903 ZeroMem (&PciNode, sizeof (PciNode));
904 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
905 PciNode.Header.SubType = HW_PCI_DP;
906 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
907 PciNode.Device = Device;
908 PciNode.Function = Function;
909
910 ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
911
912 *BridgePrimaryBus = 0xffff;
913 *BridgeSubordinateBus = 0xffff;
914 return ReturnDevicePath;
915 }
916
917
918 /**
919 Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
920
921 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
922 @param Address The PCI configuration space address of the device
923 whose Device Path is going to be returned.
924 @param PciDevicePath A pointer to the pointer for the EFI Device Path
925 for PciAddress. Memory for the Device Path is
926 allocated from the pool.
927
928 @retval EFI_SUCCESS The PciDevicePath returns a pointer to a valid EFI
929 Device Path.
930 @retval EFI_UNSUPPORTED The PciAddress does not map to a valid EFI Device
931 Path.
932 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
933 of resources.
934
935 **/
936 EFI_STATUS
937 EFIAPI
938 DeviceIoPciDevicePath (
939 IN EFI_DEVICE_IO_PROTOCOL *This,
940 IN UINT64 Address,
941 IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
942 )
943 {
944 DEVICE_IO_PRIVATE_DATA *Private;
945 UINT16 PrimaryBus;
946 UINT16 SubordinateBus;
947 UINT8 Bus;
948 UINT8 Device;
949 UINT8 Func;
950
951 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
952
953 Bus = (UINT8) (((UINT32) Address >> 24) & 0xff);
954 Device = (UINT8) (((UINT32) Address >> 16) & 0xff);
955 Func = (UINT8) (((UINT32) Address >> 8) & 0xff);
956
957 if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
958 return EFI_UNSUPPORTED;
959 }
960
961 *PciDevicePath = Private->DevicePath;
962 PrimaryBus = Private->PrimaryBus;
963 SubordinateBus = Private->SubordinateBus;
964 do {
965 *PciDevicePath = AppendPciDevicePath (
966 Private,
967 Bus,
968 Device,
969 Func,
970 *PciDevicePath,
971 &PrimaryBus,
972 &SubordinateBus
973 );
974 if (*PciDevicePath == NULL) {
975 return EFI_OUT_OF_RESOURCES;
976 }
977 } while (PrimaryBus != 0xffff);
978
979 return EFI_SUCCESS;
980 }
981
982
983 /**
984 Provides the device-specific addresses needed to access system memory.
985
986 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
987 @param Operation Indicates if the bus master is going to read or
988 write to system memory.
989 @param HostAddress The system memory address to map to the device.
990 @param NumberOfBytes On input the number of bytes to map. On output the
991 number of bytes that were mapped.
992 @param DeviceAddress The resulting map address for the bus master
993 device to use to access the hosts HostAddress.
994 @param Mapping A resulting value to pass to Unmap().
995
996 @retval EFI_SUCCESS The range was mapped for the returned
997 NumberOfBytes.
998 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.
999 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
1000 buffer.
1001 @retval EFI_DEVICE_ERROR The system hardware could not map the requested
1002 address.
1003 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1004 of resources.
1005
1006 **/
1007 EFI_STATUS
1008 EFIAPI
1009 DeviceIoMap (
1010 IN EFI_DEVICE_IO_PROTOCOL *This,
1011 IN EFI_IO_OPERATION_TYPE Operation,
1012 IN EFI_PHYSICAL_ADDRESS *HostAddress,
1013 IN OUT UINTN *NumberOfBytes,
1014 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
1015 OUT VOID **Mapping
1016 )
1017 {
1018 EFI_STATUS Status;
1019 DEVICE_IO_PRIVATE_DATA *Private;
1020
1021 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
1022
1023 if (Operation < 0 || Operation > EfiBusMasterCommonBuffer) {
1024 return EFI_INVALID_PARAMETER;
1025 }
1026
1027 if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
1028 return EFI_UNSUPPORTED;
1029 }
1030
1031 Status = Private->PciRootBridgeIo->Map (
1032 Private->PciRootBridgeIo,
1033 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
1034 (VOID *) (UINTN) (*HostAddress),
1035 NumberOfBytes,
1036 DeviceAddress,
1037 Mapping
1038 );
1039
1040 return Status;
1041 }
1042
1043
1044 /**
1045 Completes the Map() operation and releases any corresponding resources.
1046
1047 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
1048 @param Mapping The mapping value returned from Map().
1049
1050 @retval EFI_SUCCESS The range was unmapped.
1051 @retval EFI_DEVICE_ERROR The data was not committed to the target system
1052 memory.
1053
1054 **/
1055 EFI_STATUS
1056 EFIAPI
1057 DeviceIoUnmap (
1058 IN EFI_DEVICE_IO_PROTOCOL *This,
1059 IN VOID *Mapping
1060 )
1061 {
1062 EFI_STATUS Status;
1063 DEVICE_IO_PRIVATE_DATA *Private;
1064
1065 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
1066
1067 Status = Private->PciRootBridgeIo->Unmap (
1068 Private->PciRootBridgeIo,
1069 Mapping
1070 );
1071
1072 return Status;
1073 }
1074
1075
1076 /**
1077 Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
1078
1079 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
1080 @param Type The type allocation to perform.
1081 @param MemoryType The type of memory to allocate,
1082 EfiBootServicesData or EfiRuntimeServicesData.
1083 @param Pages The number of pages to allocate.
1084 @param PhysicalAddress A pointer to store the base address of the
1085 allocated range.
1086
1087 @retval EFI_SUCCESS The requested memory pages were allocated.
1088 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1089 @retval EFI_INVALID_PARAMETER The requested memory type is invalid.
1090 @retval EFI_UNSUPPORTED The requested PhysicalAddress is not supported on
1091 this platform.
1092
1093 **/
1094 EFI_STATUS
1095 EFIAPI
1096 DeviceIoAllocateBuffer (
1097 IN EFI_DEVICE_IO_PROTOCOL *This,
1098 IN EFI_ALLOCATE_TYPE Type,
1099 IN EFI_MEMORY_TYPE MemoryType,
1100 IN UINTN Pages,
1101 IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress
1102 )
1103 {
1104 EFI_STATUS Status;
1105 EFI_PHYSICAL_ADDRESS HostAddress;
1106 DEVICE_IO_PRIVATE_DATA *Private;
1107 VOID *HostAddress2;
1108
1109 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
1110
1111 HostAddress = *PhysicalAddress;
1112
1113 if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
1114 return EFI_INVALID_PARAMETER;
1115 }
1116
1117 if ((Type >= MaxAllocateType) || (Type < AllocateAnyPages)) {
1118 return EFI_INVALID_PARAMETER;
1119 }
1120
1121 if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
1122 return EFI_UNSUPPORTED;
1123 }
1124
1125 if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
1126 Type = AllocateMaxAddress;
1127 HostAddress = MAX_COMMON_BUFFER;
1128 }
1129
1130 HostAddress2 = (VOID *) (UINTN) (HostAddress);
1131 Status = Private->PciRootBridgeIo->AllocateBuffer (
1132 Private->PciRootBridgeIo,
1133 Type,
1134 MemoryType,
1135 Pages,
1136 &HostAddress2,
1137 EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
1138 EFI_PCI_ATTRIBUTE_MEMORY_CACHED
1139 );
1140
1141 if (EFI_ERROR (Status)) {
1142 return Status;
1143 }
1144
1145
1146 *PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress2;
1147
1148 return EFI_SUCCESS;
1149 }
1150
1151
1152 /**
1153 Flushes any posted write data to the device.
1154
1155 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
1156
1157 @retval EFI_SUCCESS The buffers were flushed.
1158 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware
1159 error.
1160
1161 **/
1162 EFI_STATUS
1163 EFIAPI
1164 DeviceIoFlush (
1165 IN EFI_DEVICE_IO_PROTOCOL *This
1166 )
1167 {
1168 EFI_STATUS Status;
1169 DEVICE_IO_PRIVATE_DATA *Private;
1170
1171 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
1172
1173 Status = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
1174
1175 return Status;
1176 }
1177
1178
1179 /**
1180 Frees pages that were allocated with AllocateBuffer().
1181
1182 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.
1183 @param Pages The number of pages to free.
1184 @param HostAddress The base address of the range to free.
1185
1186 @retval EFI_SUCCESS The requested memory pages were freed.
1187 @retval EFI_NOT_FOUND The requested memory pages were not allocated with
1188 AllocateBuffer().
1189 @retval EFI_INVALID_PARAMETER HostAddress is not page aligned or Pages is
1190 invalid.
1191
1192 **/
1193 EFI_STATUS
1194 EFIAPI
1195 DeviceIoFreeBuffer (
1196 IN EFI_DEVICE_IO_PROTOCOL *This,
1197 IN UINTN Pages,
1198 IN EFI_PHYSICAL_ADDRESS HostAddress
1199 )
1200 {
1201 DEVICE_IO_PRIVATE_DATA *Private;
1202
1203 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
1204
1205 if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
1206 return EFI_INVALID_PARAMETER;
1207 }
1208
1209 return Private->PciRootBridgeIo->FreeBuffer (
1210 Private->PciRootBridgeIo,
1211 Pages,
1212 (VOID *) (UINTN) HostAddress
1213 );
1214
1215 }
1216