1 /** @file
2 IIO PCI Root Bridge Io Protocol code. Generic enough to work for all IIOs.
3 Does not support configuration accesses to the extended PCI Express registers yet.
4 
5 Copyright (c) 2013-2015 Intel Corporation.
6 
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution.  The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11 
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15 
16 **/
17 
18 #include "PciRootBridge.h"
19 
20 //
21 // Define PCI express offse
22 //
23 #define PCIE_OFF(Bus, Device, Function, Register) \
24     ((UINT64) ((UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) (Function << 12) + (UINTN) (Register)))
25 
26 //
27 // Pci Root Bridge Io Module Variables
28 //
29 EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
30 EFI_CPU_IO2_PROTOCOL        *mCpuIo;
31 
32 EFI_STATUS
SimpleIioRootBridgeConstructor(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * Protocol,IN EFI_HANDLE HostBridgeHandle,IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE * ResAperture,UINT64 AllocAttributes)33 SimpleIioRootBridgeConstructor (
34   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       *Protocol,
35   IN EFI_HANDLE                            HostBridgeHandle,
36   IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE     *ResAperture,
37   UINT64                                   AllocAttributes
38   )
39 /*++
40 
41 Routine Description:
42 
43   Construct the Pci Root Bridge Io protocol.
44 
45 Arguments:
46 
47   Protocol          -  Protocol to initialize.
48   HostBridgeHandle  -  Handle to the HostBridge.
49   ResAperture       -  Resource apperture of the root bridge.
50   AllocAttributes   -  Attribute of resouce allocated.
51 
52 Returns:
53 
54   EFI_SUCCESS  -  Success.
55   Others       -  Fail.
56 
57 --*/
58 {
59   EFI_STATUS                Status;
60   PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
61   PCI_RESOURCE_TYPE         Index;
62   UINT32                    HecBase;
63   UINT32                    HecSize;
64 
65   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
66 
67   //
68   // Initialize the apertures with default values
69   //
70   CopyMem (
71     &PrivateData->Aperture,
72     ResAperture,
73     sizeof (PCI_ROOT_BRIDGE_RESOURCE_APERTURE)
74     );
75 
76   for (Index = TypeIo; Index < TypeMax; Index++) {
77     PrivateData->ResAllocNode[Index].Type   = Index;
78     PrivateData->ResAllocNode[Index].Base   = 0;
79     PrivateData->ResAllocNode[Index].Length = 0;
80     PrivateData->ResAllocNode[Index].Status = ResNone;
81   }
82 
83   EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
84   PrivateData->PciAddress             = 0xCF8;
85   PrivateData->PciData                = 0xCFC;
86 
87   PrivateData->RootBridgeAllocAttrib  = AllocAttributes;
88   PrivateData->Attributes             = 0;
89   PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
90     EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
91     EFI_PCI_ATTRIBUTE_ISA_IO_16         |
92     EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 |
93     EFI_PCI_ATTRIBUTE_VGA_MEMORY |
94     EFI_PCI_ATTRIBUTE_VGA_IO_16;
95 
96   //
97   // Don't support BASE above 4GB currently
98   // Position to bit 39:28
99   //
100   HecBase = (UINT32) PcdGet64 (PcdPciExpressBaseAddress);
101   HecSize = (UINT32) PcdGet64 (PcdPciExpressSize);
102 
103   ASSERT ((HecBase & (HecSize - 1)) == 0);
104   ASSERT (HecBase != 0);
105 
106   PrivateData->HecBase            = HecBase;
107   PrivateData->HecLen             = HecSize;
108 
109   PrivateData->BusNumberAssigned  = FALSE;
110   PrivateData->BusScanCount       = 0;
111 
112   Protocol->ParentHandle          = HostBridgeHandle;
113 
114   Protocol->PollMem               = RootBridgeIoPollMem;
115   Protocol->PollIo                = RootBridgeIoPollIo;
116 
117   Protocol->Mem.Read              = RootBridgeIoMemRead;
118   Protocol->Mem.Write             = RootBridgeIoMemWrite;
119 
120   Protocol->Io.Read               = RootBridgeIoIoRead;
121   Protocol->Io.Write              = RootBridgeIoIoWrite;
122 
123   Protocol->CopyMem               = RootBridgeIoCopyMem;
124 
125   Protocol->Pci.Read              = RootBridgeIoPciRead;
126   Protocol->Pci.Write             = RootBridgeIoPciWrite;
127 
128   Protocol->Map                   = RootBridgeIoMap;
129   Protocol->Unmap                 = RootBridgeIoUnmap;
130 
131   Protocol->AllocateBuffer        = RootBridgeIoAllocateBuffer;
132   Protocol->FreeBuffer            = RootBridgeIoFreeBuffer;
133 
134   Protocol->Flush                 = RootBridgeIoFlush;
135 
136   Protocol->GetAttributes         = RootBridgeIoGetAttributes;
137   Protocol->SetAttributes         = RootBridgeIoSetAttributes;
138 
139   Protocol->Configuration         = RootBridgeIoConfiguration;
140 
141   Protocol->SegmentNumber         = 0;
142 
143   Status                          = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
144   ASSERT_EFI_ERROR (Status);
145 
146   Status = gBS->LocateProtocol (
147                   &gEfiCpuIo2ProtocolGuid,
148                   NULL,
149                   (VOID **) &mCpuIo
150                   );
151   ASSERT_EFI_ERROR (Status);
152 
153   return EFI_SUCCESS;
154 }
155 
156 EFI_STATUS
157 EFIAPI
RootBridgeIoPollMem(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)158 RootBridgeIoPollMem (
159   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
160   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
161   IN  UINT64                                 Address,
162   IN  UINT64                                 Mask,
163   IN  UINT64                                 Value,
164   IN  UINT64                                 Delay,
165   OUT UINT64                                 *Result
166   )
167 /*++
168 
169 Routine Description:
170 
171   Poll an address in memory mapped space until an exit condition is met
172   or a timeout occurs.
173 
174 Arguments:
175 
176   This     -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
177   Width    -  Width of the memory operation.
178   Address  -  The base address of the memory operation.
179   Mask     -  Mask used for polling criteria.
180   Value    -  Comparison value used for polling exit criteria.
181   Delay    -  Number of 100ns units to poll.
182   Result   -  Pointer to the last value read from memory location.
183 
184 Returns:
185 
186   EFI_SUCCESS            -  Success.
187   EFI_INVALID_PARAMETER  -  Invalid parameter found.
188   EFI_TIMEOUT            -  Delay expired before a match occurred.
189   EFI_OUT_OF_RESOURCES   -  Fail due to lack of resources.
190 
191 --*/
192 {
193   EFI_STATUS  Status;
194   UINT64      NumberOfTicks;
195   UINT32       Remainder;
196 
197   if (Result == NULL) {
198     return EFI_INVALID_PARAMETER;
199   }
200 
201   if (Width < 0 || Width > EfiPciWidthUint64) {
202     return EFI_INVALID_PARAMETER;
203   }
204   //
205   // No matter what, always do a single poll.
206   //
207   Status = This->Mem.Read (
208                       This,
209                       Width,
210                       Address,
211                       1,
212                       Result
213                       );
214   if (EFI_ERROR (Status)) {
215     return Status;
216   }
217 
218   if ((*Result & Mask) == Value) {
219     return EFI_SUCCESS;
220   }
221 
222   if (Delay != 0) {
223     //
224     // Determine the proper # of metronome ticks to wait for polling the
225     // location.  The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
226     // The "+1" to account for the possibility of the first tick being short
227     // because we started in the middle of a tick.
228     //
229     // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
230     // protocol definition is updated.
231     //
232     NumberOfTicks = DivU64x32Remainder (
233                       Delay,
234                       (UINT32) mMetronome->TickPeriod,
235                       &Remainder
236                       );
237     if (Remainder != 0) {
238       NumberOfTicks += 1;
239     }
240 
241     NumberOfTicks += 1;
242 
243     while (NumberOfTicks) {
244 
245       mMetronome->WaitForTick (mMetronome, 1);
246 
247       Status = This->Mem.Read (
248                           This,
249                           Width,
250                           Address,
251                           1,
252                           Result
253                           );
254       if (EFI_ERROR (Status)) {
255         return Status;
256       }
257 
258       if ((*Result & Mask) == Value) {
259         return EFI_SUCCESS;
260       }
261 
262       NumberOfTicks -= 1;
263     }
264   }
265 
266   return EFI_TIMEOUT;
267 }
268 
269 EFI_STATUS
270 EFIAPI
RootBridgeIoPollIo(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)271 RootBridgeIoPollIo (
272   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
273   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
274   IN  UINT64                                 Address,
275   IN  UINT64                                 Mask,
276   IN  UINT64                                 Value,
277   IN  UINT64                                 Delay,
278   OUT UINT64                                 *Result
279   )
280 /*++
281 
282 Routine Description:
283 
284   Poll an address in I/O space until an exit condition is met
285   or a timeout occurs.
286 
287 Arguments:
288 
289   This     -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
290   Width    -  Width of I/O operation.
291   Address  -  The base address of the I/O operation.
292   Mask     -  Mask used for polling criteria.
293   Value    -  Comparison value used for polling exit criteria.
294   Delay    -  Number of 100ns units to poll.
295   Result   -  Pointer to the last value read from memory location.
296 
297 Returns:
298 
299   EFI_SUCCESS            -  Success.
300   EFI_INVALID_PARAMETER  -  Invalid parameter found.
301   EFI_TIMEOUT            -  Delay expired before a match occurred.
302   EFI_OUT_OF_RESOURCES   -  Fail due to lack of resources.
303 
304 --*/
305 {
306   EFI_STATUS  Status;
307   UINT64      NumberOfTicks;
308   UINT32       Remainder;
309 
310   //
311   // No matter what, always do a single poll.
312   //
313   if (Result == NULL) {
314     return EFI_INVALID_PARAMETER;
315   }
316 
317   if (Width < 0 || Width > EfiPciWidthUint64) {
318     return EFI_INVALID_PARAMETER;
319   }
320 
321   Status = This->Io.Read (
322                       This,
323                       Width,
324                       Address,
325                       1,
326                       Result
327                       );
328   if (EFI_ERROR (Status)) {
329     return Status;
330   }
331 
332   if ((*Result & Mask) == Value) {
333     return EFI_SUCCESS;
334   }
335 
336   if (Delay != 0) {
337     //
338     // Determine the proper # of metronome ticks to wait for polling the
339     // location.  The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
340     // The "+1" to account for the possibility of the first tick being short
341     // because we started in the middle of a tick.
342     //
343     NumberOfTicks = DivU64x32Remainder (
344                       Delay,
345                       (UINT32) mMetronome->TickPeriod,
346                       &Remainder
347                       );
348     if (Remainder != 0) {
349       NumberOfTicks += 1;
350     }
351 
352     NumberOfTicks += 1;
353 
354     while (NumberOfTicks) {
355 
356       mMetronome->WaitForTick (mMetronome, 1);
357 
358       Status = This->Io.Read (
359                           This,
360                           Width,
361                           Address,
362                           1,
363                           Result
364                           );
365       if (EFI_ERROR (Status)) {
366         return Status;
367       }
368 
369       if ((*Result & Mask) == Value) {
370         return EFI_SUCCESS;
371       }
372 
373       NumberOfTicks -= 1;
374     }
375   }
376 
377   return EFI_TIMEOUT;
378 }
379 
380 EFI_STATUS
381 EFIAPI
RootBridgeIoMemRead(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)382 RootBridgeIoMemRead (
383   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
384   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
385   IN     UINT64                                 Address,
386   IN     UINTN                                  Count,
387   IN OUT VOID                                   *Buffer
388   )
389 /*++
390 
391 Routine Description:
392 
393   Allow read from memory mapped I/O space.
394 
395 Arguments:
396 
397   This     -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
398   Width    -  The width of memory operation.
399   Address  -  Base address of the memory operation.
400   Count    -  Number of memory opeartion to perform.
401   Buffer   -  The destination buffer to store data.
402 
403 Returns:
404 
405   EFI_SUCCESS            -  Success.
406   EFI_INVALID_PARAMETER  -  Invalid parameter found.
407   EFI_OUT_OF_RESOURCES   -  Fail due to lack of resources.
408 
409 --*/
410 {
411   PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
412   if (Buffer == NULL) {
413     return EFI_INVALID_PARAMETER;
414   }
415 
416   if (Width < 0 ||
417       Width == EfiPciWidthUint64 ||
418       Width == EfiPciWidthFifoUint64 ||
419       Width == EfiPciWidthFillUint64 ||
420       Width >= EfiPciWidthMaximum
421       ) {
422     return EFI_INVALID_PARAMETER;
423   }
424 
425   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
426   //
427   // Check memory access limit
428   //
429   if (PrivateData->Aperture.Mem64Limit > PrivateData->Aperture.Mem64Base) {
430       if (Address > PrivateData->Aperture.Mem64Limit) {
431         return EFI_INVALID_PARAMETER;
432       }
433   } else {
434       if (Address > PrivateData->Aperture.Mem32Limit) {
435         return EFI_INVALID_PARAMETER;
436       }
437   }
438 
439   return mCpuIo->Mem.Read (
440                       mCpuIo,
441                       (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
442                       Address,
443                       Count,
444                       Buffer
445                       );
446 }
447 
448 EFI_STATUS
449 EFIAPI
RootBridgeIoMemWrite(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)450 RootBridgeIoMemWrite (
451   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
452   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
453   IN     UINT64                                 Address,
454   IN     UINTN                                  Count,
455   IN OUT VOID                                   *Buffer
456   )
457 /*++
458 
459 Routine Description:
460 
461   Allow write to memory mapped I/O space.
462 
463 Arguments:
464 
465   This     -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
466   Width    -  The width of memory operation.
467   Address  -  Base address of the memory operation.
468   Count    -  Number of memory opeartion to perform.
469   Buffer   -  The source buffer to write data from.
470 
471 Returns:
472 
473   EFI_SUCCESS            -  Success.
474   EFI_INVALID_PARAMETER  -  Invalid parameter found.
475   EFI_OUT_OF_RESOURCES   -  Fail due to lack of resources.
476 
477 --*/
478 {
479   PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
480 
481   if (Buffer == NULL) {
482     return EFI_INVALID_PARAMETER;
483   }
484 
485   if (Width < 0 ||
486       Width == EfiPciWidthUint64 ||
487       Width == EfiPciWidthFifoUint64 ||
488       Width == EfiPciWidthFillUint64 ||
489       Width >= EfiPciWidthMaximum
490       ) {
491     return EFI_INVALID_PARAMETER;
492   }
493 
494   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
495 
496   //
497   // Check memory access limit
498   //
499   if (PrivateData->Aperture.Mem64Limit > PrivateData->Aperture.Mem64Base) {
500       if (Address > PrivateData->Aperture.Mem64Limit) {
501         return EFI_INVALID_PARAMETER;
502       }
503   } else {
504       if (Address > PrivateData->Aperture.Mem32Limit) {
505         return EFI_INVALID_PARAMETER;
506       }
507   }
508 
509   return mCpuIo->Mem.Write (
510                       mCpuIo,
511                       (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
512                       Address,
513                       Count,
514                       Buffer
515                       );
516 }
517 
518 EFI_STATUS
519 EFIAPI
RootBridgeIoIoRead(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)520 RootBridgeIoIoRead (
521   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
522   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
523   IN     UINT64                                 Address,
524   IN     UINTN                                  Count,
525   IN OUT VOID                                   *Buffer
526   )
527 /*++
528 
529 Routine Description:
530 
531   Enable a PCI driver to read PCI controller registers in the
532   PCI root bridge I/O space.
533 
534 Arguments:
535 
536   This     -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
537   Width    -  Signifies the width of the memory operation.
538   Address  -  The base address of the I/O operation.
539   Count    -  The number of I/O operations to perform.
540   Buffer   -  The destination buffer to store the results.
541 
542 Returns:
543 
544   EFI_SUCCESS            -  The data was read from the PCI root bridge.
545   EFI_INVALID_PARAMETER  -  Invalid parameters found.
546   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of
547                             resources.
548 --*/
549 {
550 
551   UINTN                     AlignMask;
552   PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
553 
554   if (Buffer == NULL) {
555     return EFI_INVALID_PARAMETER;
556   }
557 
558   if (Width < 0 ||
559       Width == EfiPciWidthUint64 ||
560       Width == EfiPciWidthFifoUint64 ||
561       Width == EfiPciWidthFillUint64 ||
562       Width >= EfiPciWidthMaximum
563       ) {
564     return EFI_INVALID_PARAMETER;
565   }
566 
567   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
568 
569   //
570   // AlignMask = (1 << Width) - 1;
571   //
572   AlignMask = (1 << (Width & 0x03)) - 1;
573 
574   //
575   // check Io access limit
576   //
577   if (Address > PrivateData->Aperture.IoLimit) {
578     return EFI_INVALID_PARAMETER;
579   }
580 
581   if (Address & AlignMask) {
582     return EFI_INVALID_PARAMETER;
583   }
584 
585   return mCpuIo->Io.Read (
586                       mCpuIo,
587                       (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
588                       Address,
589                       Count,
590                       Buffer
591                       );
592 
593 }
594 
595 EFI_STATUS
596 EFIAPI
RootBridgeIoIoWrite(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)597 RootBridgeIoIoWrite (
598   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL          *This,
599   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
600   IN     UINT64                                   Address,
601   IN     UINTN                                    Count,
602   IN OUT VOID                                     *Buffer
603   )
604 /*++
605 
606 Routine Description:
607 
608   Enable a PCI driver to write to PCI controller registers in the
609   PCI root bridge I/O space.
610 
611 Arguments:
612 
613   This     -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
614   Width    -  Signifies the width of the memory operation.
615   Address  -  The base address of the I/O operation.
616   Count    -  The number of I/O operations to perform.
617   Buffer   -  The source buffer to write data from.
618 
619 Returns:
620 
621   EFI_SUCCESS            -  The data was written to the PCI root bridge.
622   EFI_INVALID_PARAMETER  -  Invalid parameters found.
623   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of
624                             resources.
625 --*/
626 {
627   UINTN                     AlignMask;
628   PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
629 
630   if (Buffer == NULL) {
631     return EFI_INVALID_PARAMETER;
632   }
633 
634   if (Width < 0 ||
635       Width == EfiPciWidthUint64 ||
636       Width == EfiPciWidthFifoUint64 ||
637       Width == EfiPciWidthFillUint64 ||
638       Width >= EfiPciWidthMaximum
639       ) {
640     return EFI_INVALID_PARAMETER;
641   }
642 
643   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
644 
645   //
646   // AlignMask = (1 << Width) - 1;
647   //
648   AlignMask = (1 << (Width & 0x03)) - 1;
649 
650   //
651   // Check Io access limit
652   //
653   if (Address > PrivateData->Aperture.IoLimit) {
654     return EFI_INVALID_PARAMETER;
655   }
656 
657   if (Address & AlignMask) {
658     return EFI_INVALID_PARAMETER;
659   }
660 
661   return mCpuIo->Io.Write (
662                       mCpuIo,
663                       (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
664                       Address,
665                       Count,
666                       Buffer
667                       );
668 
669 }
670 
671 EFI_STATUS
672 EFIAPI
RootBridgeIoCopyMem(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)673 RootBridgeIoCopyMem (
674   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
675   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH     Width,
676   IN UINT64                                    DestAddress,
677   IN UINT64                                    SrcAddress,
678   IN UINTN                                     Count
679   )
680 /*++
681 
682 Routine Description:
683 
684   Copy one region of PCI root bridge memory space to be copied to
685   another region of PCI root bridge memory space.
686 
687 Arguments:
688 
689   This         -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
690   Width        -  Signifies the width of the memory operation.
691   DestAddress  -  Destination address of the memory operation.
692   SrcAddress   -  Source address of the memory operation.
693   Count        -  Number of memory operations to perform.
694 
695 Returns:
696 
697   EFI_SUCCESS            -  The data was copied successfully.
698   EFI_INVALID_PARAMETER  -  Invalid parameters found.
699   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of
700                             resources.
701 --*/
702 {
703   EFI_STATUS  Status;
704   BOOLEAN     Direction;
705   UINTN       Stride;
706   UINTN       Index;
707   UINT64      Result;
708 
709   if (Width < 0 || Width > EfiPciWidthUint64) {
710     return EFI_INVALID_PARAMETER;
711   }
712 
713   if (DestAddress == SrcAddress) {
714     return EFI_SUCCESS;
715   }
716 
717   Stride    = (UINTN)1 << Width;
718 
719   Direction = TRUE;
720   if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
721     Direction   = FALSE;
722     SrcAddress  = SrcAddress + (Count - 1) * Stride;
723     DestAddress = DestAddress + (Count - 1) * Stride;
724   }
725 
726   for (Index = 0; Index < Count; Index++) {
727     Status = RootBridgeIoMemRead (
728               This,
729               Width,
730               SrcAddress,
731               1,
732               &Result
733               );
734     if (EFI_ERROR (Status)) {
735       return Status;
736     }
737 
738     Status = RootBridgeIoMemWrite (
739               This,
740               Width,
741               DestAddress,
742               1,
743               &Result
744               );
745     if (EFI_ERROR (Status)) {
746       return Status;
747     }
748 
749     if (Direction) {
750       SrcAddress += Stride;
751       DestAddress += Stride;
752     } else {
753       SrcAddress -= Stride;
754       DestAddress -= Stride;
755     }
756   }
757 
758   return EFI_SUCCESS;
759 }
760 
761 EFI_STATUS
RootBridgeIoPciRW(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN BOOLEAN Write,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 UserAddress,IN UINTN Count,IN OUT VOID * UserBuffer)762 RootBridgeIoPciRW (
763   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
764   IN BOOLEAN                                Write,
765   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
766   IN UINT64                                 UserAddress,
767   IN UINTN                                  Count,
768   IN OUT VOID                              *UserBuffer
769   )
770 /*++
771 
772 Routine Description:
773 
774 Arguments:
775 
776 Returns:
777 
778 --*/
779 {
780   PCI_CONFIG_ACCESS_CF8             Pci;
781   PCI_CONFIG_ACCESS_CF8             PciAligned;
782   UINT32                            Stride;
783   UINTN                             PciData;
784   UINTN                             PciDataStride;
785   PCI_ROOT_BRIDGE_INSTANCE         *PrivateData;
786 
787   if (Width >= EfiPciWidthMaximum) {
788     return EFI_INVALID_PARAMETER;
789   }
790 
791   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
792 
793   ASSERT (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*)&UserAddress)->ExtendedRegister == 0x00);
794 
795   Stride = 1 << Width;
796 
797   Pci.Bits.Reg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register;
798   Pci.Bits.Func = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Function;
799   Pci.Bits.Dev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Device;
800   Pci.Bits.Bus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Bus;
801   Pci.Bits.Reserved = 0;
802   Pci.Bits.Enable = 1;
803 
804   //
805   // PCI Configure access are all 32-bit aligned, but by accessing the
806   //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
807   //  are possible on PCI.
808   //
809   // To read a byte of PCI configuration space you load 0xcf8 and
810   //  read 0xcfc, 0xcfd, 0xcfe, 0xcff
811   //
812   PciDataStride = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register & 0x03;
813 
814   while (Count) {
815     PciAligned = Pci;
816     PciAligned.Bits.Reg &= 0xfc;
817     PciData = PrivateData->PciData + PciDataStride;
818     EfiAcquireLock(&PrivateData->PciLock);
819     This->Io.Write (This, EfiPciWidthUint32, \
820                     PrivateData->PciAddress, 1, &PciAligned);
821     if (Write) {
822       This->Io.Write (This, Width, PciData, 1, UserBuffer);
823     } else {
824       This->Io.Read (This, Width, PciData, 1, UserBuffer);
825     }
826     EfiReleaseLock(&PrivateData->PciLock);
827     UserBuffer = ((UINT8 *)UserBuffer) + Stride;
828     PciDataStride = (PciDataStride + Stride) % 4;
829     Count -= 1;
830 
831     //
832     // Only increment the PCI address if Width is not a FIFO.
833     //
834     if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
835       Pci.Bits.Reg += Stride;
836     }
837   }
838   return EFI_SUCCESS;
839 }
840 
841 EFI_STATUS
842 EFIAPI
RootBridgeIoPciRead(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)843 RootBridgeIoPciRead (
844   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL          *This,
845   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
846   IN     UINT64                                   Address,
847   IN     UINTN                                    Count,
848   IN OUT VOID                                     *Buffer
849   )
850 /*++
851 
852 Routine Description:
853 
854   Allows read from PCI configuration space.
855 
856 Arguments:
857 
858   This     -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
859   Width    -  Signifies the width of the memory operation.
860   Address  -  The address within the PCI configuration space
861               for the PCI controller.
862   Count    -  The number of PCI configuration operations
863               to perform.
864   Buffer   -  The destination buffer to store the results.
865 
866 Returns:
867 
868   EFI_SUCCESS            -  The data was read from the PCI root bridge.
869   EFI_INVALID_PARAMETER  -  Invalid parameters found.
870   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of
871                             resources.
872 --*/
873 {
874   PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
875   UINT32                    PciBus;
876   UINT32                    PciDev;
877   UINT32                    PciFn;
878   UINT32                    PciExtReg;
879   UINT64                    ExtConfigAdd;
880 
881   if (Buffer == NULL) {
882     return EFI_INVALID_PARAMETER;
883   }
884 
885   if (Width < 0 ||
886       Width == EfiPciWidthUint64 ||
887       Width == EfiPciWidthFifoUint64 ||
888       Width == EfiPciWidthFillUint64 ||
889       Width >= EfiPciWidthMaximum
890       ) {
891     return EFI_INVALID_PARAMETER;
892   }
893 
894   //
895   // Read Pci configuration space
896   //
897   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
898 
899   if (PrivateData->HecBase == 0) {
900     return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
901   }
902 
903   if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
904     PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
905   } else {
906     PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
907   }
908 
909   PciBus        = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
910   PciDev        = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
911   PciFn         = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;
912 
913   ExtConfigAdd  = (UINT64) PrivateData->HecBase + PCIE_OFF (PciBus, PciDev, PciFn, PciExtReg);
914 
915   return mCpuIo->Mem.Read (
916                       mCpuIo,
917                       (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
918                       ExtConfigAdd,
919                       Count,
920                       Buffer
921                       );
922 }
923 
924 EFI_STATUS
925 EFIAPI
RootBridgeIoPciWrite(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)926 RootBridgeIoPciWrite (
927   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL          *This,
928   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
929   IN UINT64                                   Address,
930   IN UINTN                                    Count,
931   IN OUT VOID                                 *Buffer
932   )
933 /*++
934 
935 Routine Description:
936 
937   Allows write to PCI configuration space.
938 
939 Arguments:
940 
941   This     -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
942   Width    -  Signifies the width of the memory operation.
943   Address  -  The address within the PCI configuration space
944               for the PCI controller.
945   Count    -  The number of PCI configuration operations
946               to perform.
947   Buffer   -  The source buffer to get the results.
948 
949 Returns:
950 
951   EFI_SUCCESS            -  The data was written to the PCI root bridge.
952   EFI_INVALID_PARAMETER  -  Invalid parameters found.
953   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of
954                             resources.
955 --*/
956 {
957   PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
958   UINT32                    PciBus;
959   UINT32                    PciDev;
960   UINT32                    PciFn;
961   UINT32                    PciExtReg;
962   UINT64                    ExtConfigAdd;
963 
964   if (Buffer == NULL) {
965     return EFI_INVALID_PARAMETER;
966   }
967 
968   if (Width < 0 || Width >= EfiPciWidthMaximum) {
969     return EFI_INVALID_PARAMETER;
970   }
971 
972   //
973   // Write Pci configuration space
974   //
975   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
976 
977   if (PrivateData->HecBase == 0) {
978     return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
979   }
980 
981   if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
982     PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
983   } else {
984     PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
985   }
986 
987   PciBus        = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
988   PciDev        = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
989   PciFn         = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;
990 
991   ExtConfigAdd  = (UINT64) PrivateData->HecBase + PCIE_OFF (PciBus, PciDev, PciFn, PciExtReg);
992 
993   return mCpuIo->Mem.Write (
994                       mCpuIo,
995                       (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
996                       ExtConfigAdd,
997                       Count,
998                       Buffer
999                       );
1000 }
1001 
1002 EFI_STATUS
1003 EFIAPI
RootBridgeIoMap(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)1004 RootBridgeIoMap (
1005   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
1006   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
1007   IN     VOID                                       *HostAddress,
1008   IN OUT UINTN                                      *NumberOfBytes,
1009   OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
1010   OUT    VOID                                       **Mapping
1011   )
1012 /*++
1013 
1014 Routine Description:
1015 
1016   Provides the PCI controller-specific address needed to access
1017   system memory for DMA.
1018 
1019 Arguments:
1020 
1021   This           -  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1022   Operation      -  Indicate if the bus master is going to read or write
1023                     to system memory.
1024   HostAddress    -  The system memory address to map on the PCI controller.
1025   NumberOfBytes  -  On input the number of bytes to map.
1026                     On output the number of bytes that were mapped.
1027   DeviceAddress  -  The resulting map address for the bus master PCI
1028                     controller to use to access the system memory's HostAddress.
1029   Mapping        -  The value to pass to Unmap() when the bus master DMA
1030                     operation is complete.
1031 
1032 Returns:
1033 
1034   EFI_SUCCESS            -  Success.
1035   EFI_INVALID_PARAMETER  -  Invalid parameters found.
1036   EFI_UNSUPPORTED        -  The HostAddress cannot be mapped as a common
1037                             buffer.
1038   EFI_DEVICE_ERROR       -  The System hardware could not map the requested
1039                             address.
1040   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to
1041                             lack of resources.
1042 
1043 --*/
1044 {
1045   EFI_STATUS            Status;
1046   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
1047   MAP_INFO              *MapInfo;
1048 
1049   if (NumberOfBytes == NULL || Mapping == NULL || DeviceAddress == NULL || HostAddress == NULL) {
1050     return EFI_INVALID_PARAMETER;
1051   }
1052   //
1053   // Initialize the return values to their defaults
1054   //
1055   *Mapping = NULL;
1056 
1057   //
1058   // Make sure that Operation is valid
1059   //
1060   if ((Operation < 0) || (Operation > EfiPciOperationBusMasterCommonBuffer64)) {
1061     return EFI_INVALID_PARAMETER;
1062   }
1063   //
1064   // Most PCAT like chipsets can not handle performing DMA above 4GB.
1065   // If any part of the DMA transfer being mapped is above 4GB, then
1066   // map the DMA transfer to a buffer below 4GB.
1067   //
1068   PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1069   if ((PhysicalAddress +*NumberOfBytes) > 0x100000000ULL) {
1070     //
1071     // Common Buffer operations can not be remapped.  If the common buffer
1072     // if above 4GB, then it is not possible to generate a mapping, so return
1073     // an error.
1074     //
1075     if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
1076       return EFI_INVALID_PARAMETER;
1077     }
1078   }
1079 
1080   if ((PhysicalAddress + *NumberOfBytes) > (DMA_MEMORY_TOP+1)) {
1081 
1082     //
1083     // Common Buffer operations can not be remapped.
1084     //
1085     if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
1086       *DeviceAddress = PhysicalAddress;
1087       return EFI_SUCCESS;
1088     }
1089     //
1090     // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
1091     // called later.
1092     //
1093     Status = gBS->AllocatePool (
1094                     EfiBootServicesData,
1095                     sizeof (MAP_INFO),
1096                     (VOID **) &MapInfo
1097                     );
1098     if (EFI_ERROR (Status)) {
1099       *NumberOfBytes = 0;
1100       return Status;
1101     }
1102     //
1103     // Return a pointer to the MAP_INFO structure in Mapping
1104     //
1105     *Mapping = MapInfo;
1106 
1107     //
1108     // Initialize the MAP_INFO structure
1109     //
1110     MapInfo->Operation          = Operation;
1111     MapInfo->NumberOfBytes      = *NumberOfBytes;
1112     MapInfo->NumberOfPages      = EFI_SIZE_TO_PAGES (*NumberOfBytes);
1113     MapInfo->HostAddress        = PhysicalAddress;
1114     MapInfo->MappedHostAddress  = DMA_MEMORY_TOP;
1115 
1116     //
1117     // Allocate a buffer below DMA_MEMORY_TOP to map the transfer to.
1118     //
1119     Status = gBS->AllocatePages (
1120                     AllocateMaxAddress,
1121                     EfiBootServicesData,
1122                     MapInfo->NumberOfPages,
1123                     &MapInfo->MappedHostAddress
1124                     );
1125     if (EFI_ERROR (Status)) {
1126       gBS->FreePool (MapInfo);
1127       *NumberOfBytes = 0;
1128       return Status;
1129     }
1130     //
1131     // If this is a read operation from the Bus Master's point of view,
1132     // then copy the contents of the real buffer into the mapped buffer
1133     // so the Bus Master can read the contents of the real buffer.
1134     //
1135     if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
1136       CopyMem (
1137         (VOID *) (UINTN) MapInfo->MappedHostAddress,
1138         (VOID *) (UINTN) MapInfo->HostAddress,
1139         MapInfo->NumberOfBytes
1140         );
1141     }
1142     //
1143     // The DeviceAddress is the address of the maped buffer below DMA_MEMORY_TOP
1144     //
1145     *DeviceAddress = MapInfo->MappedHostAddress;
1146   } else {
1147     //
1148     // The transfer is below DMA_MEMORY_TOP, so the DeviceAddress is simply the HostAddress
1149     //
1150     *DeviceAddress = PhysicalAddress;
1151   }
1152 
1153   return EFI_SUCCESS;
1154 }
1155 
1156 EFI_STATUS
1157 EFIAPI
RootBridgeIoUnmap(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN VOID * Mapping)1158 RootBridgeIoUnmap (
1159   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
1160   IN VOID                             *Mapping
1161   )
1162 /*++
1163 
1164 Routine Description:
1165 
1166   Completes the Map() operation and releases any corresponding resources.
1167 
1168 Arguments:
1169 
1170   This     -  Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1171   Mapping  -  The value returned from Map() operation.
1172 
1173 Returns:
1174 
1175   EFI_SUCCESS            -  The range was unmapped successfully.
1176   EFI_INVALID_PARAMETER  -  Mapping is not a value that was returned
1177                             by Map operation.
1178   EFI_DEVICE_ERROR       -  The data was not committed to the target
1179                             system memory.
1180 
1181 --*/
1182 {
1183   MAP_INFO  *MapInfo;
1184 
1185   //
1186   // See if the Map() operation associated with this Unmap() required a mapping buffer.
1187   // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
1188   //
1189   if (Mapping != NULL) {
1190     //
1191     // Get the MAP_INFO structure from Mapping
1192     //
1193     MapInfo = (MAP_INFO *) Mapping;
1194 
1195     //
1196     // If this is a write operation from the Bus Master's point of view,
1197     // then copy the contents of the mapped buffer into the real buffer
1198     // so the processor can read the contents of the real buffer.
1199     //
1200     if ((MapInfo->Operation == EfiPciOperationBusMasterWrite) ||
1201         (MapInfo->Operation == EfiPciOperationBusMasterWrite64)
1202         ) {
1203       CopyMem (
1204         (VOID *) (UINTN) MapInfo->HostAddress,
1205         (VOID *) (UINTN) MapInfo->MappedHostAddress,
1206         MapInfo->NumberOfBytes
1207         );
1208     }
1209     //
1210     // Free the mapped buffer and the MAP_INFO structure.
1211     //
1212     gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
1213     gBS->FreePool (Mapping);
1214   }
1215 
1216   return EFI_SUCCESS;
1217 }
1218 
1219 EFI_STATUS
1220 EFIAPI
RootBridgeIoAllocateBuffer(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,OUT VOID ** HostAddress,IN UINT64 Attributes)1221 RootBridgeIoAllocateBuffer (
1222   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
1223   IN  EFI_ALLOCATE_TYPE                Type,
1224   IN  EFI_MEMORY_TYPE                  MemoryType,
1225   IN  UINTN                            Pages,
1226   OUT VOID                             **HostAddress,
1227   IN  UINT64                           Attributes
1228   )
1229 /*++
1230 
1231 Routine Description:
1232 
1233   Allocates pages that are suitable for a common buffer mapping.
1234 
1235 Arguments:
1236 
1237   This         -  Pointer to EFI_ROOT_BRIDGE_IO_PROTOCOL instance.
1238   Type         -  Not used and can be ignored.
1239   MemoryType   -  Type of memory to allocate.
1240   Pages        -  Number of pages to allocate.
1241   HostAddress  -  Pointer to store the base system memory address
1242                   of the allocated range.
1243   Attributes   -  Requested bit mask of attributes of the allocated
1244                   range.
1245 
1246 Returns:
1247 
1248   EFI_SUCCESS            -  The requested memory range were allocated.
1249   EFI_INVALID_PARAMETER  -  Invalid parameter found.
1250   EFI_UNSUPPORTED        -  Attributes is unsupported.
1251 
1252 --*/
1253 {
1254   EFI_STATUS            Status;
1255   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
1256 
1257   //
1258   // Validate Attributes
1259   //
1260   if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
1261     return EFI_UNSUPPORTED;
1262   }
1263   //
1264   // Check for invalid inputs
1265   //
1266   if (HostAddress == NULL) {
1267     return EFI_INVALID_PARAMETER;
1268   }
1269   //
1270   // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1271   //
1272   if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
1273     return EFI_INVALID_PARAMETER;
1274   }
1275   //
1276   // Limit allocations to memory below DMA_MEMORY_TOP
1277   //
1278   PhysicalAddress = DMA_MEMORY_TOP;
1279 
1280   Status = gBS->AllocatePages (
1281                   AllocateMaxAddress,
1282                   MemoryType,
1283                   Pages,
1284                   &PhysicalAddress
1285                   );
1286   if (EFI_ERROR (Status)) {
1287     return Status;
1288   }
1289 
1290   *HostAddress = (VOID *) (UINTN) PhysicalAddress;
1291 
1292   return EFI_SUCCESS;
1293 }
1294 
1295 EFI_STATUS
1296 EFIAPI
RootBridgeIoFreeBuffer(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN UINTN Pages,OUT VOID * HostAddress)1297 RootBridgeIoFreeBuffer (
1298   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
1299   IN  UINTN                            Pages,
1300   OUT VOID                             *HostAddress
1301   )
1302 /*++
1303 
1304 Routine Description:
1305 
1306   Free memory allocated in AllocateBuffer.
1307 
1308 Arguments:
1309 
1310   This         -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1311                   instance.
1312   Pages        -  Number of pages to free.
1313   HostAddress  -  The base system memory address of the
1314                   allocated range.
1315 
1316 Returns:
1317 
1318   EFI_SUCCESS            -  Requested memory pages were freed.
1319   EFI_INVALID_PARAMETER  -  Invalid parameter found.
1320 
1321 --*/
1322 {
1323   return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
1324 }
1325 
1326 EFI_STATUS
1327 EFIAPI
RootBridgeIoFlush(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This)1328 RootBridgeIoFlush (
1329   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       *This
1330   )
1331 /*++
1332 
1333 Routine Description:
1334 
1335   Flushes all PCI posted write transactions from a PCI host
1336   bridge to system memory.
1337 
1338 Arguments:
1339 
1340   This  - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1341 
1342 Returns:
1343 
1344   EFI_SUCCESS       -  PCI posted write transactions were flushed
1345                        from PCI host bridge to system memory.
1346   EFI_DEVICE_ERROR  -  Fail due to hardware error.
1347 
1348 --*/
1349 {
1350   //
1351   // not supported yet
1352   //
1353   return EFI_SUCCESS;
1354 }
1355 
1356 EFI_STATUS
1357 EFIAPI
RootBridgeIoGetAttributes(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,OUT UINT64 * Supported,OUT UINT64 * Attributes)1358 RootBridgeIoGetAttributes (
1359   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
1360   OUT UINT64                           *Supported,
1361   OUT UINT64                           *Attributes
1362   )
1363 /*++
1364 
1365 Routine Description:
1366 
1367   Get the attributes that a PCI root bridge supports and
1368   the attributes the PCI root bridge is currently using.
1369 
1370 Arguments:
1371 
1372   This        -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1373                  instance.
1374   Supports    -  A pointer to the mask of attributes that
1375                  this PCI root bridge supports.
1376   Attributes  -  A pointer to the mask of attributes that
1377                  this PCI root bridge is currently using.
1378 Returns:
1379 
1380   EFI_SUCCESS            -  Success.
1381   EFI_INVALID_PARAMETER  -  Invalid parameter found.
1382 
1383 --*/
1384 
1385 // GC_TODO:    Supported - add argument and description to function comment
1386 //
1387 // GC_TODO:    Supported - add argument and description to function comment
1388 //
1389 // GC_TODO:    Supported - add argument and description to function comment
1390 //
1391 {
1392   PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
1393 
1394   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
1395 
1396   if (Attributes == NULL && Supported == NULL) {
1397     return EFI_INVALID_PARAMETER;
1398   }
1399   //
1400   // Set the return value for Supported and Attributes
1401   //
1402   if (Supported) {
1403     *Supported = PrivateData->Supports;
1404   }
1405 
1406   if (Attributes) {
1407     *Attributes = PrivateData->Attributes;
1408   }
1409 
1410   return EFI_SUCCESS;
1411 }
1412 
1413 EFI_STATUS
1414 EFIAPI
RootBridgeIoSetAttributes(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN UINT64 Attributes,IN OUT UINT64 * ResourceBase,IN OUT UINT64 * ResourceLength)1415 RootBridgeIoSetAttributes (
1416   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
1417   IN     UINT64                           Attributes,
1418   IN OUT UINT64                           *ResourceBase,
1419   IN OUT UINT64                           *ResourceLength
1420   )
1421 /*++
1422 
1423 Routine Description:
1424 
1425   Sets the attributes for a resource range on a PCI root bridge.
1426 
1427 Arguments:
1428 
1429   This            -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1430   Attributes      -  The mask of attributes to set.
1431   ResourceBase    -  Pointer to the base address of the resource range
1432                      to be modified by the attributes specified by Attributes.
1433   ResourceLength  -  Pointer to the length of the resource range to be modified.
1434 
1435 Returns:
1436   EFI_SUCCESS            -  Success.
1437   EFI_INVALID_PARAMETER  -  Invalid parameter found.
1438   EFI_OUT_OF_RESOURCES   -  Not enough resources to set the attributes upon.
1439 
1440 --*/
1441 
1442 //
1443 // GC_TODO:    EFI_UNSUPPORTED - add return value to function comment
1444 //
1445 {
1446   PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
1447 
1448   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
1449 
1450   if (Attributes != 0) {
1451     Attributes &= (PrivateData->Supports);
1452     if (Attributes == 0) {
1453       return EFI_UNSUPPORTED;
1454     }
1455   }
1456 
1457   if (Attributes == PrivateData->Attributes) {
1458     return EFI_SUCCESS;
1459   }
1460   //
1461   // It is just a trick for some attribute can only be enabled or disabled
1462   // otherwise it can impact on other devices
1463   //
1464   PrivateData->Attributes = Attributes;
1465 
1466   return EFI_SUCCESS;
1467 }
1468 
1469 EFI_STATUS
1470 EFIAPI
RootBridgeIoConfiguration(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,OUT VOID ** Resources)1471 RootBridgeIoConfiguration (
1472   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
1473   OUT VOID                             **Resources
1474   )
1475 /*++
1476 
1477 Routine Description:
1478 
1479   Retrieves the current resource settings of this PCI root bridge
1480   in the form of a set of ACPI 2.0 resource descriptor.
1481 
1482 Arguments:
1483 
1484   This       -  Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1485   Resources  -  Pointer to the ACPI 2.0 resource descriptor that
1486                 describe the current configuration of this PCI root
1487                 bridge.
1488 
1489 Returns:
1490 
1491   EFI_SUCCESS      -  Success.
1492   EFI_UNSUPPORTED  -  Current configuration of the PCI root bridge
1493                       could not be retrieved.
1494 
1495 --*/
1496 
1497 //
1498 // GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
1499 //
1500 {
1501   EFI_STATUS                        Status;
1502   UINTN                             Idx;
1503 
1504   PCI_ROOT_BRIDGE_INSTANCE          *RbPrivateData;
1505   PCI_RES_NODE                      *ResAllocNode;
1506   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Config;
1507 
1508   //
1509   // Get this instance of the Root Bridge.
1510   //
1511   RbPrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
1512 
1513   //
1514   // If the pointer is not NULL, it points to a buffer already allocated.
1515   //
1516   if (RbPrivateData->ConfigBuffer == NULL) {
1517     Status = gBS->AllocatePool (
1518                     EfiBootServicesData,
1519                     TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
1520                     &RbPrivateData->ConfigBuffer
1521                     );
1522     if (EFI_ERROR (Status)) {
1523       return EFI_OUT_OF_RESOURCES;
1524     }
1525   }
1526 
1527   Config = RbPrivateData->ConfigBuffer;
1528 
1529   ZeroMem (Config, TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1530 
1531   for (Idx = 0; Idx < TypeMax; Idx++) {
1532 
1533     ResAllocNode = &RbPrivateData->ResAllocNode[Idx];
1534 
1535     if (ResAllocNode->Status != ResAllocated) {
1536       continue;
1537     }
1538 
1539     switch (ResAllocNode->Type) {
1540 
1541     case TypeIo:
1542       Config->Desc          = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1543       Config->Len           = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1544       Config->ResType       = ACPI_ADDRESS_SPACE_TYPE_IO;
1545       Config->AddrRangeMin  = ResAllocNode->Base;
1546       Config->AddrRangeMax  = ResAllocNode->Base + ResAllocNode->Length - 1;
1547       Config->AddrLen       = ResAllocNode->Length;
1548       break;
1549 
1550     case TypeMem32:
1551       Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1552       Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1553       Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
1554       Config->AddrSpaceGranularity  = 32;
1555       Config->AddrRangeMin          = ResAllocNode->Base;
1556       Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
1557       Config->AddrLen               = ResAllocNode->Length;
1558       break;
1559 
1560     case TypePMem32:
1561       Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1562       Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1563       Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
1564       Config->SpecificFlag          = 6;
1565       Config->AddrSpaceGranularity  = 32;
1566       Config->AddrRangeMin          = ResAllocNode->Base;
1567       Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
1568       Config->AddrLen               = ResAllocNode->Length;
1569       break;
1570 
1571     case TypeMem64:
1572       Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1573       Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1574       Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
1575       Config->SpecificFlag          = 6;
1576       Config->AddrSpaceGranularity  = 64;
1577       Config->AddrRangeMin          = ResAllocNode->Base;
1578       Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
1579       Config->AddrLen               = ResAllocNode->Length;
1580       break;
1581 
1582     case TypePMem64:
1583       Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1584       Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1585       Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
1586       Config->SpecificFlag          = 6;
1587       Config->AddrSpaceGranularity  = 64;
1588       Config->AddrRangeMin          = ResAllocNode->Base;
1589       Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
1590       Config->AddrLen               = ResAllocNode->Length;
1591       break;
1592 
1593     case TypeBus:
1594       Config->Desc          = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1595       Config->Len           = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1596       Config->ResType       = ACPI_ADDRESS_SPACE_TYPE_BUS;
1597       Config->AddrRangeMin  = ResAllocNode->Base;
1598       Config->AddrRangeMax  = ResAllocNode->Base + ResAllocNode->Length - 1;
1599       Config->AddrLen       = ResAllocNode->Length;
1600       break;
1601 
1602     default:
1603       break;
1604     }
1605 
1606     Config++;
1607   }
1608   //
1609   // Terminate the entries.
1610   //
1611   ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Desc      = ACPI_END_TAG_DESCRIPTOR;
1612   ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Checksum  = 0x0;
1613 
1614   *Resources = RbPrivateData->ConfigBuffer;
1615   return EFI_SUCCESS;
1616 }
1617