• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
PciRbPollMem(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINT64 Mask,IN UINT64 Value,IN UINT64 Delay,OUT UINT64 * Result)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
PciRbPollIo(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINT64 Mask,IN UINT64 Value,IN UINT64 Delay,OUT UINT64 * Result)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
PciRbMemRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)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
PciRbMemWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)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
PciRbIoRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)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
PciRbIoWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)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
PciRbPciRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 EfiAddress,IN UINTN Count,IN OUT VOID * Buffer)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
PciRbPciWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 EfiAddress,IN UINTN Count,IN OUT VOID * Buffer)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
PciRbCopyMem(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 DestAddress,IN UINT64 SrcAddress,IN UINTN Count)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
PciRbMap(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)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
PciRbUnMap(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN VOID * Mapping)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
PciRbAllocateBuffer(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,IN OUT VOID ** HostAddress,IN UINT64 Attributes)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
PciRbFreeBuffer(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN UINTN Pages,IN VOID * HostAddress)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
PciRbFlush(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This)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
PciRbSetAttributes(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN UINT64 Attributes,IN OUT UINT64 * ResourceBase,IN OUT UINT64 * ResourceLength)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
PciRbGetAttributes(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,OUT UINT64 * Supported,OUT UINT64 * Attributes)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
PciRbConfiguration(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,OUT VOID ** Resources)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
PciRbConstructor(IN PCI_HOST_BRIDGE_INSTANCE * HostBridge,IN UINT32 PciAcpiUid,IN UINT64 MemAllocAttributes)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
PciRbDestructor(IN PCI_ROOT_BRIDGE_INSTANCE * RootBridge)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 }
746