]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciIo.c
5a407892b00502e3aa55138da9b70d36f21c1790
[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 //
1466 if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) {
1467 Attributes &= (PciIoDevice->Supports);
1468
1469 //
1470 // Raise the EFI_P_PC_ENABLE Status code
1471 //
1472 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1473 EFI_PROGRESS_CODE,
1474 EFI_IO_BUS_PCI | EFI_P_PC_ENABLE,
1475 PciIoDevice->DevicePath
1476 );
1477 }
1478
1479 //
1480 // If no attributes can be supported, then return.
1481 // Otherwise, set the attributes that it can support.
1482 //
1483 Supports = (PciIoDevice->Supports) & Attributes;
1484 if (Supports != Attributes) {
1485 return EFI_UNSUPPORTED;
1486 }
1487
1488 //
1489 // For Root Bridge, just call RootBridgeIo to set attributes;
1490 //
1491 if (!PciIoDevice->Parent) {
1492 Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation);
1493 return Status;
1494 }
1495
1496 Command = 0;
1497 BridgeControl = 0;
1498
1499 //
1500 // Check VGA and VGA16, they can not be set at the same time
1501 //
1502 if (((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) &&
1503 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) ||
1504 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) &&
1505 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) ||
1506 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) &&
1507 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) ||
1508 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) &&
1509 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) ) {
1510 return EFI_UNSUPPORTED;
1511 }
1512
1513 //
1514 // For PPB & P2C, set relevant attribute bits
1515 //
1516 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
1517
1518 if (Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {
1519 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA;
1520 }
1521
1522 if (Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {
1523 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA;
1524 }
1525
1526 if (Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) {
1527 Command |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
1528 }
1529
1530 if (Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {
1531 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA_16;
1532 }
1533
1534 } else {
1535 //
1536 // Do with the attributes on VGA
1537 // Only for VGA's legacy resource, we just can enable once.
1538 //
1539 if (Attributes &
1540 (EFI_PCI_IO_ATTRIBUTE_VGA_IO |
1541 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 |
1542 EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY)) {
1543 //
1544 // Check if a VGA has been enabled before enabling a new one
1545 //
1546 if (Operation == EfiPciIoAttributeOperationEnable) {
1547 //
1548 // Check if there have been an active VGA device on the same segment
1549 //
1550 Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
1551 if (Temp && Temp != PciIoDevice) {
1552 //
1553 // An active VGA has been detected, so can not enable another
1554 //
1555 return EFI_UNSUPPORTED;
1556 }
1557 }
1558 }
1559
1560 //
1561 // Do with the attributes on GFX
1562 //
1563 if (Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) {
1564
1565 if (Operation == EfiPciIoAttributeOperationEnable) {
1566 //
1567 // Check if snoop can be enabled in current configuration
1568 //
1569 Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation);
1570
1571 if (EFI_ERROR (Status)) {
1572
1573 //
1574 // Enable operation is forbidden, so mask the bit in attributes
1575 // so as to keep consistent with the actual Status
1576 //
1577 // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
1578 //
1579 //
1580 //
1581 return EFI_UNSUPPORTED;
1582
1583 }
1584 }
1585
1586 //
1587 // It can be supported, so get ready to set the bit
1588 //
1589 Command |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
1590 }
1591 }
1592
1593 if (Attributes & EFI_PCI_IO_ATTRIBUTE_IO) {
1594 Command |= EFI_PCI_COMMAND_IO_SPACE;
1595 }
1596
1597 if (Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {
1598 Command |= EFI_PCI_COMMAND_MEMORY_SPACE;
1599 }
1600
1601 if (Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {
1602 Command |= EFI_PCI_COMMAND_BUS_MASTER;
1603 }
1604 //
1605 // The upstream bridge should be also set to revelant attribute
1606 // expect for IO, Mem and BusMaster
1607 //
1608 UpStreamAttributes = Attributes &
1609 (~(EFI_PCI_IO_ATTRIBUTE_IO |
1610 EFI_PCI_IO_ATTRIBUTE_MEMORY |
1611 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
1612 )
1613 );
1614 UpStreamBridge = PciIoDevice->Parent;
1615
1616 if (Operation == EfiPciIoAttributeOperationEnable) {
1617 //
1618 // Enable relevant attributes to command register and bridge control register
1619 //
1620 Status = PciEnableCommandRegister (PciIoDevice, Command);
1621 if (BridgeControl) {
1622 Status = PciEnableBridgeControlRegister (PciIoDevice, BridgeControl);
1623 }
1624
1625 PciIoDevice->Attributes |= Attributes;
1626
1627 //
1628 // Enable attributes of the upstream bridge
1629 //
1630 Status = UpStreamBridge->PciIo.Attributes (
1631 &(UpStreamBridge->PciIo),
1632 EfiPciIoAttributeOperationEnable,
1633 UpStreamAttributes,
1634 NULL
1635 );
1636 } else {
1637
1638 //
1639 // Disable relevant attributes to command register and bridge control register
1640 //
1641 Status = PciDisableCommandRegister (PciIoDevice, Command);
1642 if (BridgeControl) {
1643 Status = PciDisableBridgeControlRegister (PciIoDevice, BridgeControl);
1644 }
1645
1646 PciIoDevice->Attributes &= (~Attributes);
1647 Status = EFI_SUCCESS;
1648
1649 }
1650
1651 if (EFI_ERROR (Status)) {
1652 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
1653 }
1654
1655 return Status;
1656 }
1657
1658 EFI_STATUS
1659 EFIAPI
1660 PciIoGetBarAttributes (
1661 IN EFI_PCI_IO_PROTOCOL * This,
1662 IN UINT8 BarIndex,
1663 OUT UINT64 *Supports, OPTIONAL
1664 OUT VOID **Resources OPTIONAL
1665 )
1666 /*++
1667
1668 Routine Description:
1669
1670
1671 Arguments:
1672
1673 Returns:
1674
1675 None
1676
1677 --*/
1678 // TODO: This - add argument and description to function comment
1679 // TODO: BarIndex - add argument and description to function comment
1680 // TODO: Supports - add argument and description to function comment
1681 // TODO: Resources - add argument and description to function comment
1682 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1683 // TODO: EFI_UNSUPPORTED - add return value to function comment
1684 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1685 // TODO: EFI_SUCCESS - add return value to function comment
1686 {
1687
1688 UINT8 *Configuration;
1689 UINT8 NumConfig;
1690 PCI_IO_DEVICE *PciIoDevice;
1691 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1692 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
1693
1694 NumConfig = 0;
1695
1696 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1697
1698 if (Supports == NULL && Resources == NULL) {
1699 return EFI_INVALID_PARAMETER;
1700 }
1701
1702 if (BarIndex >= PCI_MAX_BAR) {
1703 return EFI_UNSUPPORTED;
1704 }
1705
1706 //
1707 // This driver does not support modifications to the WRITE_COMBINE or
1708 // CACHED attributes for BAR ranges.
1709 //
1710 if (Supports != NULL) {
1711 *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
1712 }
1713
1714 if (Resources != NULL) {
1715
1716 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {
1717 NumConfig = 1;
1718 }
1719
1720 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1721 if (Configuration == NULL) {
1722 return EFI_OUT_OF_RESOURCES;
1723 }
1724
1725 ZeroMem (
1726 Configuration,
1727 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
1728 );
1729
1730 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1731
1732 if (NumConfig == 1) {
1733 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1734 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1735
1736 Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;
1737 Ptr->AddrLen = PciIoDevice->PciBar[BarIndex].Length;
1738 Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;
1739
1740 switch (PciIoDevice->PciBar[BarIndex].BarType) {
1741 case PciBarTypeIo16:
1742 case PciBarTypeIo32:
1743 //
1744 // Io
1745 //
1746 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1747 break;
1748
1749 case PciBarTypeMem32:
1750 //
1751 // Mem
1752 //
1753 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1754 //
1755 // 32 bit
1756 //
1757 Ptr->AddrSpaceGranularity = 32;
1758 break;
1759
1760 case PciBarTypePMem32:
1761 //
1762 // Mem
1763 //
1764 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1765 //
1766 // prefechable
1767 //
1768 Ptr->SpecificFlag = 0x6;
1769 //
1770 // 32 bit
1771 //
1772 Ptr->AddrSpaceGranularity = 32;
1773 break;
1774
1775 case PciBarTypeMem64:
1776 //
1777 // Mem
1778 //
1779 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1780 //
1781 // 64 bit
1782 //
1783 Ptr->AddrSpaceGranularity = 64;
1784 break;
1785
1786 case PciBarTypePMem64:
1787 //
1788 // Mem
1789 //
1790 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1791 //
1792 // prefechable
1793 //
1794 Ptr->SpecificFlag = 0x6;
1795 //
1796 // 64 bit
1797 //
1798 Ptr->AddrSpaceGranularity = 64;
1799 break;
1800
1801 default:
1802 break;
1803 }
1804
1805 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1806 }
1807
1808 //
1809 // put the checksum
1810 //
1811 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);
1812 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
1813 PtrEnd->Checksum = 0;
1814
1815 *Resources = Configuration;
1816 }
1817
1818 return EFI_SUCCESS;
1819 }
1820
1821 EFI_STATUS
1822 EFIAPI
1823 PciIoSetBarAttributes (
1824 IN EFI_PCI_IO_PROTOCOL *This,
1825 IN UINT64 Attributes,
1826 IN UINT8 BarIndex,
1827 IN OUT UINT64 *Offset,
1828 IN OUT UINT64 *Length
1829 )
1830 /*++
1831
1832 Routine Description:
1833
1834
1835 Arguments:
1836
1837 Returns:
1838
1839 None
1840
1841 --*/
1842 // TODO: This - add argument and description to function comment
1843 // TODO: Attributes - add argument and description to function comment
1844 // TODO: BarIndex - add argument and description to function comment
1845 // TODO: Offset - add argument and description to function comment
1846 // TODO: Length - add argument and description to function comment
1847 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1848 // TODO: EFI_UNSUPPORTED - add return value to function comment
1849 // TODO: EFI_UNSUPPORTED - add return value to function comment
1850 // TODO: EFI_UNSUPPORTED - add return value to function comment
1851 // TODO: EFI_SUCCESS - add return value to function comment
1852 {
1853 EFI_STATUS Status;
1854 PCI_IO_DEVICE *PciIoDevice;
1855 UINT64 NonRelativeOffset;
1856 UINT64 Supports;
1857
1858 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1859
1860 //
1861 // Make sure Offset and Length are not NULL
1862 //
1863 if (Offset == NULL || Length == NULL) {
1864 return EFI_INVALID_PARAMETER;
1865 }
1866
1867 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {
1868 return EFI_UNSUPPORTED;
1869 }
1870 //
1871 // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
1872 // If Attributes is not 0, then return EFI_UNSUPPORTED.
1873 //
1874 Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
1875
1876 if (Attributes != (Attributes & Supports)) {
1877 return EFI_UNSUPPORTED;
1878 }
1879 //
1880 // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and
1881 // Length are valid for this PCI device.
1882 //
1883 NonRelativeOffset = *Offset;
1884 Status = PciIoVerifyBarAccess (
1885 PciIoDevice,
1886 BarIndex,
1887 PciBarTypeMem,
1888 EfiPciIoWidthUint8,
1889 (UINT32) *Length,
1890 &NonRelativeOffset
1891 );
1892 if (EFI_ERROR (Status)) {
1893 return EFI_UNSUPPORTED;
1894 }
1895
1896 return EFI_SUCCESS;
1897 }
1898
1899 EFI_STATUS
1900 UpStreamBridgesAttributes (
1901 IN PCI_IO_DEVICE *PciIoDevice,
1902 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
1903 IN UINT64 Attributes
1904 )
1905 /*++
1906
1907 Routine Description:
1908
1909 Arguments:
1910
1911 Returns:
1912
1913 None
1914
1915 --*/
1916 // TODO: PciIoDevice - add argument and description to function comment
1917 // TODO: Operation - add argument and description to function comment
1918 // TODO: Attributes - add argument and description to function comment
1919 // TODO: EFI_SUCCESS - add return value to function comment
1920 {
1921 PCI_IO_DEVICE *Parent;
1922 EFI_PCI_IO_PROTOCOL *PciIo;
1923
1924 Parent = PciIoDevice->Parent;
1925
1926 while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {
1927
1928 //
1929 // Get the PciIo Protocol
1930 //
1931 PciIo = &Parent->PciIo;
1932
1933 PciIo->Attributes (PciIo, Operation, Attributes, NULL);
1934
1935 Parent = Parent->Parent;
1936 }
1937
1938 return EFI_SUCCESS;
1939 }
1940
1941 BOOLEAN
1942 PciDevicesOnTheSamePath (
1943 IN PCI_IO_DEVICE *PciDevice1,
1944 IN PCI_IO_DEVICE *PciDevice2
1945 )
1946 /*++
1947
1948 Routine Description:
1949
1950 Arguments:
1951
1952 Returns:
1953
1954 None
1955
1956 --*/
1957 // TODO: PciDevice1 - add argument and description to function comment
1958 // TODO: PciDevice2 - add argument and description to function comment
1959 {
1960 BOOLEAN Existed1;
1961 BOOLEAN Existed2;
1962
1963 if (PciDevice1->Parent == PciDevice2->Parent) {
1964 return TRUE;
1965 }
1966
1967 Existed1 = PciDeviceExisted (PciDevice1->Parent, PciDevice2);
1968 Existed2 = PciDeviceExisted (PciDevice2->Parent, PciDevice1);
1969
1970 return (BOOLEAN) (Existed1 || Existed2);
1971 }