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