]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciIo.c
Loaded Image device paths for EFI Drivers loaded from PCI Option ROM
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciIo.c
1 /** @file
2 Implement all interfaces for EFI_PCI_IO_PROTOCOL.
3
4 Copyright (c) 2006 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include "PciBus.h"
17
18 //
19 // Internal use only
20 //
21 /**
22 report a error Status code of PCI bus driver controller.
23
24 @param PciIoDevice Pci device instance.
25 @param Code status code.
26 **/
27 EFI_STATUS
28 ReportErrorStatusCode (
29 IN PCI_IO_DEVICE *PciIoDevice,
30 IN EFI_STATUS_CODE_VALUE Code
31 );
32
33 //
34 // PCI I/O Support Function Prototypes
35 //
36 //
37 //
38 // Pci Io Protocol Interface
39 //
40 EFI_PCI_IO_PROTOCOL PciIoInterface = {
41 PciIoPollMem,
42 PciIoPollIo,
43 {
44 PciIoMemRead,
45 PciIoMemWrite
46 },
47 {
48 PciIoIoRead,
49 PciIoIoWrite
50 },
51 {
52 PciIoConfigRead,
53 PciIoConfigWrite
54 },
55 PciIoCopyMem,
56 PciIoMap,
57 PciIoUnmap,
58 PciIoAllocateBuffer,
59 PciIoFreeBuffer,
60 PciIoFlush,
61 PciIoGetLocation,
62 PciIoAttributes,
63 PciIoGetBarAttributes,
64 PciIoSetBarAttributes,
65 0,
66 NULL
67 };
68
69 /**
70 report a error Status code of PCI bus driver controller.
71
72 @param PciIoDevice Pci device instance.
73 @param Code status code.
74 **/
75 EFI_STATUS
76 ReportErrorStatusCode (
77 IN PCI_IO_DEVICE *PciIoDevice,
78 IN EFI_STATUS_CODE_VALUE Code
79 )
80 {
81 return REPORT_STATUS_CODE_WITH_DEVICE_PATH (
82 EFI_ERROR_CODE | EFI_ERROR_MINOR,
83 Code,
84 PciIoDevice->DevicePath
85 );
86 }
87
88 /**
89 Initializes a PCI I/O Instance.
90
91 @param PciIoDevice Pci device instance.
92
93 **/
94 VOID
95 InitializePciIoInstance (
96 PCI_IO_DEVICE *PciIoDevice
97 )
98 {
99 CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));
100 }
101
102 /**
103 Verifies access to a PCI Base Address Register (BAR)
104
105 @param PciIoDevice Pci device instance
106 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
107 base address for the memory or I/O operation to perform.
108 @param Type Operation type could be memory or I/O
109 @param Width Signifies the width of the memory or I/O operations.
110 @param Count The number of memory or I/O operations to perform.
111 @param Offset The offset within the PCI configuration space for the PCI controller.
112
113 @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.
114 @retval EFI_SUCCESS Success Operation.
115 **/
116 EFI_STATUS
117 PciIoVerifyBarAccess (
118 PCI_IO_DEVICE *PciIoDevice,
119 UINT8 BarIndex,
120 PCI_BAR_TYPE Type,
121 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
122 IN UINTN Count,
123 UINT64 *Offset
124 )
125 {
126 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
127 return EFI_INVALID_PARAMETER;
128 }
129
130 if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {
131 return EFI_SUCCESS;
132 }
133
134 //
135 // BarIndex 0-5 is legal
136 //
137 if (BarIndex >= PCI_MAX_BAR) {
138 return EFI_INVALID_PARAMETER;
139 }
140
141 if (!CheckBarType (PciIoDevice, BarIndex, Type)) {
142 return EFI_INVALID_PARAMETER;
143 }
144
145 //
146 // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
147 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
148 //
149 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
150 Count = 1;
151 }
152
153 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
154
155 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {
156 return EFI_INVALID_PARAMETER;
157 }
158
159 *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;
160
161 return EFI_SUCCESS;
162 }
163
164 /**
165 Verifies access to a PCI Config Header
166
167 @param PciIoDevice Pci device instance
168 @param Width Signifies the width of the memory or I/O operations.
169 @param Count The number of memory or I/O operations to perform.
170 @param Offset The offset within the PCI configuration space for the PCI controller.
171
172 @retval EFI_INVALID_PARAMETER Invalid Width
173 @retval EFI_UNSUPPORTED Offset overflow
174 @retval EFI_SUCCESS Success operation
175 **/
176 EFI_STATUS
177 PciIoVerifyConfigAccess (
178 PCI_IO_DEVICE *PciIoDevice,
179 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
180 IN UINTN Count,
181 IN UINT64 *Offset
182 )
183 {
184 UINT64 ExtendOffset;
185
186 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
187 return EFI_INVALID_PARAMETER;
188 }
189
190 //
191 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
192 //
193 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
194
195 if (PciIoDevice->IsPciExp) {
196 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {
197 return EFI_UNSUPPORTED;
198 }
199
200 ExtendOffset = LShiftU64 (*Offset, 32);
201 *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
202 *Offset = (*Offset) | ExtendOffset;
203
204 } else {
205 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {
206 return EFI_UNSUPPORTED;
207 }
208
209 *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);
210 }
211
212 return EFI_SUCCESS;
213 }
214
215 /**
216 Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
217 satisfied or after a defined duration.
218
219 @param This Pointer to protocol instance of EFI_PCI_IO_PROTOCOL
220 @param Width Signifies the width of the memory or I/O operations.
221 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
222 base address for the memory or I/O operation to perform.
223 @param Offset The offset within the PCI configuration space for the PCI controller.
224 @param Mask Mask used for the polling criteria.
225 @param Value The comparison value used for the polling exit criteria.
226 @param Delay The number of 100 ns units to poll.
227 @param Result Pointer to the last value read from the memory location.
228
229 @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
230 @retval EFI_TIMEOUT Delay expired before a match occurred.
231 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
232 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
233 **/
234 EFI_STATUS
235 EFIAPI
236 PciIoPollMem (
237 IN EFI_PCI_IO_PROTOCOL *This,
238 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
239 IN UINT8 BarIndex,
240 IN UINT64 Offset,
241 IN UINT64 Mask,
242 IN UINT64 Value,
243 IN UINT64 Delay,
244 OUT UINT64 *Result
245 )
246 {
247 EFI_STATUS Status;
248 PCI_IO_DEVICE *PciIoDevice;
249
250 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
251
252 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
253 return EFI_INVALID_PARAMETER;
254 }
255
256 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);
257 if (EFI_ERROR (Status)) {
258 return EFI_UNSUPPORTED;
259 }
260
261 if (Width > EfiPciIoWidthUint64) {
262 return EFI_INVALID_PARAMETER;
263 }
264
265 Status = PciIoDevice->PciRootBridgeIo->PollMem (
266 PciIoDevice->PciRootBridgeIo,
267 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
268 Offset,
269 Mask,
270 Value,
271 Delay,
272 Result
273 );
274
275 if (EFI_ERROR (Status)) {
276 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
277 }
278
279 return Status;
280 }
281
282 /**
283 Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
284 satisfied or after a defined duration.
285
286 @param This A pointer to the EFI_PCI_IO_PROTOCOL.
287 @param Width Signifies the width of the memory or I/O operations.
288 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
289 base address for the memory or I/O operation to perform.
290 @param Offset The offset within the selected BAR to start the memory or I/O operation.
291 @param Mask Mask used for the polling criteria.
292 @param Value The comparison value used for the polling exit criteria.
293 @param Delay The number of 100 ns units to poll.
294 @param Result Pointer to the last value read from the memory location.
295
296 @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
297 @retval EFI_TIMEOUT Delay expired before a match occurred.
298 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
299 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
300
301 **/
302 EFI_STATUS
303 EFIAPI
304 PciIoPollIo (
305 IN EFI_PCI_IO_PROTOCOL *This,
306 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
307 IN UINT8 BarIndex,
308 IN UINT64 Offset,
309 IN UINT64 Mask,
310 IN UINT64 Value,
311 IN UINT64 Delay,
312 OUT UINT64 *Result
313 )
314 {
315 EFI_STATUS Status;
316 PCI_IO_DEVICE *PciIoDevice;
317
318 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
319
320 if (Width < 0 || Width > EfiPciIoWidthUint64) {
321 return EFI_INVALID_PARAMETER;
322 }
323
324 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);
325 if (EFI_ERROR (Status)) {
326 return EFI_UNSUPPORTED;
327 }
328
329 Status = PciIoDevice->PciRootBridgeIo->PollIo (
330 PciIoDevice->PciRootBridgeIo,
331 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
332 Offset,
333 Mask,
334 Value,
335 Delay,
336 Result
337 );
338
339 if (EFI_ERROR (Status)) {
340 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
341 }
342
343 return Status;
344 }
345
346 /**
347 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
348
349 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
350 @param Width Signifies the width of the memory or I/O operations.
351 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
352 base address for the memory or I/O operation to perform.
353 @param Offset The offset within the selected BAR to start the memory or I/O operation.
354 @param Count The number of memory or I/O operations to perform.
355 @param Buffer For read operations, the destination buffer to store the results. For write
356 operations, the source buffer to write data from.
357
358 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
359 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
360 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
361 valid for the PCI BAR specified by BarIndex.
362 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
363 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
364
365 **/
366 EFI_STATUS
367 EFIAPI
368 PciIoMemRead (
369 IN EFI_PCI_IO_PROTOCOL *This,
370 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
371 IN UINT8 BarIndex,
372 IN UINT64 Offset,
373 IN UINTN Count,
374 IN OUT VOID *Buffer
375 )
376 {
377 EFI_STATUS Status;
378 PCI_IO_DEVICE *PciIoDevice;
379
380 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
381
382 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
383 return EFI_INVALID_PARAMETER;
384 }
385
386 if (Buffer == NULL) {
387 return EFI_INVALID_PARAMETER;
388 }
389
390 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
391 if (EFI_ERROR (Status)) {
392 return EFI_UNSUPPORTED;
393 }
394
395 Status = PciIoDevice->PciRootBridgeIo->Mem.Read (
396 PciIoDevice->PciRootBridgeIo,
397 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
398 Offset,
399 Count,
400 Buffer
401 );
402
403 if (EFI_ERROR (Status)) {
404 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);
405 }
406
407 return Status;
408 }
409
410 /**
411 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
412
413 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
414 @param Width Signifies the width of the memory or I/O operations.
415 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
416 base address for the memory or I/O operation to perform.
417 @param Offset The offset within the selected BAR to start the memory or I/O operation.
418 @param Count The number of memory or I/O operations to perform.
419 @param Buffer For read operations, the destination buffer to store the results. For write
420 operations, the source buffer to write data from.
421
422 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
423 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
424 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
425 valid for the PCI BAR specified by BarIndex.
426 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
427 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
428
429 **/
430 EFI_STATUS
431 EFIAPI
432 PciIoMemWrite (
433 IN EFI_PCI_IO_PROTOCOL *This,
434 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
435 IN UINT8 BarIndex,
436 IN UINT64 Offset,
437 IN UINTN Count,
438 IN OUT VOID *Buffer
439 )
440 {
441 EFI_STATUS Status;
442 PCI_IO_DEVICE *PciIoDevice;
443
444 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
445
446 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
447 return EFI_INVALID_PARAMETER;
448 }
449
450 if (Buffer == NULL) {
451 return EFI_INVALID_PARAMETER;
452 }
453
454 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
455 if (EFI_ERROR (Status)) {
456 return EFI_UNSUPPORTED;
457 }
458
459 Status = PciIoDevice->PciRootBridgeIo->Mem.Write (
460 PciIoDevice->PciRootBridgeIo,
461 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
462 Offset,
463 Count,
464 Buffer
465 );
466
467 if (EFI_ERROR (Status)) {
468 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);
469 }
470
471 return Status;
472 }
473
474 /**
475 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
476
477 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
478 @param Width Signifies the width of the memory or I/O operations.
479 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
480 base address for the memory or I/O operation to perform.
481 @param Offset The offset within the selected BAR to start the memory or I/O operation.
482 @param Count The number of memory or I/O operations to perform.
483 @param Buffer For read operations, the destination buffer to store the results. For write
484 operations, the source buffer to write data from.
485
486 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
487 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
488 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
489 valid for the PCI BAR specified by BarIndex.
490 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
491 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
492
493 **/
494 EFI_STATUS
495 EFIAPI
496 PciIoIoRead (
497 IN EFI_PCI_IO_PROTOCOL *This,
498 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
499 IN UINT8 BarIndex,
500 IN UINT64 Offset,
501 IN UINTN Count,
502 IN OUT VOID *Buffer
503 )
504 {
505 EFI_STATUS Status;
506 PCI_IO_DEVICE *PciIoDevice;
507
508 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
509
510 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
511 return EFI_INVALID_PARAMETER;
512 }
513
514 if (Buffer == NULL) {
515 return EFI_INVALID_PARAMETER;
516 }
517
518 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
519 if (EFI_ERROR (Status)) {
520 return EFI_UNSUPPORTED;
521 }
522
523 Status = PciIoDevice->PciRootBridgeIo->Io.Read (
524 PciIoDevice->PciRootBridgeIo,
525 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
526 Offset,
527 Count,
528 Buffer
529 );
530
531 if (EFI_ERROR (Status)) {
532 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);
533 }
534
535 return Status;
536 }
537
538 /**
539 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
540
541 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
542 @param Width Signifies the width of the memory or I/O operations.
543 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
544 base address for the memory or I/O operation to perform.
545 @param Offset The offset within the selected BAR to start the memory or I/O operation.
546 @param Count The number of memory or I/O operations to perform.
547 @param Buffer For read operations, the destination buffer to store the results. For write
548 operations, the source buffer to write data from.
549
550 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
551 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
552 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
553 valid for the PCI BAR specified by BarIndex.
554 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
555 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
556
557 **/
558 EFI_STATUS
559 EFIAPI
560 PciIoIoWrite (
561 IN EFI_PCI_IO_PROTOCOL *This,
562 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
563 IN UINT8 BarIndex,
564 IN UINT64 Offset,
565 IN UINTN Count,
566 IN OUT VOID *Buffer
567 )
568 {
569 EFI_STATUS Status;
570 PCI_IO_DEVICE *PciIoDevice;
571
572 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
573
574 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
575 return EFI_INVALID_PARAMETER;
576 }
577
578 if (Buffer == NULL) {
579 return EFI_INVALID_PARAMETER;
580 }
581
582 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
583 if (EFI_ERROR (Status)) {
584 return EFI_UNSUPPORTED;
585 }
586
587 Status = PciIoDevice->PciRootBridgeIo->Io.Write (
588 PciIoDevice->PciRootBridgeIo,
589 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
590 Offset,
591 Count,
592 Buffer
593 );
594
595 if (EFI_ERROR (Status)) {
596 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);
597 }
598
599 return Status;
600 }
601
602 /**
603 Enable a PCI driver to access PCI controller registers in PCI configuration space.
604
605 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
606 @param Width Signifies the width of the memory operations.
607 @param Offset The offset within the PCI configuration space for the PCI controller.
608 @param Count The number of PCI configuration operations to perform.
609 @param Buffer For read operations, the destination buffer to store the results. For write
610 operations, the source buffer to write data from.
611
612
613 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
614 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
615 valid for the PCI configuration header of the PCI controller.
616 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
617 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
618
619 **/
620 EFI_STATUS
621 EFIAPI
622 PciIoConfigRead (
623 IN EFI_PCI_IO_PROTOCOL *This,
624 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
625 IN UINT32 Offset,
626 IN UINTN Count,
627 IN OUT VOID *Buffer
628 )
629 {
630 EFI_STATUS Status;
631 PCI_IO_DEVICE *PciIoDevice;
632 UINT64 Address;
633
634 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
635
636 Address = Offset;
637 Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
638 if (EFI_ERROR (Status)) {
639 return Status;
640 }
641
642 Status = PciIoDevice->PciRootBridgeIo->Pci.Read (
643 PciIoDevice->PciRootBridgeIo,
644 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
645 Address,
646 Count,
647 Buffer
648 );
649
650 if (EFI_ERROR (Status)) {
651 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);
652 }
653
654 return Status;
655 }
656
657 /**
658 Enable a PCI driver to access PCI controller registers in PCI configuration space.
659
660 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
661 @param Width Signifies the width of the memory operations.
662 @param Offset The offset within the PCI configuration space for the PCI controller.
663 @param Count The number of PCI configuration operations to perform.
664 @param Buffer For read operations, the destination buffer to store the results. For write
665 operations, the source buffer to write data from.
666
667
668 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
669 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
670 valid for the PCI configuration header of the PCI controller.
671 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
672 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
673
674 **/
675 EFI_STATUS
676 EFIAPI
677 PciIoConfigWrite (
678 IN EFI_PCI_IO_PROTOCOL *This,
679 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
680 IN UINT32 Offset,
681 IN UINTN Count,
682 IN OUT VOID *Buffer
683 )
684 {
685 EFI_STATUS Status;
686 PCI_IO_DEVICE *PciIoDevice;
687 UINT64 Address;
688
689 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
690
691 Address = Offset;
692 Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
693 if (EFI_ERROR (Status)) {
694 return Status;
695 }
696
697 Status = PciIoDevice->PciRootBridgeIo->Pci.Write (
698 PciIoDevice->PciRootBridgeIo,
699 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
700 Address,
701 Count,
702 Buffer
703 );
704
705 if (EFI_ERROR (Status)) {
706 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);
707 }
708
709 return Status;
710 }
711
712 /**
713 Enables a PCI driver to copy one region of PCI memory space to another region of PCI
714 memory space.
715
716 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
717 @param Width Signifies the width of the memory operations.
718 @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the
719 base address for the memory operation to perform.
720 @param DestOffset The destination offset within the BAR specified by DestBarIndex to
721 start the memory writes for the copy operation.
722 @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the
723 base address for the memory operation to perform.
724 @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start
725 the memory reads for the copy operation.
726 @param Count The number of memory operations to perform. Bytes moved is Width
727 size * Count, starting at DestOffset and SrcOffset.
728
729 @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
730 @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI controller.
731 @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI controller.
732 @retval EFI_UNSUPPORTED The address range specified by DestOffset, Width, and Count
733 is not valid for the PCI BAR specified by DestBarIndex.
734 @retval EFI_UNSUPPORTED The address range specified by SrcOffset, Width, and Count is
735 not valid for the PCI BAR specified by SrcBarIndex.
736 @retval EFI_INVALID_PARAMETER Width is invalid.
737 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
738
739 **/
740 EFI_STATUS
741 EFIAPI
742 PciIoCopyMem (
743 IN EFI_PCI_IO_PROTOCOL *This,
744 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
745 IN UINT8 DestBarIndex,
746 IN UINT64 DestOffset,
747 IN UINT8 SrcBarIndex,
748 IN UINT64 SrcOffset,
749 IN UINTN Count
750 )
751 {
752 EFI_STATUS Status;
753 PCI_IO_DEVICE *PciIoDevice;
754
755 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
756
757 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
758 return EFI_INVALID_PARAMETER;
759 }
760
761 if (Width == EfiPciIoWidthFifoUint8 ||
762 Width == EfiPciIoWidthFifoUint16 ||
763 Width == EfiPciIoWidthFifoUint32 ||
764 Width == EfiPciIoWidthFifoUint64 ||
765 Width == EfiPciIoWidthFillUint8 ||
766 Width == EfiPciIoWidthFillUint16 ||
767 Width == EfiPciIoWidthFillUint32 ||
768 Width == EfiPciIoWidthFillUint64) {
769 return EFI_INVALID_PARAMETER;
770 }
771
772 Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);
773 if (EFI_ERROR (Status)) {
774 return EFI_UNSUPPORTED;
775 }
776
777 Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);
778 if (EFI_ERROR (Status)) {
779 return EFI_UNSUPPORTED;
780 }
781
782 Status = PciIoDevice->PciRootBridgeIo->CopyMem (
783 PciIoDevice->PciRootBridgeIo,
784 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
785 DestOffset,
786 SrcOffset,
787 Count
788 );
789
790 if (EFI_ERROR (Status)) {
791 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
792 }
793
794 return Status;
795 }
796
797 /**
798 Provides the PCI controller-Cspecific addresses needed to access system memory.
799
800 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
801 @param Operation Indicates if the bus master is going to read or write to system memory.
802 @param HostAddress The system memory address to map to the PCI controller.
803 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
804 that were mapped.
805 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
806 access the hosts HostAddress.
807 @param Mapping A resulting value to pass to Unmap().
808
809 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
810 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
811 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
812 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
813 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
814
815 **/
816 EFI_STATUS
817 EFIAPI
818 PciIoMap (
819 IN EFI_PCI_IO_PROTOCOL *This,
820 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
821 IN VOID *HostAddress,
822 IN OUT UINTN *NumberOfBytes,
823 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
824 OUT VOID **Mapping
825 )
826 {
827 EFI_STATUS Status;
828 PCI_IO_DEVICE *PciIoDevice;
829
830 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
831
832 if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {
833 return EFI_INVALID_PARAMETER;
834 }
835
836 if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
837 return EFI_INVALID_PARAMETER;
838 }
839
840 if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {
841 Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);
842 }
843
844 Status = PciIoDevice->PciRootBridgeIo->Map (
845 PciIoDevice->PciRootBridgeIo,
846 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
847 HostAddress,
848 NumberOfBytes,
849 DeviceAddress,
850 Mapping
851 );
852
853 if (EFI_ERROR (Status)) {
854 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
855 }
856
857 return Status;
858 }
859
860 /**
861 Completes the Map() operation and releases any corresponding resources.
862
863 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
864 @param Mapping The mapping value returned from Map().
865
866 @retval EFI_SUCCESS The range was unmapped.
867 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
868
869 **/
870 EFI_STATUS
871 EFIAPI
872 PciIoUnmap (
873 IN EFI_PCI_IO_PROTOCOL *This,
874 IN VOID *Mapping
875 )
876 {
877 EFI_STATUS Status;
878 PCI_IO_DEVICE *PciIoDevice;
879
880 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
881
882 Status = PciIoDevice->PciRootBridgeIo->Unmap (
883 PciIoDevice->PciRootBridgeIo,
884 Mapping
885 );
886
887 if (EFI_ERROR (Status)) {
888 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
889 }
890
891 return Status;
892 }
893
894 /**
895 Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
896 mapping.
897
898 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
899 @param Type This parameter is not used and must be ignored.
900 @param MemoryType The type of memory to allocate, EfiBootServicesData or
901 EfiRuntimeServicesData.
902 @param Pages The number of pages to allocate.
903 @param HostAddress A pointer to store the base system memory address of the
904 allocated range.
905 @param Attributes The requested bit mask of attributes for the allocated range.
906
907 @retval EFI_SUCCESS The requested memory pages were allocated.
908 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
909 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
910 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
911 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
912
913 **/
914 EFI_STATUS
915 EFIAPI
916 PciIoAllocateBuffer (
917 IN EFI_PCI_IO_PROTOCOL *This,
918 IN EFI_ALLOCATE_TYPE Type,
919 IN EFI_MEMORY_TYPE MemoryType,
920 IN UINTN Pages,
921 OUT VOID **HostAddress,
922 IN UINT64 Attributes
923 )
924 {
925 EFI_STATUS Status;
926 PCI_IO_DEVICE *PciIoDevice;
927
928 if ((Attributes &
929 (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) != 0){
930 return EFI_UNSUPPORTED;
931 }
932
933 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
934
935 if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {
936 Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
937 }
938
939 Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (
940 PciIoDevice->PciRootBridgeIo,
941 Type,
942 MemoryType,
943 Pages,
944 HostAddress,
945 Attributes
946 );
947
948 if (EFI_ERROR (Status)) {
949 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
950 }
951
952 return Status;
953 }
954
955 /**
956 Frees memory that was allocated with AllocateBuffer().
957
958 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
959 @param Pages The number of pages to free.
960 @param HostAddress The base system memory address of the allocated range.
961
962 @retval EFI_SUCCESS The requested memory pages were freed.
963 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
964 was not allocated with AllocateBuffer().
965
966 **/
967 EFI_STATUS
968 EFIAPI
969 PciIoFreeBuffer (
970 IN EFI_PCI_IO_PROTOCOL *This,
971 IN UINTN Pages,
972 IN VOID *HostAddress
973 )
974 {
975 EFI_STATUS Status;
976 PCI_IO_DEVICE *PciIoDevice;
977
978 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
979
980 Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (
981 PciIoDevice->PciRootBridgeIo,
982 Pages,
983 HostAddress
984 );
985
986 if (EFI_ERROR (Status)) {
987 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
988 }
989
990 return Status;
991 }
992
993 /**
994 Flushes all PCI posted write transactions from a PCI host bridge to system memory.
995
996 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
997
998 @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
999 bridge to system memory.
1000 @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
1001 host bridge due to a hardware error.
1002
1003 **/
1004 EFI_STATUS
1005 EFIAPI
1006 PciIoFlush (
1007 IN EFI_PCI_IO_PROTOCOL *This
1008 )
1009 {
1010 EFI_STATUS Status;
1011 PCI_IO_DEVICE *PciIoDevice;
1012
1013 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1014
1015 Status = PciIoDevice->PciRootBridgeIo->Flush (
1016 PciIoDevice->PciRootBridgeIo
1017 );
1018 if (EFI_ERROR (Status)) {
1019 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
1020 }
1021
1022 return Status;
1023 }
1024
1025 /**
1026 Retrieves this PCI controller's current PCI bus number, device number, and function number.
1027
1028 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1029 @param SegmentNumber The PCI controller's current PCI segment number.
1030 @param BusNumber The PCI controller's current PCI bus number.
1031 @param DeviceNumber The PCI controller's current PCI device number.
1032 @param FunctionNumber The PCI controller's current PCI function number.
1033
1034 @retval EFI_SUCCESS The PCI controller location was returned.
1035 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1036
1037 **/
1038 EFI_STATUS
1039 EFIAPI
1040 PciIoGetLocation (
1041 IN EFI_PCI_IO_PROTOCOL *This,
1042 OUT UINTN *Segment,
1043 OUT UINTN *Bus,
1044 OUT UINTN *Device,
1045 OUT UINTN *Function
1046 )
1047 {
1048 PCI_IO_DEVICE *PciIoDevice;
1049
1050 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1051
1052 if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {
1053 return EFI_INVALID_PARAMETER;
1054 }
1055
1056 *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber;
1057 *Bus = PciIoDevice->BusNumber;
1058 *Device = PciIoDevice->DeviceNumber;
1059 *Function = PciIoDevice->FunctionNumber;
1060
1061 return EFI_SUCCESS;
1062 }
1063
1064 /**
1065 Check BAR type for PCI resource.
1066
1067 @param PciIoDevice PCI device instance
1068 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1069 base address for the memory or I/O operation to perform.
1070 @param BarType Memory or I/O
1071
1072 @return whether Pci device's bar type is same with input BarType.
1073 **/
1074 BOOLEAN
1075 CheckBarType (
1076 IN PCI_IO_DEVICE *PciIoDevice,
1077 UINT8 BarIndex,
1078 PCI_BAR_TYPE BarType
1079 )
1080 {
1081 switch (BarType) {
1082
1083 case PciBarTypeMem:
1084
1085 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 &&
1086 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&
1087 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&
1088 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) {
1089 return FALSE;
1090 }
1091
1092 return TRUE;
1093
1094 case PciBarTypeIo:
1095 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&
1096 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){
1097 return FALSE;
1098 }
1099
1100 return TRUE;
1101
1102 default:
1103 break;
1104 }
1105
1106 return FALSE;
1107 }
1108
1109 /**
1110 Set/Disable new attributes to a Root Bridge
1111
1112 @param PciIoDevice Pci device instance
1113 @param Attributes New attribute want to be set
1114 @param Operation Set or Disable
1115
1116 @retval EFI_UNSUPPORTED If root bridge does not support change attribute
1117 @retval EFI_SUCCESS Success operation.
1118 **/
1119 EFI_STATUS
1120 ModifyRootBridgeAttributes (
1121 IN PCI_IO_DEVICE *PciIoDevice,
1122 IN UINT64 Attributes,
1123 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
1124 )
1125 {
1126 UINT64 PciRootBridgeSupports;
1127 UINT64 PciRootBridgeAttributes;
1128 UINT64 NewPciRootBridgeAttributes;
1129 EFI_STATUS Status;
1130
1131 //
1132 // Get the current attributes of this PCI device's PCI Root Bridge
1133 //
1134 Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
1135 PciIoDevice->PciRootBridgeIo,
1136 &PciRootBridgeSupports,
1137 &PciRootBridgeAttributes
1138 );
1139 if (EFI_ERROR (Status)) {
1140 return EFI_UNSUPPORTED;
1141 }
1142
1143 //
1144 // Record the new attribute of the Root Bridge
1145 //
1146 if (Operation == EfiPciIoAttributeOperationEnable) {
1147 NewPciRootBridgeAttributes = PciRootBridgeAttributes | Attributes;
1148 } else {
1149 NewPciRootBridgeAttributes = PciRootBridgeAttributes & (~Attributes);
1150 }
1151
1152 //
1153 // Call the PCI Root Bridge to attempt to modify the attributes
1154 //
1155 if ((NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) != 0) {
1156
1157 Status = PciIoDevice->PciRootBridgeIo->SetAttributes (
1158 PciIoDevice->PciRootBridgeIo,
1159 NewPciRootBridgeAttributes,
1160 NULL,
1161 NULL
1162 );
1163 if (EFI_ERROR (Status)) {
1164 //
1165 // The PCI Root Bridge could not modify the attributes, so return the error.
1166 //
1167 return EFI_UNSUPPORTED;
1168 }
1169 }
1170
1171 //
1172 // Also update the attributes for this Root Bridge structure
1173 //
1174 PciIoDevice->Attributes = NewPciRootBridgeAttributes;
1175 return EFI_SUCCESS;
1176
1177 }
1178
1179 /**
1180 Check whether this device can be enable/disable to snoop
1181
1182 @param PciIoDevice Pci device instance
1183 @param Operation Enable/Disable
1184
1185 @retval EFI_UNSUPPORTED Pci device is not GFX device or not support snoop
1186 @retval EFI_SUCCESS Snoop can be supported.
1187 **/
1188 EFI_STATUS
1189 SupportPaletteSnoopAttributes (
1190 IN PCI_IO_DEVICE *PciIoDevice,
1191 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
1192 )
1193 {
1194 PCI_IO_DEVICE *Temp;
1195 UINT16 VGACommand;
1196
1197 //
1198 // Snoop attribute can be only modified by GFX
1199 //
1200 if (!IS_PCI_GFX (&PciIoDevice->Pci)) {
1201 return EFI_UNSUPPORTED;
1202 }
1203
1204 //
1205 // Get the boot VGA on the same segement
1206 //
1207 Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
1208
1209 if (Temp == NULL) {
1210 //
1211 // If there is no VGA device on the segement, set
1212 // this graphics card to decode the palette range
1213 //
1214 return EFI_SUCCESS;
1215 }
1216
1217 //
1218 // Check these two agents are on the same path
1219 //
1220 if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) {
1221 //
1222 // they are not on the same path, so snoop can be enabled or disabled
1223 //
1224 return EFI_SUCCESS;
1225 }
1226 //
1227 // Check if they are on the same bus
1228 //
1229 if (Temp->Parent == PciIoDevice->Parent) {
1230
1231 PciReadCommandRegister (Temp, &VGACommand);
1232
1233 //
1234 // If they are on the same bus, either one can
1235 // be set to snoop, the other set to decode
1236 //
1237 if ((VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
1238 //
1239 // VGA has set to snoop, so GFX can be only set to disable snoop
1240 //
1241 if (Operation == EfiPciIoAttributeOperationEnable) {
1242 return EFI_UNSUPPORTED;
1243 }
1244 } else {
1245 //
1246 // VGA has disabled to snoop, so GFX can be only enabled
1247 //
1248 if (Operation == EfiPciIoAttributeOperationDisable) {
1249 return EFI_UNSUPPORTED;
1250 }
1251 }
1252
1253 return EFI_SUCCESS;
1254 }
1255
1256 //
1257 // If they are on the same path but on the different bus
1258 // The first agent is set to snoop, the second one set to
1259 // decode
1260 //
1261
1262 if (Temp->BusNumber < PciIoDevice->BusNumber) {
1263 //
1264 // GFX should be set to decode
1265 //
1266 if (Operation == EfiPciIoAttributeOperationDisable) {
1267 PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
1268 Temp->Attributes |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
1269 } else {
1270 return EFI_UNSUPPORTED;
1271 }
1272
1273 } else {
1274 //
1275 // GFX should be set to snoop
1276 //
1277 if (Operation == EfiPciIoAttributeOperationEnable) {
1278 PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
1279 Temp->Attributes &= (~EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
1280 } else {
1281 return EFI_UNSUPPORTED;
1282 }
1283
1284 }
1285
1286 return EFI_SUCCESS;
1287 }
1288
1289 /**
1290 Performs an operation on the attributes that this PCI controller supports. The operations include
1291 getting the set of supported attributes, retrieving the current attributes, setting the current
1292 attributes, enabling attributes, and disabling attributes.
1293
1294 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1295 @param Operation The operation to perform on the attributes for this PCI controller.
1296 @param Attributes The mask of attributes that are used for Set, Enable, and Disable
1297 operations.
1298 @param Result A pointer to the result mask of attributes that are returned for the Get
1299 and Supported operations.
1300
1301 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
1302 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1303 @retval EFI_UNSUPPORTED one or more of the bits set in
1304 Attributes are not supported by this PCI controller or one of
1305 its parent bridges when Operation is Set, Enable or Disable.
1306
1307 **/
1308 EFI_STATUS
1309 EFIAPI
1310 PciIoAttributes (
1311 IN EFI_PCI_IO_PROTOCOL * This,
1312 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
1313 IN UINT64 Attributes,
1314 OUT UINT64 *Result OPTIONAL
1315 )
1316 {
1317 EFI_STATUS Status;
1318
1319 PCI_IO_DEVICE *PciIoDevice;
1320 PCI_IO_DEVICE *UpStreamBridge;
1321 PCI_IO_DEVICE *Temp;
1322
1323 UINT64 Supports;
1324 UINT64 UpStreamAttributes;
1325 UINT16 BridgeControl;
1326 UINT16 Command;
1327
1328 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1329
1330 switch (Operation) {
1331 case EfiPciIoAttributeOperationGet:
1332 if (Result == NULL) {
1333 return EFI_INVALID_PARAMETER;
1334 }
1335
1336 *Result = PciIoDevice->Attributes;
1337 return EFI_SUCCESS;
1338
1339 case EfiPciIoAttributeOperationSupported:
1340 if (Result == NULL) {
1341 return EFI_INVALID_PARAMETER;
1342 }
1343
1344 *Result = PciIoDevice->Supports;
1345 return EFI_SUCCESS;
1346
1347 case EfiPciIoAttributeOperationSet:
1348 Status = PciIoDevice->PciIo.Attributes (
1349 &(PciIoDevice->PciIo),
1350 EfiPciIoAttributeOperationEnable,
1351 Attributes,
1352 NULL
1353 );
1354 if (EFI_ERROR (Status)) {
1355 return EFI_UNSUPPORTED;
1356 }
1357
1358 Status = PciIoDevice->PciIo.Attributes (
1359 &(PciIoDevice->PciIo),
1360 EfiPciIoAttributeOperationDisable,
1361 (~Attributes) & (PciIoDevice->Supports),
1362 NULL
1363 );
1364 if (EFI_ERROR (Status)) {
1365 return EFI_UNSUPPORTED;
1366 }
1367
1368 return EFI_SUCCESS;
1369
1370 case EfiPciIoAttributeOperationEnable:
1371 case EfiPciIoAttributeOperationDisable:
1372 break;
1373
1374 default:
1375 return EFI_INVALID_PARAMETER;
1376 }
1377 //
1378 // Just a trick for ENABLE attribute
1379 // EFI_PCI_DEVICE_ENABLE is not defined in UEFI spec, which is the internal usage.
1380 // So, this logic doesn't confrom to UEFI spec, which should be removed.
1381 // But this trick logic is still kept for some binary drivers that depend on it.
1382 //
1383 if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) {
1384 Attributes &= (PciIoDevice->Supports);
1385
1386 //
1387 // Raise the EFI_P_PC_ENABLE Status code
1388 //
1389 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1390 EFI_PROGRESS_CODE,
1391 EFI_IO_BUS_PCI | EFI_P_PC_ENABLE,
1392 PciIoDevice->DevicePath
1393 );
1394 }
1395
1396 //
1397 // If no attributes can be supported, then return.
1398 // Otherwise, set the attributes that it can support.
1399 //
1400 Supports = (PciIoDevice->Supports) & Attributes;
1401 if (Supports != Attributes) {
1402 return EFI_UNSUPPORTED;
1403 }
1404
1405 //
1406 // For Root Bridge, just call RootBridgeIo to set attributes;
1407 //
1408 if (PciIoDevice->Parent == NULL) {
1409 Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation);
1410 return Status;
1411 }
1412
1413 Command = 0;
1414 BridgeControl = 0;
1415
1416 //
1417 // Check VGA and VGA16, they can not be set at the same time
1418 //
1419 if (((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) != 0 &&
1420 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16) != 0) ||
1421 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) != 0 &&
1422 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16) != 0) ||
1423 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) != 0 &&
1424 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16) != 0) ||
1425 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) != 0 &&
1426 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16) != 0) ) {
1427 return EFI_UNSUPPORTED;
1428 }
1429
1430 //
1431 // For PPB & P2C, set relevant attribute bits
1432 //
1433 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
1434
1435 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {
1436 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA;
1437 }
1438
1439 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) != 0) {
1440 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA;
1441 }
1442
1443 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {
1444 Command |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
1445 }
1446
1447 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {
1448 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA_16;
1449 }
1450
1451 } else {
1452 //
1453 // Do with the attributes on VGA
1454 // Only for VGA's legacy resource, we just can enable once.
1455 //
1456 if ((Attributes &
1457 (EFI_PCI_IO_ATTRIBUTE_VGA_IO |
1458 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 |
1459 EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY)) != 0) {
1460 //
1461 // Check if a VGA has been enabled before enabling a new one
1462 //
1463 if (Operation == EfiPciIoAttributeOperationEnable) {
1464 //
1465 // Check if there have been an active VGA device on the same segment
1466 //
1467 Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
1468 if (Temp != NULL && Temp != PciIoDevice) {
1469 //
1470 // An active VGA has been detected, so can not enable another
1471 //
1472 return EFI_UNSUPPORTED;
1473 }
1474 }
1475 }
1476
1477 //
1478 // Do with the attributes on GFX
1479 //
1480 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {
1481
1482 if (Operation == EfiPciIoAttributeOperationEnable) {
1483 //
1484 // Check if snoop can be enabled in current configuration
1485 //
1486 Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation);
1487
1488 if (EFI_ERROR (Status)) {
1489
1490 //
1491 // Enable operation is forbidden, so mask the bit in attributes
1492 // so as to keep consistent with the actual Status
1493 //
1494 // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
1495 //
1496 //
1497 //
1498 return EFI_UNSUPPORTED;
1499
1500 }
1501 }
1502
1503 //
1504 // It can be supported, so get ready to set the bit
1505 //
1506 Command |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
1507 }
1508 }
1509
1510 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {
1511 Command |= EFI_PCI_COMMAND_IO_SPACE;
1512 }
1513
1514 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) != 0) {
1515 Command |= EFI_PCI_COMMAND_MEMORY_SPACE;
1516 }
1517
1518 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) != 0) {
1519 Command |= EFI_PCI_COMMAND_BUS_MASTER;
1520 }
1521 //
1522 // The upstream bridge should be also set to revelant attribute
1523 // expect for IO, Mem and BusMaster
1524 //
1525 UpStreamAttributes = Attributes &
1526 (~(EFI_PCI_IO_ATTRIBUTE_IO |
1527 EFI_PCI_IO_ATTRIBUTE_MEMORY |
1528 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
1529 )
1530 );
1531 UpStreamBridge = PciIoDevice->Parent;
1532
1533 if (Operation == EfiPciIoAttributeOperationEnable) {
1534 //
1535 // Enable relevant attributes to command register and bridge control register
1536 //
1537 Status = PciEnableCommandRegister (PciIoDevice, Command);
1538 if (BridgeControl != 0) {
1539 Status = PciEnableBridgeControlRegister (PciIoDevice, BridgeControl);
1540 }
1541
1542 PciIoDevice->Attributes |= Attributes;
1543
1544 //
1545 // Enable attributes of the upstream bridge
1546 //
1547 Status = UpStreamBridge->PciIo.Attributes (
1548 &(UpStreamBridge->PciIo),
1549 EfiPciIoAttributeOperationEnable,
1550 UpStreamAttributes,
1551 NULL
1552 );
1553 } else {
1554
1555 //
1556 // Disable relevant attributes to command register and bridge control register
1557 //
1558 Status = PciDisableCommandRegister (PciIoDevice, Command);
1559 if (BridgeControl != 0) {
1560 Status = PciDisableBridgeControlRegister (PciIoDevice, BridgeControl);
1561 }
1562
1563 PciIoDevice->Attributes &= (~Attributes);
1564 Status = EFI_SUCCESS;
1565
1566 }
1567
1568 if (EFI_ERROR (Status)) {
1569 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
1570 }
1571
1572 return Status;
1573 }
1574
1575 /**
1576 Gets the attributes that this PCI controller supports setting on a BAR using
1577 SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
1578
1579 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1580 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1581 base address for resource range. The legal range for this field is 0..5.
1582 @param Supports A pointer to the mask of attributes that this PCI controller supports
1583 setting for this BAR with SetBarAttributes().
1584 @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current
1585 configuration of this BAR of the PCI controller.
1586
1587 @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI
1588 controller supports are returned in Supports. If Resources
1589 is not NULL, then the ACPI 2.0 resource descriptors that the PCI
1590 controller is currently using are returned in Resources.
1591 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
1592 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1593 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate
1594 Resources.
1595
1596 **/
1597 EFI_STATUS
1598 EFIAPI
1599 PciIoGetBarAttributes (
1600 IN EFI_PCI_IO_PROTOCOL * This,
1601 IN UINT8 BarIndex,
1602 OUT UINT64 *Supports, OPTIONAL
1603 OUT VOID **Resources OPTIONAL
1604 )
1605 {
1606
1607 UINT8 *Configuration;
1608 UINT8 NumConfig;
1609 PCI_IO_DEVICE *PciIoDevice;
1610 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1611 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
1612
1613 NumConfig = 0;
1614
1615 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1616
1617 if (Supports == NULL && Resources == NULL) {
1618 return EFI_INVALID_PARAMETER;
1619 }
1620
1621 if (BarIndex >= PCI_MAX_BAR) {
1622 return EFI_UNSUPPORTED;
1623 }
1624
1625 //
1626 // This driver does not support modifications to the WRITE_COMBINE or
1627 // CACHED attributes for BAR ranges.
1628 //
1629 if (Supports != NULL) {
1630 *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
1631 }
1632
1633 if (Resources != NULL) {
1634
1635 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {
1636 NumConfig = 1;
1637 }
1638
1639 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1640 if (Configuration == NULL) {
1641 return EFI_OUT_OF_RESOURCES;
1642 }
1643
1644 ZeroMem (
1645 Configuration,
1646 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
1647 );
1648
1649 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1650
1651 if (NumConfig == 1) {
1652 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1653 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1654
1655 Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;
1656 Ptr->AddrLen = PciIoDevice->PciBar[BarIndex].Length;
1657 Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;
1658
1659 switch (PciIoDevice->PciBar[BarIndex].BarType) {
1660 case PciBarTypeIo16:
1661 case PciBarTypeIo32:
1662 //
1663 // Io
1664 //
1665 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1666 break;
1667
1668 case PciBarTypeMem32:
1669 //
1670 // Mem
1671 //
1672 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1673 //
1674 // 32 bit
1675 //
1676 Ptr->AddrSpaceGranularity = 32;
1677 break;
1678
1679 case PciBarTypePMem32:
1680 //
1681 // Mem
1682 //
1683 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1684 //
1685 // prefechable
1686 //
1687 Ptr->SpecificFlag = 0x6;
1688 //
1689 // 32 bit
1690 //
1691 Ptr->AddrSpaceGranularity = 32;
1692 break;
1693
1694 case PciBarTypeMem64:
1695 //
1696 // Mem
1697 //
1698 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1699 //
1700 // 64 bit
1701 //
1702 Ptr->AddrSpaceGranularity = 64;
1703 break;
1704
1705 case PciBarTypePMem64:
1706 //
1707 // Mem
1708 //
1709 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1710 //
1711 // prefechable
1712 //
1713 Ptr->SpecificFlag = 0x6;
1714 //
1715 // 64 bit
1716 //
1717 Ptr->AddrSpaceGranularity = 64;
1718 break;
1719
1720 default:
1721 break;
1722 }
1723
1724 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1725 }
1726
1727 //
1728 // put the checksum
1729 //
1730 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);
1731 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
1732 PtrEnd->Checksum = 0;
1733
1734 *Resources = Configuration;
1735 }
1736
1737 return EFI_SUCCESS;
1738 }
1739
1740 /**
1741 Sets the attributes for a range of a BAR on a PCI controller.
1742
1743 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1744 @param Attributes The mask of attributes to set for the resource range specified by
1745 BarIndex, Offset, and Length.
1746 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1747 base address for resource range. The legal range for this field is 0..5.
1748 @param Offset A pointer to the BAR relative base address of the resource range to be
1749 modified by the attributes specified by Attributes.
1750 @param Length A pointer to the length of the resource range to be modified by the
1751 attributes specified by Attributes.
1752
1753 @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource
1754 range specified by BarIndex, Offset, and Length were
1755 set on the PCI controller, and the actual resource range is returned
1756 in Offset and Length.
1757 @retval EFI_INVALID_PARAMETER Offset or Length is NULL.
1758 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1759 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the
1760 resource range specified by BarIndex, Offset, and
1761 Length.
1762
1763 **/
1764 EFI_STATUS
1765 EFIAPI
1766 PciIoSetBarAttributes (
1767 IN EFI_PCI_IO_PROTOCOL *This,
1768 IN UINT64 Attributes,
1769 IN UINT8 BarIndex,
1770 IN OUT UINT64 *Offset,
1771 IN OUT UINT64 *Length
1772 )
1773 {
1774 EFI_STATUS Status;
1775 PCI_IO_DEVICE *PciIoDevice;
1776 UINT64 NonRelativeOffset;
1777 UINT64 Supports;
1778
1779 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1780
1781 //
1782 // Make sure Offset and Length are not NULL
1783 //
1784 if (Offset == NULL || Length == NULL) {
1785 return EFI_INVALID_PARAMETER;
1786 }
1787
1788 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {
1789 return EFI_UNSUPPORTED;
1790 }
1791 //
1792 // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
1793 // If Attributes is not 0, then return EFI_UNSUPPORTED.
1794 //
1795 Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
1796
1797 if (Attributes != (Attributes & Supports)) {
1798 return EFI_UNSUPPORTED;
1799 }
1800 //
1801 // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and
1802 // Length are valid for this PCI device.
1803 //
1804 NonRelativeOffset = *Offset;
1805 Status = PciIoVerifyBarAccess (
1806 PciIoDevice,
1807 BarIndex,
1808 PciBarTypeMem,
1809 EfiPciIoWidthUint8,
1810 (UINT32) *Length,
1811 &NonRelativeOffset
1812 );
1813 if (EFI_ERROR (Status)) {
1814 return EFI_UNSUPPORTED;
1815 }
1816
1817 return EFI_SUCCESS;
1818 }
1819
1820 /**
1821 Program parent bridge's attribute recurrently.
1822
1823 @param PciIoDevice Child Pci device instance
1824 @param Operation The operation to perform on the attributes for this PCI controller.
1825 @param Attributes The mask of attributes that are used for Set, Enable, and Disable
1826 operations.
1827
1828 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
1829 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1830 @retval EFI_UNSUPPORTED one or more of the bits set in
1831 Attributes are not supported by this PCI controller or one of
1832 its parent bridges when Operation is Set, Enable or Disable.
1833
1834 **/
1835 EFI_STATUS
1836 UpStreamBridgesAttributes (
1837 IN PCI_IO_DEVICE *PciIoDevice,
1838 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
1839 IN UINT64 Attributes
1840 )
1841 {
1842 PCI_IO_DEVICE *Parent;
1843 EFI_PCI_IO_PROTOCOL *PciIo;
1844
1845 Parent = PciIoDevice->Parent;
1846
1847 while (Parent != NULL && IS_PCI_BRIDGE (&Parent->Pci)) {
1848
1849 //
1850 // Get the PciIo Protocol
1851 //
1852 PciIo = &Parent->PciIo;
1853
1854 PciIo->Attributes (PciIo, Operation, Attributes, NULL);
1855
1856 Parent = Parent->Parent;
1857 }
1858
1859 return EFI_SUCCESS;
1860 }
1861
1862 /**
1863 Test whether two Pci device has same parent bridge.
1864
1865 @param PciDevice1 the frist pci device for testing
1866 @param PciDevice2 the second pci device for testing
1867
1868 @return whether two Pci device has same parent bridge.
1869 **/
1870 BOOLEAN
1871 PciDevicesOnTheSamePath (
1872 IN PCI_IO_DEVICE *PciDevice1,
1873 IN PCI_IO_DEVICE *PciDevice2
1874 )
1875 {
1876 BOOLEAN Existed1;
1877 BOOLEAN Existed2;
1878
1879 if (PciDevice1->Parent == PciDevice2->Parent) {
1880 return TRUE;
1881 }
1882
1883 Existed1 = PciDeviceExisted (PciDevice1->Parent, PciDevice2);
1884 Existed2 = PciDeviceExisted (PciDevice2->Parent, PciDevice1);
1885
1886 return (BOOLEAN) (Existed1 || Existed2);
1887 }
1888