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