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