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