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