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