]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciRootBridge.c
ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe: Fix for PCI Dual Address Cycle
[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 Operation == EfiPciOperationBusMasterRead64) {
523 DmaOperation = MapOperationBusMasterRead;
524 } else if (Operation == EfiPciOperationBusMasterWrite ||
525 Operation == EfiPciOperationBusMasterWrite64) {
526 DmaOperation = MapOperationBusMasterWrite;
527 } else if (Operation == EfiPciOperationBusMasterCommonBuffer ||
528 Operation == EfiPciOperationBusMasterCommonBuffer64) {
529 DmaOperation = MapOperationBusMasterCommonBuffer;
530 } else {
531 return EFI_INVALID_PARAMETER;
532 }
533 return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
534 }
535
536 EFI_STATUS
537 PciRbUnMap (
538 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
539 IN VOID *Mapping
540 )
541 {
542 PCI_TRACE ("PciRbUnMap()");
543 return DmaUnmap (Mapping);
544 }
545
546 EFI_STATUS
547 PciRbAllocateBuffer (
548 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
549 IN EFI_ALLOCATE_TYPE Type,
550 IN EFI_MEMORY_TYPE MemoryType,
551 IN UINTN Pages,
552 IN OUT VOID **HostAddress,
553 IN UINT64 Attributes
554 )
555 {
556 PCI_TRACE ("PciRbAllocateBuffer()");
557
558 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
559 return EFI_UNSUPPORTED;
560 }
561
562 return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
563 }
564
565 EFI_STATUS
566 PciRbFreeBuffer (
567 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
568 IN UINTN Pages,
569 IN VOID *HostAddress
570 )
571 {
572 PCI_TRACE ("PciRbFreeBuffer()");
573 return DmaFreeBuffer (Pages, HostAddress);
574 }
575
576 EFI_STATUS
577 PciRbFlush (
578 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
579 )
580 {
581 PCI_TRACE ("PciRbFlush()");
582
583 //TODO: Not supported yet
584
585 return EFI_SUCCESS;
586 }
587
588 EFI_STATUS
589 PciRbSetAttributes (
590 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
591 IN UINT64 Attributes,
592 IN OUT UINT64 *ResourceBase,
593 IN OUT UINT64 *ResourceLength
594 )
595 {
596 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
597
598 PCI_TRACE ("PciRbSetAttributes()");
599
600 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
601
602 if (Attributes) {
603 if ((Attributes & (~(RootBridgeInstance->Supports))) != 0) {
604 return EFI_UNSUPPORTED;
605 }
606 }
607
608 //TODO: Cannot allowed to change attributes
609 if (Attributes & ~RootBridgeInstance->Attributes) {
610 return EFI_UNSUPPORTED;
611 }
612
613 return EFI_SUCCESS;
614 }
615
616 EFI_STATUS
617 PciRbGetAttributes (
618 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
619 OUT UINT64 *Supported,
620 OUT UINT64 *Attributes
621 )
622 {
623 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
624
625 PCI_TRACE ("PciRbGetAttributes()");
626
627 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
628
629 if (Attributes == NULL && Supported == NULL) {
630 return EFI_INVALID_PARAMETER;
631 }
632
633 // Set the return value for Supported and Attributes
634 if (Supported) {
635 *Supported = RootBridgeInstance->Supports;
636 }
637
638 if (Attributes) {
639 *Attributes = RootBridgeInstance->Attributes;
640 }
641
642 return EFI_SUCCESS;
643 }
644
645 EFI_STATUS
646 PciRbConfiguration (
647 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
648 OUT VOID **Resources
649 )
650 {
651 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
652 UINTN Index;
653
654 PCI_TRACE ("PciRbConfiguration()");
655
656 RootBridge = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
657
658 for (Index = 0; Index < ResTypeMax; Index++) {
659 //if (ResAlloc[Index].Length != 0) => Resource allocated
660 if (RootBridge->ResAlloc[Index].Length != 0) {
661 Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->ResAlloc[Index].Base;
662 Configuration.SpaceDesp[Index].AddrRangeMax = RootBridge->ResAlloc[Index].Base + RootBridge->ResAlloc[Index].Length - 1;
663 Configuration.SpaceDesp[Index].AddrLen = RootBridge->ResAlloc[Index].Length;
664 }
665 }
666
667 // Set up Configuration for the bus
668 Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->BusStart;
669 Configuration.SpaceDesp[Index].AddrLen = RootBridge->BusLength;
670
671 *Resources = &Configuration;
672 return EFI_SUCCESS;
673 }
674
675 EFI_STATUS
676 PciRbConstructor (
677 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge,
678 IN UINT32 PciAcpiUid,
679 IN UINT64 MemAllocAttributes
680 )
681 {
682 PCI_ROOT_BRIDGE_INSTANCE* RootBridge;
683 EFI_STATUS Status;
684
685 PCI_TRACE ("PciRbConstructor()");
686
687 // Allocate Memory for the Instance from a Template
688 RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));
689 if (RootBridge == NULL) {
690 PCI_TRACE ("PciRbConstructor(): ERROR: Out of Resources");
691 return EFI_OUT_OF_RESOURCES;
692 }
693 RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
694 CopyMem (&(RootBridge->DevicePath), &gDevicePathTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_DEVICE_PATH));
695 CopyMem (&(RootBridge->Io), &gIoTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL));
696
697 // Set Parent Handle
698 RootBridge->Io.ParentHandle = HostBridge->Handle;
699
700 // Attach the Root Bridge to the PCI Host Bridge Instance
701 RootBridge->HostBridge = HostBridge;
702
703 // Set Device Path for this Root Bridge
704 RootBridge->DevicePath.Acpi.UID = PciAcpiUid;
705
706 RootBridge->BusStart = FixedPcdGet32 (PcdPciBusMin);
707 RootBridge->BusLength = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
708
709 // PCI Attributes
710 RootBridge->Supports = 0;
711 RootBridge->Attributes = 0;
712
713 // Install Protocol Instances. It will also generate a device handle for the PCI Root Bridge
714 Status = gBS->InstallMultipleProtocolInterfaces (
715 &RootBridge->Handle,
716 &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,
717 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,
718 NULL
719 );
720 ASSERT (RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
721 if (EFI_ERROR (Status)) {
722 PCI_TRACE ("PciRbConstructor(): ERROR: Fail to install Protocol Interfaces");
723 FreePool (RootBridge);
724 return EFI_DEVICE_ERROR;
725 }
726
727 HostBridge->RootBridge = RootBridge;
728 return EFI_SUCCESS;
729 }
730
731 EFI_STATUS
732 PciRbDestructor (
733 IN PCI_ROOT_BRIDGE_INSTANCE* RootBridge
734 )
735 {
736 EFI_STATUS Status;
737
738 Status = gBS->UninstallMultipleProtocolInterfaces (
739 RootBridge->Handle,
740 &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,
741 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,
742 NULL
743 );
744
745 FreePool (RootBridge);
746
747 return Status;
748 }