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