]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciRootBridge.c
10a4575c168722d69279013a507c1c63070c39bb
[mirror_edk2.git] / ArmPlatformPkg / ArmJunoPkg / Drivers / PciHostBridgeDxe / PciRootBridge.c
1 /** @file
2 * Implementation of the PCI Root Bridge Protocol for XPress-RICH3 PCIe Root Complex
3 *
4 * Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
5 *
6 * This program and the accompanying materials
7 * are licensed and made available under the terms and conditions of the BSD License
8 * which accompanies this distribution. The full text of the license may be found at
9 * http://opensource.org/licenses/bsd-license.php
10 *
11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 *
14 **/
15
16 #include "PciHostBridge.h"
17
18 #include <Library/DevicePathLib.h>
19 #include <Library/DmaLib.h>
20
21 #define CPUIO_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->CpuIo)
22 #define METRONOME_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->Metronome)
23
24 /**
25 * PCI Root Bridge Instance Templates
26 */
27 STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH gDevicePathTemplate = {
28 {
29 { ACPI_DEVICE_PATH,
30 ACPI_DP,
31 { (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
32 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) }
33 },
34 EISA_PNP_ID (0x0A03),
35 0
36 },
37 {
38 END_DEVICE_PATH_TYPE,
39 END_ENTIRE_DEVICE_PATH_SUBTYPE,
40 { END_DEVICE_PATH_LENGTH, 0 }
41 }
42 };
43
44 STATIC CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL gIoTemplate = {
45 0,
46 PciRbPollMem,
47 PciRbPollIo,
48 {
49 PciRbMemRead,
50 PciRbMemWrite
51 },
52 {
53 PciRbIoRead,
54 PciRbIoWrite
55 },
56 {
57 PciRbPciRead,
58 PciRbPciWrite
59 },
60 PciRbCopyMem,
61 PciRbMap,
62 PciRbUnMap,
63 PciRbAllocateBuffer,
64 PciRbFreeBuffer,
65 PciRbFlush,
66 PciRbGetAttributes,
67 PciRbSetAttributes,
68 PciRbConfiguration,
69 0
70 };
71
72 typedef struct {
73 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[ResTypeMax+1];
74 EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;
75 } RESOURCE_CONFIGURATION;
76
77
78 RESOURCE_CONFIGURATION Configuration = {
79 {{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_IO , 0, 0, 0, 0, 0, 0, 0},
80 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 32, 0, 0, 0, 0},
81 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 32, 0, 0, 0, 0},
82 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 64, 0, 0, 0, 0},
83 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 64, 0, 0, 0, 0},
84 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_BUS, 0, 0, 0, 0, 255, 0, 255}},
85 {ACPI_END_TAG_DESCRIPTOR, 0}
86 };
87
88
89 EFI_STATUS
90 PciRbPollMem (
91 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
92 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
93 IN UINT64 Address,
94 IN UINT64 Mask,
95 IN UINT64 Value,
96 IN UINT64 Delay,
97 OUT UINT64 *Result
98 )
99 {
100 EFI_STATUS Status;
101 UINT64 NumberOfTicks;
102 UINT32 Remainder;
103 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
104 EFI_METRONOME_ARCH_PROTOCOL *Metronome;
105
106 PCI_TRACE ("PciRbPollMem()");
107
108 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
109 Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
110
111 if (Result == NULL) {
112 return EFI_INVALID_PARAMETER;
113 }
114
115 if (Width > EfiPciWidthUint64) {
116 return EFI_INVALID_PARAMETER;
117 }
118
119 // No matter what, always do a single poll.
120 Status = This->Mem.Read (This, Width, Address, 1, Result);
121 if (EFI_ERROR (Status)) {
122 return Status;
123 }
124 if ((*Result & Mask) == Value) {
125 return EFI_SUCCESS;
126 }
127
128 if (Delay == 0) {
129 return EFI_SUCCESS;
130 }
131
132 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder);
133 if (Remainder != 0) {
134 NumberOfTicks += 1;
135 }
136 NumberOfTicks += 1;
137
138 while (NumberOfTicks) {
139 Metronome->WaitForTick (Metronome, 1);
140
141 Status = This->Mem.Read (This, Width, Address, 1, Result);
142 if (EFI_ERROR (Status)) {
143 return Status;
144 }
145
146 if ((*Result & Mask) == Value) {
147 return EFI_SUCCESS;
148 }
149
150 NumberOfTicks -= 1;
151 }
152
153 return EFI_TIMEOUT;
154 }
155
156 EFI_STATUS
157 PciRbPollIo (
158 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
159 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
160 IN UINT64 Address,
161 IN UINT64 Mask,
162 IN UINT64 Value,
163 IN UINT64 Delay,
164 OUT UINT64 *Result
165 )
166 {
167 EFI_STATUS Status;
168 UINT64 NumberOfTicks;
169 UINT32 Remainder;
170 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
171 EFI_METRONOME_ARCH_PROTOCOL *Metronome;
172
173 PCI_TRACE ("PciRbPollIo()");
174
175 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
176 Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
177
178 if (Result == NULL) {
179 return EFI_INVALID_PARAMETER;
180 }
181
182 if (Width > EfiPciWidthUint64) {
183 return EFI_INVALID_PARAMETER;
184 }
185
186 // No matter what, always do a single poll.
187 Status = This->Io.Read (This, Width, Address, 1, Result);
188 if (EFI_ERROR (Status)) {
189 return Status;
190 }
191 if ((*Result & Mask) == Value) {
192 return EFI_SUCCESS;
193 }
194
195 if (Delay == 0) {
196 return EFI_SUCCESS;
197 }
198
199 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder);
200 if (Remainder != 0) {
201 NumberOfTicks += 1;
202 }
203 NumberOfTicks += 1;
204
205 while (NumberOfTicks) {
206 Metronome->WaitForTick (Metronome, 1);
207
208 Status = This->Io.Read (This, Width, Address, 1, Result);
209 if (EFI_ERROR (Status)) {
210 return Status;
211 }
212
213 if ((*Result & Mask) == Value) {
214 return EFI_SUCCESS;
215 }
216
217 NumberOfTicks -= 1;
218 }
219
220 return EFI_TIMEOUT;
221 }
222
223 EFI_STATUS
224 PciRbMemRead (
225 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
226 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
227 IN UINT64 Address,
228 IN UINTN Count,
229 IN OUT VOID *Buffer
230 )
231 {
232 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
233 EFI_CPU_IO2_PROTOCOL *CpuIo;
234
235 PCI_TRACE ("PciRbMemRead()");
236
237 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
238 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
239
240 if (Buffer == NULL) {
241 return EFI_INVALID_PARAMETER;
242 }
243
244 if (Width >= EfiPciWidthMaximum) {
245 return EFI_INVALID_PARAMETER;
246 }
247
248 if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) &&
249 ((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) {
250 return EFI_INVALID_PARAMETER;
251 }
252
253 return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
254 }
255
256 EFI_STATUS
257 PciRbMemWrite (
258 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
259 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
260 IN UINT64 Address,
261 IN UINTN Count,
262 IN OUT VOID *Buffer
263 )
264 {
265 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
266 EFI_CPU_IO2_PROTOCOL *CpuIo;
267
268 PCI_TRACE ("PciRbMemWrite()");
269
270 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
271 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
272
273 if (Buffer == NULL) {
274 return EFI_INVALID_PARAMETER;
275 }
276
277 if (Width >= EfiPciWidthMaximum) {
278 return EFI_INVALID_PARAMETER;
279 }
280
281 if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) &&
282 ((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) {
283 return EFI_INVALID_PARAMETER;
284 }
285
286 return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
287 }
288
289 EFI_STATUS
290 PciRbIoRead (
291 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
292 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
293 IN UINT64 Address,
294 IN UINTN Count,
295 IN OUT VOID *Buffer
296 )
297 {
298 PCI_TRACE ("PciRbIoRead()");
299
300 if (Buffer == NULL) {
301 return EFI_INVALID_PARAMETER;
302 }
303
304 if (Width >= EfiPciWidthMaximum) {
305 return EFI_INVALID_PARAMETER;
306 }
307
308 // IO currently unsupported
309 return EFI_INVALID_PARAMETER;
310 }
311
312 EFI_STATUS
313 PciRbIoWrite (
314 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
315 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
316 IN UINT64 Address,
317 IN UINTN Count,
318 IN OUT VOID *Buffer
319 )
320 {
321 PCI_TRACE ("PciRbIoWrite()");
322
323 if (Buffer == NULL) {
324 return EFI_INVALID_PARAMETER;
325 }
326
327 if (Width >= EfiPciWidthMaximum) {
328 return EFI_INVALID_PARAMETER;
329 }
330
331 // IO currently unsupported
332 return EFI_INVALID_PARAMETER;
333 }
334
335 EFI_STATUS
336 PciRbPciRead (
337 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
338 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
339 IN UINT64 EfiAddress,
340 IN UINTN Count,
341 IN OUT VOID *Buffer
342 )
343 {
344 UINT32 Offset;
345 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
346 EFI_CPU_IO2_PROTOCOL *CpuIo;
347 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
348 UINT64 Address;
349
350 EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
351 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
352 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
353
354 if (Buffer == NULL) {
355 return EFI_INVALID_PARAMETER;
356 }
357
358 if (Width >= EfiPciWidthMaximum) {
359 return EFI_INVALID_PARAMETER;
360 }
361
362 if (EfiPciAddress->ExtendedRegister) {
363 Offset = EfiPciAddress->ExtendedRegister;
364 } else {
365 Offset = EfiPciAddress->Register;
366 }
367
368 // The UEFI PCI enumerator scans for devices at all possible addresses,
369 // and ignores some PCI rules - this results in some hardware being
370 // detected multiple times. We work around this by faking absent
371 // devices
372 if ((EfiPciAddress->Bus == 0) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) {
373 *((UINT32 *)Buffer) = 0xffffffff;
374 return EFI_SUCCESS;
375 }
376 if ((EfiPciAddress->Bus == 1) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) {
377 *((UINT32 *)Buffer) = 0xffffffff;
378 return EFI_SUCCESS;
379 }
380
381 // Work around incorrect class ID in the root bridge
382 if ((EfiPciAddress->Bus == 0) && (EfiPciAddress->Device == 0) && (EfiPciAddress->Function == 0) && (Offset == 8)) {
383 *((UINT32 *)Buffer) = 0x06040001;
384 return EFI_SUCCESS;
385 }
386
387 Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) |
388 (EfiPciAddress->Device << 15) |
389 (EfiPciAddress->Function << 12) | Offset);
390
391 if ((Address < PCI_ECAM_BASE) || (Address > PCI_ECAM_BASE + PCI_ECAM_SIZE)) {
392 return EFI_INVALID_PARAMETER;
393 }
394
395 return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
396 }
397
398 EFI_STATUS
399 PciRbPciWrite (
400 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
401 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
402 IN UINT64 EfiAddress,
403 IN UINTN Count,
404 IN OUT VOID *Buffer
405 )
406 {
407 UINT32 Offset;
408 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
409 EFI_CPU_IO2_PROTOCOL *CpuIo;
410 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
411 UINT64 Address;
412
413 EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
414 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
415 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
416
417 if (Buffer == NULL) {
418 return EFI_INVALID_PARAMETER;
419 }
420
421 if (Width >= EfiPciWidthMaximum) {
422 return EFI_INVALID_PARAMETER;
423 }
424
425 if (EfiPciAddress->ExtendedRegister)
426 Offset = EfiPciAddress->ExtendedRegister;
427 else
428 Offset = EfiPciAddress->Register;
429
430 Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) |
431 (EfiPciAddress->Device << 15) |
432 (EfiPciAddress->Function << 12) | Offset);
433
434 if (Address < PCI_ECAM_BASE || Address > PCI_ECAM_BASE + PCI_ECAM_SIZE) {
435 return EFI_INVALID_PARAMETER;
436 }
437
438 return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
439 }
440
441 EFI_STATUS
442 PciRbCopyMem (
443 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
444 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
445 IN UINT64 DestAddress,
446 IN UINT64 SrcAddress,
447 IN UINTN Count
448 )
449 {
450 EFI_STATUS Status;
451 BOOLEAN Direction;
452 UINTN Stride;
453 UINTN Index;
454 UINT64 Result;
455
456 PCI_TRACE ("PciRbCopyMem()");
457
458 if (Width > EfiPciWidthUint64) {
459 return EFI_INVALID_PARAMETER;
460 }
461
462 if (DestAddress == SrcAddress) {
463 return EFI_SUCCESS;
464 }
465
466 Stride = (UINTN)(1 << Width);
467
468 Direction = TRUE;
469 if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
470 Direction = FALSE;
471 SrcAddress = SrcAddress + (Count-1) * Stride;
472 DestAddress = DestAddress + (Count-1) * Stride;
473 }
474
475 for (Index = 0; Index < Count; Index++) {
476 Status = PciRbMemRead (
477 This,
478 Width,
479 SrcAddress,
480 1,
481 &Result
482 );
483 if (EFI_ERROR (Status)) {
484 return Status;
485 }
486 Status = PciRbMemWrite (
487 This,
488 Width,
489 DestAddress,
490 1,
491 &Result
492 );
493 if (EFI_ERROR (Status)) {
494 return Status;
495 }
496 if (Direction) {
497 SrcAddress += Stride;
498 DestAddress += Stride;
499 } else {
500 SrcAddress -= Stride;
501 DestAddress -= Stride;
502 }
503 }
504 return EFI_SUCCESS;
505 }
506
507 EFI_STATUS
508 PciRbMap (
509 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
510 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
511 IN VOID *HostAddress,
512 IN OUT UINTN *NumberOfBytes,
513 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
514 OUT VOID **Mapping
515 )
516 {
517 DMA_MAP_OPERATION DmaOperation;
518
519 PCI_TRACE ("PciRbMap()");
520
521 if (Operation == EfiPciOperationBusMasterRead) {
522 DmaOperation = MapOperationBusMasterRead;
523 } else if (Operation == EfiPciOperationBusMasterWrite) {
524 DmaOperation = MapOperationBusMasterWrite;
525 } else if (Operation == EfiPciOperationBusMasterCommonBuffer) {
526 DmaOperation = MapOperationBusMasterCommonBuffer;
527 } else {
528 return EFI_INVALID_PARAMETER;
529 }
530 return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
531 }
532
533 EFI_STATUS
534 PciRbUnMap (
535 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
536 IN VOID *Mapping
537 )
538 {
539 PCI_TRACE ("PciRbUnMap()");
540 return DmaUnmap (Mapping);
541 }
542
543 EFI_STATUS
544 PciRbAllocateBuffer (
545 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
546 IN EFI_ALLOCATE_TYPE Type,
547 IN EFI_MEMORY_TYPE MemoryType,
548 IN UINTN Pages,
549 IN OUT VOID **HostAddress,
550 IN UINT64 Attributes
551 )
552 {
553 PCI_TRACE ("PciRbAllocateBuffer()");
554
555 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
556 return EFI_UNSUPPORTED;
557 }
558
559 return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
560 }
561
562 EFI_STATUS
563 PciRbFreeBuffer (
564 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
565 IN UINTN Pages,
566 IN VOID *HostAddress
567 )
568 {
569 PCI_TRACE ("PciRbFreeBuffer()");
570 return DmaFreeBuffer (Pages, HostAddress);
571 }
572
573 EFI_STATUS
574 PciRbFlush (
575 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
576 )
577 {
578 PCI_TRACE ("PciRbFlush()");
579
580 //TODO: Not supported yet
581
582 return EFI_SUCCESS;
583 }
584
585 EFI_STATUS
586 PciRbSetAttributes (
587 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
588 IN UINT64 Attributes,
589 IN OUT UINT64 *ResourceBase,
590 IN OUT UINT64 *ResourceLength
591 )
592 {
593 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
594
595 PCI_TRACE ("PciRbSetAttributes()");
596
597 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
598
599 if (Attributes) {
600 if ((Attributes & (~(RootBridgeInstance->Supports))) != 0) {
601 return EFI_UNSUPPORTED;
602 }
603 }
604
605 //TODO: Cannot allowed to change attributes
606 if (Attributes & ~RootBridgeInstance->Attributes) {
607 return EFI_UNSUPPORTED;
608 }
609
610 return EFI_SUCCESS;
611 }
612
613 EFI_STATUS
614 PciRbGetAttributes (
615 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
616 OUT UINT64 *Supported,
617 OUT UINT64 *Attributes
618 )
619 {
620 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
621
622 PCI_TRACE ("PciRbGetAttributes()");
623
624 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
625
626 if (Attributes == NULL && Supported == NULL) {
627 return EFI_INVALID_PARAMETER;
628 }
629
630 // Set the return value for Supported and Attributes
631 if (Supported) {
632 *Supported = RootBridgeInstance->Supports;
633 }
634
635 if (Attributes) {
636 *Attributes = RootBridgeInstance->Attributes;
637 }
638
639 return EFI_SUCCESS;
640 }
641
642 EFI_STATUS
643 PciRbConfiguration (
644 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
645 OUT VOID **Resources
646 )
647 {
648 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
649 UINTN Index;
650
651 PCI_TRACE ("PciRbConfiguration()");
652
653 RootBridge = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
654
655 for (Index = 0; Index < ResTypeMax; Index++) {
656 //if (ResAlloc[Index].Length != 0) => Resource allocated
657 if (RootBridge->ResAlloc[Index].Length != 0) {
658 Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->ResAlloc[Index].Base;
659 Configuration.SpaceDesp[Index].AddrRangeMax = RootBridge->ResAlloc[Index].Base + RootBridge->ResAlloc[Index].Length - 1;
660 Configuration.SpaceDesp[Index].AddrLen = RootBridge->ResAlloc[Index].Length;
661 }
662 }
663
664 // Set up Configuration for the bus
665 Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->BusStart;
666 Configuration.SpaceDesp[Index].AddrLen = RootBridge->BusLength;
667
668 *Resources = &Configuration;
669 return EFI_SUCCESS;
670 }
671
672 EFI_STATUS
673 PciRbConstructor (
674 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge,
675 IN UINT32 PciAcpiUid,
676 IN UINT64 MemAllocAttributes
677 )
678 {
679 PCI_ROOT_BRIDGE_INSTANCE* RootBridge;
680 EFI_STATUS Status;
681
682 PCI_TRACE ("PciRbConstructor()");
683
684 // Allocate Memory for the Instance from a Template
685 RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));
686 if (RootBridge == NULL) {
687 PCI_TRACE ("PciRbConstructor(): ERROR: Out of Resources");
688 return EFI_OUT_OF_RESOURCES;
689 }
690 RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
691 CopyMem (&(RootBridge->DevicePath), &gDevicePathTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_DEVICE_PATH));
692 CopyMem (&(RootBridge->Io), &gIoTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL));
693
694 // Set Parent Handle
695 RootBridge->Io.ParentHandle = HostBridge->Handle;
696
697 // Attach the Root Bridge to the PCI Host Bridge Instance
698 RootBridge->HostBridge = HostBridge;
699
700 // Set Device Path for this Root Bridge
701 RootBridge->DevicePath.Acpi.UID = PciAcpiUid;
702
703 RootBridge->BusStart = FixedPcdGet32 (PcdPciBusMin);
704 RootBridge->BusLength = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
705
706 // PCI Attributes
707 RootBridge->Supports = 0;
708 RootBridge->Attributes = 0;
709
710 // Install Protocol Instances. It will also generate a device handle for the PCI Root Bridge
711 Status = gBS->InstallMultipleProtocolInterfaces (
712 &RootBridge->Handle,
713 &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,
714 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,
715 NULL
716 );
717 ASSERT (RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
718 if (EFI_ERROR (Status)) {
719 PCI_TRACE ("PciRbConstructor(): ERROR: Fail to install Protocol Interfaces");
720 FreePool (RootBridge);
721 return EFI_DEVICE_ERROR;
722 }
723
724 HostBridge->RootBridge = RootBridge;
725 return EFI_SUCCESS;
726 }
727
728 EFI_STATUS
729 PciRbDestructor (
730 IN PCI_ROOT_BRIDGE_INSTANCE* RootBridge
731 )
732 {
733 EFI_STATUS Status;
734
735 Status = gBS->UninstallMultipleProtocolInterfaces (
736 RootBridge->Handle,
737 &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,
738 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,
739 NULL
740 );
741
742 FreePool (RootBridge);
743
744 return Status;
745 }