1 /*++
2
3 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 PciIo.c
15
16 Abstract:
17
18 PCI I/O Abstraction Driver
19
20 Revision History
21
22 --*/
23
24 #include "PciBus.h"
25
26 //
27 // PCI I/O Support Function Prototypes
28 //
29 //
30
31 BOOLEAN
32 PciDevicesOnTheSamePath (
33 IN PCI_IO_DEVICE *PciDevice1,
34 IN PCI_IO_DEVICE *PciDevice2
35 );
36
37
38 EFI_STATUS
39 UpStreamBridgesAttributes (
40 IN PCI_IO_DEVICE *PciIoDevice,
41 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
42 IN UINT64 Attributes
43 );
44
45
46 BOOLEAN
47 CheckBarType (
48 IN PCI_IO_DEVICE *PciIoDevice,
49 UINT8 BarIndex,
50 PCI_BAR_TYPE BarType
51 );
52
53
54 EFI_STATUS
55 SetBootVGA (
56 IN PCI_IO_DEVICE *PciIoDevice
57 );
58
59 EFI_STATUS
60 DisableBootVGA (
61 IN PCI_IO_DEVICE *PciIoDevice
62 );
63
64
65 EFI_STATUS
66 PciIoVerifyBarAccess (
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
75 EFI_STATUS
76 PciIoVerifyConfigAccess (
77 PCI_IO_DEVICE *PciIoDevice,
78 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
79 IN UINTN Count,
80 IN UINT64 *Offset
81 );
82
83 EFI_STATUS
84 EFIAPI
85 PciIoPollMem (
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
96 EFI_STATUS
97 EFIAPI
98 PciIoPollIo (
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
109 EFI_STATUS
110 EFIAPI
111 PciIoMemRead (
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
120 EFI_STATUS
121 EFIAPI
122 PciIoMemWrite (
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
131 EFI_STATUS
132 EFIAPI
133 PciIoIoRead (
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
142 EFI_STATUS
143 EFIAPI
144 PciIoIoWrite (
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
153 EFI_STATUS
154 EFIAPI
155 PciIoConfigRead (
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
163 EFI_STATUS
164 EFIAPI
165 PciIoConfigWrite (
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
173 EFI_STATUS
174 EFIAPI
175 PciIoCopyMem (
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
185 EFI_STATUS
186 EFIAPI
187 PciIoMap (
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
196 EFI_STATUS
197 EFIAPI
198 PciIoUnmap (
199 IN EFI_PCI_IO_PROTOCOL *This,
200 IN VOID *Mapping
201 );
202
203 EFI_STATUS
204 EFIAPI
205 PciIoAllocateBuffer (
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
214 EFI_STATUS
215 EFIAPI
216 PciIoFreeBuffer (
217 IN EFI_PCI_IO_PROTOCOL *This,
218 IN UINTN Pages,
219 IN VOID *HostAddress
220 );
221
222 EFI_STATUS
223 EFIAPI
224 PciIoFlush (
225 IN EFI_PCI_IO_PROTOCOL *This
226 );
227
228 EFI_STATUS
229 EFIAPI
230 PciIoGetLocation (
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
238 EFI_STATUS
239 EFIAPI
240 PciIoAttributes (
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
247 EFI_STATUS
248 EFIAPI
249 PciIoGetBarAttributes(
250 IN EFI_PCI_IO_PROTOCOL *This,
251 IN UINT8 BarIndex,
252 OUT UINT64 *Supports, OPTIONAL
253 OUT VOID **Resources OPTIONAL
254 );
255
256 EFI_STATUS
257 EFIAPI
258 PciIoSetBarAttributes(
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 //
270 EFI_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
300 EFI_STATUS
InitializePciIoInstance(PCI_IO_DEVICE * PciIoDevice)301 InitializePciIoInstance (
302 PCI_IO_DEVICE *PciIoDevice
303 )
304 /*++
305
306 Routine Description:
307
308 Initializes a PCI I/O Instance
309
310 Arguments:
311
312 Returns:
313
314 None
315
316 --*/
317
318 {
319 CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));
320 return EFI_SUCCESS;
321 }
322
323 EFI_STATUS
PciIoVerifyBarAccess(PCI_IO_DEVICE * PciIoDevice,UINT8 BarIndex,PCI_BAR_TYPE Type,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINTN Count,UINT64 * Offset)324 PciIoVerifyBarAccess (
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
334 Routine Description:
335
336 Verifies access to a PCI Base Address Register (BAR)
337
338 Arguments:
339
340 Returns:
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
384 EFI_STATUS
PciIoVerifyConfigAccess(PCI_IO_DEVICE * PciIoDevice,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINTN Count,IN UINT64 * Offset)385 PciIoVerifyConfigAccess (
386 PCI_IO_DEVICE *PciIoDevice,
387 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
388 IN UINTN Count,
389 IN UINT64 *Offset
390 )
391 /*++
392
393 Routine Description:
394
395 Verifies access to a PCI Config Header
396
397 Arguments:
398
399 Returns:
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
437 EFI_STATUS
438 EFIAPI
PciIoPollMem(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINT8 BarIndex,IN UINT64 Offset,IN UINT64 Mask,IN UINT64 Value,IN UINT64 Delay,OUT UINT64 * Result)439 PciIoPollMem (
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
451 Routine Description:
452
453 Poll PCI Memmory
454
455 Arguments:
456
457 Returns:
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
493 EFI_STATUS
494 EFIAPI
PciIoPollIo(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINT8 BarIndex,IN UINT64 Offset,IN UINT64 Mask,IN UINT64 Value,IN UINT64 Delay,OUT UINT64 * Result)495 PciIoPollIo (
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
507 Routine Description:
508
509 Poll PCI IO
510
511 Arguments:
512
513 Returns:
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
546 EFI_STATUS
547 EFIAPI
PciIoMemRead(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINT8 BarIndex,IN UINT64 Offset,IN UINTN Count,IN OUT VOID * Buffer)548 PciIoMemRead (
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
558 Routine Description:
559
560 Performs a PCI Memory Read Cycle
561
562 Arguments:
563
564 Returns:
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
599 EFI_STATUS
600 EFIAPI
PciIoMemWrite(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINT8 BarIndex,IN UINT64 Offset,IN UINTN Count,IN OUT VOID * Buffer)601 PciIoMemWrite (
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
611 Routine Description:
612
613 Performs a PCI Memory Write Cycle
614
615 Arguments:
616
617 Returns:
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
652 EFI_STATUS
653 EFIAPI
PciIoIoRead(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINT8 BarIndex,IN UINT64 Offset,IN UINTN Count,IN OUT VOID * Buffer)654 PciIoIoRead (
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
664 Routine Description:
665
666 Performs a PCI I/O Read Cycle
667
668 Arguments:
669
670 Returns:
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
705 EFI_STATUS
706 EFIAPI
PciIoIoWrite(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINT8 BarIndex,IN UINT64 Offset,IN UINTN Count,IN OUT VOID * Buffer)707 PciIoIoWrite (
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
717 Routine Description:
718
719 Performs a PCI I/O Write Cycle
720
721 Arguments:
722
723 Returns:
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
758 EFI_STATUS
759 EFIAPI
PciIoConfigRead(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINT32 Offset,IN UINTN Count,IN OUT VOID * Buffer)760 PciIoConfigRead (
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
769 Routine Description:
770
771 Performs a PCI Configuration Read Cycle
772
773 Arguments:
774
775 Returns:
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
804 EFI_STATUS
805 EFIAPI
PciIoConfigWrite(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINT32 Offset,IN UINTN Count,IN OUT VOID * Buffer)806 PciIoConfigWrite (
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
815 Routine Description:
816
817 Performs a PCI Configuration Write Cycle
818
819 Arguments:
820
821 Returns:
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
850 EFI_STATUS
851 EFIAPI
PciIoCopyMem(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_WIDTH Width,IN UINT8 DestBarIndex,IN UINT64 DestOffset,IN UINT8 SrcBarIndex,IN UINT64 SrcOffset,IN UINTN Count)852 PciIoCopyMem (
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
863 Routine Description:
864
865 Copy PCI Memory
866
867 Arguments:
868
869 Returns:
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
916 EFI_STATUS
917 EFIAPI
PciIoMap(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)918 PciIoMap (
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
928 Routine Description:
929
930 Maps a memory region for DMA
931
932 Arguments:
933
934 Returns:
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
969 EFI_STATUS
970 EFIAPI
PciIoUnmap(IN EFI_PCI_IO_PROTOCOL * This,IN VOID * Mapping)971 PciIoUnmap (
972 IN EFI_PCI_IO_PROTOCOL *This,
973 IN VOID *Mapping
974 )
975 /*++
976
977 Routine Description:
978
979 Unmaps a memory region for DMA
980
981 Arguments:
982
983 Returns:
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
1002 EFI_STATUS
1003 EFIAPI
PciIoAllocateBuffer(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,OUT VOID ** HostAddress,IN UINT64 Attributes)1004 PciIoAllocateBuffer (
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
1014 Routine Description:
1015
1016 Allocates a common buffer for DMA
1017
1018 Arguments:
1019
1020 Returns:
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
1052 EFI_STATUS
1053 EFIAPI
PciIoFreeBuffer(IN EFI_PCI_IO_PROTOCOL * This,IN UINTN Pages,IN VOID * HostAddress)1054 PciIoFreeBuffer (
1055 IN EFI_PCI_IO_PROTOCOL *This,
1056 IN UINTN Pages,
1057 IN VOID *HostAddress
1058 )
1059 /*++
1060
1061 Routine Description:
1062
1063 Frees a common buffer
1064
1065 Arguments:
1066
1067 Returns:
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
1091 EFI_STATUS
1092 EFIAPI
PciIoFlush(IN EFI_PCI_IO_PROTOCOL * This)1093 PciIoFlush (
1094 IN EFI_PCI_IO_PROTOCOL *This
1095 )
1096 /*++
1097
1098 Routine Description:
1099
1100 Flushes a DMA buffer
1101
1102 Arguments:
1103
1104 Returns:
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
1135 EFI_STATUS
1136 EFIAPI
PciIoGetLocation(IN EFI_PCI_IO_PROTOCOL * This,OUT UINTN * Segment,OUT UINTN * Bus,OUT UINTN * Device,OUT UINTN * Function)1137 PciIoGetLocation (
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
1146 Routine Description:
1147
1148 Gets a PCI device's current bus number, device number, and function number.
1149
1150 Arguments:
1151
1152 Returns:
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
1174 BOOLEAN
CheckBarType(IN PCI_IO_DEVICE * PciIoDevice,UINT8 BarIndex,PCI_BAR_TYPE BarType)1175 CheckBarType (
1176 IN PCI_IO_DEVICE *PciIoDevice,
1177 UINT8 BarIndex,
1178 PCI_BAR_TYPE BarType
1179 )
1180 /*++
1181
1182 Routine Description:
1183
1184 Sets a PCI controllers attributes on a resource range
1185
1186 Arguments:
1187
1188 Returns:
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
1222 EFI_STATUS
1223 EFIAPI
PciIoAttributes(IN EFI_PCI_IO_PROTOCOL * This,IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,IN UINT64 Attributes,OUT UINT64 * Result OPTIONAL)1224 PciIoAttributes (
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
1232 Routine Description:
1233
1234
1235 Arguments:
1236
1237 Returns:
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
1582 EFI_STATUS
1583 EFIAPI
PciIoGetBarAttributes(IN EFI_PCI_IO_PROTOCOL * This,IN UINT8 BarIndex,OUT UINT64 * Supports,OPTIONAL OUT VOID ** Resources OPTIONAL)1584 PciIoGetBarAttributes (
1585 IN EFI_PCI_IO_PROTOCOL * This,
1586 IN UINT8 BarIndex,
1587 OUT UINT64 *Supports, OPTIONAL
1588 OUT VOID **Resources OPTIONAL
1589 )
1590 /*++
1591
1592 Routine Description:
1593
1594
1595 Arguments:
1596
1597 Returns:
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
1719 EFI_STATUS
1720 EFIAPI
PciIoSetBarAttributes(IN EFI_PCI_IO_PROTOCOL * This,IN UINT64 Attributes,IN UINT8 BarIndex,IN OUT UINT64 * Offset,IN OUT UINT64 * Length)1721 PciIoSetBarAttributes (
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
1730 Routine Description:
1731
1732
1733 Arguments:
1734
1735 Returns:
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
1787 EFI_STATUS
UpStreamBridgesAttributes(IN PCI_IO_DEVICE * PciIoDevice,IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,IN UINT64 Attributes)1788 UpStreamBridgesAttributes (
1789 IN PCI_IO_DEVICE *PciIoDevice,
1790 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
1791 IN UINT64 Attributes
1792 )
1793 /*++
1794
1795 Routine Description:
1796
1797 Arguments:
1798
1799 Returns:
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
1825 BOOLEAN
PciDevicesOnTheSamePath(IN PCI_IO_DEVICE * PciDevice1,IN PCI_IO_DEVICE * PciDevice2)1826 PciDevicesOnTheSamePath (
1827 IN PCI_IO_DEVICE *PciDevice1,
1828 IN PCI_IO_DEVICE *PciDevice2
1829 )
1830 /*++
1831
1832 Routine Description:
1833
1834 Arguments:
1835
1836 PciDevice1 - The pointer to the first PCI_IO_DEVICE.
1837 PciDevice2 - The pointer to the second PCI_IO_DEVICE.
1838
1839 Returns:
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 }
1853