• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2014, AppliedMicro Corp. All rights reserved.
3  * Copyright (c) 2016, Hisilicon Limited. All rights reserved.
4  * Copyright (c) 2016, Linaro Limited. 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 #include <Library/DevicePathLib.h>
18 #include <Library/DmaLib.h>
19 #include <Library/PciExpressLib.h>
20 #include <Regs/HisiPcieV1RegOffset.h>
21 
22 
23 typedef struct {
24   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     SpaceDesp[TypeMax];
25   EFI_ACPI_END_TAG_DESCRIPTOR           EndDesp;
26 } RESOURCE_CONFIGURATION;
27 
28 RESOURCE_CONFIGURATION Configuration = {
29   {{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0},
30   {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0},
31   {0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0},
32   {0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0},
33   {0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0},
34   {0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0}},
35   {0x79, 0}
36 };
37 
38 //
39 // Protocol Member Function Prototypes
40 //
41 
42 /**
43    Polls an address in memory mapped I/O space until an exit condition is met, or
44    a timeout occurs.
45 
46    This function provides a standard way to poll a PCI memory location. A PCI memory read
47    operation is performed at the PCI memory address specified by Address for the width specified
48    by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
49    read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
50    Mask) is equal to Value.
51 
52    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
53    @param[in]   Width     Signifies the width of the memory operations.
54    @param[in]   Address   The base address of the memory operations. The caller is
55                           responsible for aligning Address if required.
56    @param[in]   Mask      Mask used for the polling criteria. Bytes above Width in Mask
57                           are ignored. The bits in the bytes below Width which are zero in
58                           Mask are ignored when polling the memory address.
59    @param[in]   Value     The comparison value used for the polling exit criteria.
60    @param[in]   Delay     The number of 100 ns units to poll. Note that timer available may
61                           be of poorer granularity.
62    @param[out]  Result    Pointer to the last value read from the memory location.
63 
64    @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
65    @retval EFI_INVALID_PARAMETER  Width is invalid.
66    @retval EFI_INVALID_PARAMETER  Result is NULL.
67    @retval EFI_TIMEOUT            Delay expired before a match occurred.
68    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
69 
70 **/
71 EFI_STATUS
72 EFIAPI
73 RootBridgeIoPollMem (
74   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
75   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
76   IN  UINT64                                 Address,
77   IN  UINT64                                 Mask,
78   IN  UINT64                                 Value,
79   IN  UINT64                                 Delay,
80   OUT UINT64                                 *Result
81   );
82 
83 /**
84    Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
85    satisfied or after a defined duration.
86 
87    This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
88    performed at the PCI I/O address specified by Address for the width specified by Width.
89    The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
90    repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
91    to Value.
92 
93    @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
94    @param[in] Width     Signifies the width of the I/O operations.
95    @param[in] Address   The base address of the I/O operations. The caller is responsible
96                         for aligning Address if required.
97    @param[in] Mask      Mask used for the polling criteria. Bytes above Width in Mask
98                         are ignored. The bits in the bytes below Width which are zero in
99                         Mask are ignored when polling the I/O address.
100    @param[in] Value     The comparison value used for the polling exit criteria.
101    @param[in] Delay     The number of 100 ns units to poll. Note that timer available may
102                         be of poorer granularity.
103    @param[out] Result   Pointer to the last value read from the memory location.
104 
105    @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
106    @retval EFI_INVALID_PARAMETER  Width is invalid.
107    @retval EFI_INVALID_PARAMETER  Result is NULL.
108    @retval EFI_TIMEOUT            Delay expired before a match occurred.
109    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
110 
111 **/
112 EFI_STATUS
113 EFIAPI
114 RootBridgeIoPollIo (
115   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
116   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
117   IN  UINT64                                 Address,
118   IN  UINT64                                 Mask,
119   IN  UINT64                                 Value,
120   IN  UINT64                                 Delay,
121   OUT UINT64                                 *Result
122   );
123 
124 /**
125    Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
126 
127    The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
128    registers in the PCI root bridge memory space.
129    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
130    any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
131 
132    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
133    @param[in]   Width     Signifies the width of the memory operation.
134    @param[in]   Address   The base address of the memory operation. The caller is
135                           responsible for aligning the Address if required.
136    @param[in]   Count     The number of memory operations to perform. Bytes moved is
137                           Width size * Count, starting at Address.
138    @param[out]  Buffer    For read operations, the destination buffer to store the results. For
139                           write operations, the source buffer to write data from.
140 
141    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
142    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
143    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
144    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
145 
146 **/
147 EFI_STATUS
148 EFIAPI
149 RootBridgeIoMemRead (
150   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
151   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
152   IN     UINT64                                 Address,
153   IN     UINTN                                  Count,
154   OUT    VOID                                   *Buffer
155   );
156 
157 /**
158    Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
159 
160    The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
161    registers in the PCI root bridge memory space.
162    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
163    any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
164 
165    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
166    @param[in]   Width     Signifies the width of the memory operation.
167    @param[in]   Address   The base address of the memory operation. The caller is
168                           responsible for aligning the Address if required.
169    @param[in]   Count     The number of memory operations to perform. Bytes moved is
170                           Width size * Count, starting at Address.
171    @param[in]   Buffer    For read operations, the destination buffer to store the results. For
172                           write operations, the source buffer to write data from.
173 
174    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
175    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
176    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
177    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
178 **/
179 EFI_STATUS
180 EFIAPI
181 RootBridgeIoMemWrite (
182   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
183   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
184   IN     UINT64                                 Address,
185   IN     UINTN                                  Count,
186   IN     VOID                                   *Buffer
187   );
188 
189 /**
190    Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
191 
192    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
193    @param[in]   Width       Signifies the width of the memory operations.
194    @param[in]   UserAddress The base address of the I/O operation. The caller is responsible for
195                             aligning the Address if required.
196    @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
197                             size * Count, starting at Address.
198    @param[out]  UserBuffer  For read operations, the destination buffer to store the results. For
199                             write operations, the source buffer to write data from.
200 
201    @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
202    @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
203    @retval EFI_INVALID_PARAMETER    Buffer is NULL.
204    @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
205 
206 **/
207 EFI_STATUS
208 EFIAPI
209 RootBridgeIoIoRead (
210   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
211   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
212   IN     UINT64                                 UserAddress,
213   IN     UINTN                                  Count,
214   OUT    VOID                                   *UserBuffer
215   );
216 
217 /**
218    Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
219 
220    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
221    @param[in]   Width       Signifies the width of the memory operations.
222    @param[in]   UserAddress The base address of the I/O operation. The caller is responsible for
223                             aligning the Address if required.
224    @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
225                             size * Count, starting at Address.
226    @param[in]   UserBuffer  For read operations, the destination buffer to store the results. For
227                             write operations, the source buffer to write data from.
228 
229    @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
230    @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
231    @retval EFI_INVALID_PARAMETER    Buffer is NULL.
232    @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
233 
234 **/
235 EFI_STATUS
236 EFIAPI
237 RootBridgeIoIoWrite (
238   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
239   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
240   IN     UINT64                                 UserAddress,
241   IN     UINTN                                  Count,
242   IN     VOID                                   *UserBuffer
243   );
244 
245 /**
246    Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
247    root bridge memory space.
248 
249    The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
250    space to another region of PCI root bridge memory space. This is especially useful for video scroll
251    operation on a memory mapped video buffer.
252    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
253    any alignment and memory width restrictions that a PCI root bridge on a platform might require.
254 
255    @param[in] This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
256    @param[in] Width       Signifies the width of the memory operations.
257    @param[in] DestAddress The destination address of the memory operation. The caller is
258                           responsible for aligning the DestAddress if required.
259    @param[in] SrcAddress  The source address of the memory operation. The caller is
260                           responsible for aligning the SrcAddress if required.
261    @param[in] Count       The number of memory operations to perform. Bytes moved is
262                           Width size * Count, starting at DestAddress and SrcAddress.
263 
264    @retval  EFI_SUCCESS             The data was copied from one memory region to another memory region.
265    @retval  EFI_INVALID_PARAMETER   Width is invalid for this PCI root bridge.
266    @retval  EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.
267 
268 **/
269 EFI_STATUS
270 EFIAPI
271 RootBridgeIoCopyMem (
272   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
273   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
274   IN     UINT64                                 DestAddress,
275   IN     UINT64                                 SrcAddress,
276   IN     UINTN                                  Count
277   );
278 
279 /**
280    Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
281 
282    The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
283    registers for a PCI controller.
284    The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
285    any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
286    require.
287 
288    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
289    @param[in]   Width     Signifies the width of the memory operations.
290    @param[in]   Address   The address within the PCI configuration space for the PCI controller.
291    @param[in]   Count     The number of PCI configuration operations to perform. Bytes
292                           moved is Width size * Count, starting at Address.
293    @param[out]  Buffer    For read operations, the destination buffer to store the results. For
294                           write operations, the source buffer to write data from.
295 
296    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
297    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
298    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
299    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
300 
301 **/
302 EFI_STATUS
303 EFIAPI
304 RootBridgeIoPciRead (
305   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
306   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
307   IN     UINT64                                 Address,
308   IN     UINTN                                  Count,
309   OUT    VOID                                   *Buffer
310   );
311 
312 /**
313    Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
314 
315    The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
316    registers for a PCI controller.
317    The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
318    any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
319    require.
320 
321    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
322    @param[in]   Width     Signifies the width of the memory operations.
323    @param[in]   Address   The address within the PCI configuration space for the PCI controller.
324    @param[in]   Count     The number of PCI configuration operations to perform. Bytes
325                           moved is Width size * Count, starting at Address.
326    @param[in]   Buffer    For read operations, the destination buffer to store the results. For
327                           write operations, the source buffer to write data from.
328 
329    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
330    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
331    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
332    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
333 
334 **/
335 EFI_STATUS
336 EFIAPI
337 RootBridgeIoPciWrite (
338   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
339   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
340   IN     UINT64                                 Address,
341   IN     UINTN                                  Count,
342   IN     VOID                                   *Buffer
343   );
344 
345 /**
346    Provides the PCI controller-specific addresses required to access system memory from a
347    DMA bus master.
348 
349    The Map() function provides the PCI controller specific addresses needed to access system
350    memory. This function is used to map system memory for PCI bus master DMA accesses.
351 
352    @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
353    @param[in]       Operation       Indicates if the bus master is going to read or write to system memory.
354    @param[in]       HostAddress     The system memory address to map to the PCI controller.
355    @param[in, out]  NumberOfBytes   On input the number of bytes to map. On output the number of bytes that were mapped.
356    @param[out]      DeviceAddress   The resulting map address for the bus master PCI controller to use
357                                     to access the system memory's HostAddress.
358    @param[out]      Mapping         The value to pass to Unmap() when the bus master DMA operation is complete.
359 
360    @retval EFI_SUCCESS            The range was mapped for the returned NumberOfBytes.
361    @retval EFI_INVALID_PARAMETER  Operation is invalid.
362    @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
363    @retval EFI_INVALID_PARAMETER  NumberOfBytes is NULL.
364    @retval EFI_INVALID_PARAMETER  DeviceAddress is NULL.
365    @retval EFI_INVALID_PARAMETER  Mapping is NULL.
366    @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common buffer.
367    @retval EFI_DEVICE_ERROR       The system hardware could not map the requested address.
368    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
369 
370 **/
371 EFI_STATUS
372 EFIAPI
373 RootBridgeIoMap (
374   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
375   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
376   IN     VOID                                       *HostAddress,
377   IN OUT UINTN                                      *NumberOfBytes,
378   OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
379   OUT    VOID                                       **Mapping
380   );
381 
382 /**
383    Completes the Map() operation and releases any corresponding resources.
384 
385    The Unmap() function completes the Map() operation and releases any corresponding resources.
386    If the operation was an EfiPciOperationBusMasterWrite or
387    EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
388    Any resources used for the mapping are freed.
389 
390    @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
391    @param[in] Mapping   The mapping value returned from Map().
392 
393    @retval EFI_SUCCESS            The range was unmapped.
394    @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
395    @retval EFI_DEVICE_ERROR       The data was not committed to the target system memory.
396 
397 **/
398 EFI_STATUS
399 EFIAPI
400 RootBridgeIoUnmap (
401   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
402   IN  VOID                             *Mapping
403   );
404 
405 /**
406    Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
407    EfiPciOperationBusMasterCommonBuffer64 mapping.
408 
409    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
410    @param Type        This parameter is not used and must be ignored.
411    @param MemoryType  The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
412    @param Pages       The number of pages to allocate.
413    @param HostAddress A pointer to store the base system memory address of the allocated range.
414    @param Attributes  The requested bit mask of attributes for the allocated range. Only
415                       the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
416                       and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
417 
418    @retval EFI_SUCCESS            The requested memory pages were allocated.
419    @retval EFI_INVALID_PARAMETER  MemoryType is invalid.
420    @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
421    @retval EFI_UNSUPPORTED        Attributes is unsupported. The only legal attribute bits are
422                                   MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
423    @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
424 
425 **/
426 EFI_STATUS
427 EFIAPI
428 RootBridgeIoAllocateBuffer (
429   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
430   IN  EFI_ALLOCATE_TYPE                Type,
431   IN  EFI_MEMORY_TYPE                  MemoryType,
432   IN  UINTN                            Pages,
433   OUT VOID                             **HostAddress,
434   IN  UINT64                           Attributes
435   );
436 
437 /**
438    Frees memory that was allocated with AllocateBuffer().
439 
440    The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
441 
442    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
443    @param Pages       The number of pages to free.
444    @param HostAddress The base system memory address of the allocated range.
445 
446    @retval EFI_SUCCESS            The requested memory pages were freed.
447    @retval EFI_INVALID_PARAMETER  The memory range specified by HostAddress and Pages
448                                   was not allocated with AllocateBuffer().
449 
450 **/
451 EFI_STATUS
452 EFIAPI
453 RootBridgeIoFreeBuffer (
454   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
455   IN  UINTN                            Pages,
456   OUT VOID                             *HostAddress
457   );
458 
459 /**
460    Flushes all PCI posted write transactions from a PCI host bridge to system memory.
461 
462    The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
463    memory. Posted write transactions are generated by PCI bus masters when they perform write
464    transactions to target addresses in system memory.
465    This function does not flush posted write transactions from any PCI bridges. A PCI controller
466    specific action must be taken to guarantee that the posted write transactions have been flushed from
467    the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
468    a PCI read transaction from the PCI controller prior to calling Flush().
469 
470    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
471 
472    @retval EFI_SUCCESS        The PCI posted write transactions were flushed from the PCI host
473                               bridge to system memory.
474    @retval EFI_DEVICE_ERROR   The PCI posted write transactions were not flushed from the PCI
475                               host bridge due to a hardware error.
476 
477 **/
478 EFI_STATUS
479 EFIAPI
480 RootBridgeIoFlush (
481   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
482   );
483 
484 /**
485    Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
486    attributes that a PCI root bridge is currently using.
487 
488    The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
489    and the mask of attributes that the PCI root bridge is currently using.
490 
491    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
492    @param Supported   A pointer to the mask of attributes that this PCI root bridge
493                       supports setting with SetAttributes().
494    @param Attributes  A pointer to the mask of attributes that this PCI root bridge is
495                       currently using.
496 
497    @retval  EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI root
498                                   bridge supports is returned in Supports. If Attributes is
499                                   not NULL, then the attributes that the PCI root bridge is currently
500                                   using is returned in Attributes.
501    @retval  EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
502 
503 **/
504 EFI_STATUS
505 EFIAPI
506 RootBridgeIoGetAttributes (
507   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
508   OUT UINT64                           *Supported,
509   OUT UINT64                           *Attributes
510   );
511 
512 /**
513    Sets attributes for a resource range on a PCI root bridge.
514 
515    The SetAttributes() function sets the attributes specified in Attributes for the PCI root
516    bridge on the resource range specified by ResourceBase and ResourceLength. Since the
517    granularity of setting these attributes may vary from resource type to resource type, and from
518    platform to platform, the actual resource range and the one passed in by the caller may differ. As a
519    result, this function may set the attributes specified by Attributes on a larger resource range
520    than the caller requested. The actual range is returned in ResourceBase and
521    ResourceLength. The caller is responsible for verifying that the actual range for which the
522    attributes were set is acceptable.
523 
524    @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
525    @param[in]       Attributes      The mask of attributes to set. If the attribute bit
526                                     MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
527                                     MEMORY_DISABLE is set, then the resource range is specified by
528                                     ResourceBase and ResourceLength. If
529                                     MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
530                                     MEMORY_DISABLE are not set, then ResourceBase and
531                                     ResourceLength are ignored, and may be NULL.
532    @param[in, out]  ResourceBase    A pointer to the base address of the resource range to be modified
533                                     by the attributes specified by Attributes.
534    @param[in, out]  ResourceLength  A pointer to the length of the resource range to be modified by the
535                                     attributes specified by Attributes.
536 
537    @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
538    @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
539    @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
540 
541 **/
542 EFI_STATUS
543 EFIAPI
544 RootBridgeIoSetAttributes (
545   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
546   IN     UINT64                           Attributes,
547   IN OUT UINT64                           *ResourceBase,
548   IN OUT UINT64                           *ResourceLength
549   );
550 
551 /**
552    Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
553    resource descriptors.
554 
555    There are only two resource descriptor types from the ACPI Specification that may be used to
556    describe the current resources allocated to a PCI root bridge. These are the QWORD Address
557    Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
558    QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
559    or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
560    Address Space Descriptors followed by an End Tag.
561 
562    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
563    @param[out]  Resources   A pointer to the ACPI 2.0 resource descriptors that describe the
564                             current configuration of this PCI root bridge. The storage for the
565                             ACPI 2.0 resource descriptors is allocated by this function. The
566                             caller must treat the return buffer as read-only data, and the buffer
567                             must not be freed by the caller.
568 
569    @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
570    @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
571    @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
572 
573 **/
574 EFI_STATUS
575 EFIAPI
576 RootBridgeIoConfiguration (
577   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
578   OUT    VOID                             **Resources
579   );
580 
581 //
582 // Memory Controller Pci Root Bridge Io Module Variables
583 //
584 EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
585 
586 //
587 // Lookup table for increment values based on transfer widths
588 //
589 UINT8 mInStride[] = {
590   1, // EfiPciWidthUint8
591   2, // EfiPciWidthUint16
592   4, // EfiPciWidthUint32
593   8, // EfiPciWidthUint64
594   0, // EfiPciWidthFifoUint8
595   0, // EfiPciWidthFifoUint16
596   0, // EfiPciWidthFifoUint32
597   0, // EfiPciWidthFifoUint64
598   1, // EfiPciWidthFillUint8
599   2, // EfiPciWidthFillUint16
600   4, // EfiPciWidthFillUint32
601   8  // EfiPciWidthFillUint64
602 };
603 
604 //
605 // Lookup table for increment values based on transfer widths
606 //
607 UINT8 mOutStride[] = {
608   1, // EfiPciWidthUint8
609   2, // EfiPciWidthUint16
610   4, // EfiPciWidthUint32
611   8, // EfiPciWidthUint64
612   1, // EfiPciWidthFifoUint8
613   2, // EfiPciWidthFifoUint16
614   4, // EfiPciWidthFifoUint32
615   8, // EfiPciWidthFifoUint64
616   0, // EfiPciWidthFillUint8
617   0, // EfiPciWidthFillUint16
618   0, // EfiPciWidthFillUint32
619   0  // EfiPciWidthFillUint64
620 };
621 
622 
GetPcieCfgAddress(UINT64 Ecam,UINTN Bus,UINTN Device,UINTN Function,UINTN Reg)623 UINT64 GetPcieCfgAddress (
624     UINT64 Ecam,
625     UINTN Bus,
626     UINTN Device,
627     UINTN Function,
628     UINTN Reg
629     )
630 {
631   return Ecam + PCI_EXPRESS_LIB_ADDRESS (Bus, Device, Function, Reg);
632 }
633 
634 
SetAtuConfig0RW(PCI_ROOT_BRIDGE_INSTANCE * Private,UINT32 Index)635 void SetAtuConfig0RW (
636     PCI_ROOT_BRIDGE_INSTANCE *Private,
637     UINT32 Index
638     )
639 {
640     UINTN RbPciBase = Private->RbPciBar;
641     UINT64 MemLimit = GetPcieCfgAddress (Private->Ecam, Private->BusBase + 1, 1, 0, 0) - 1;
642 
643 
644     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index);
645     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(Private->Ecam));
646     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)(Private->Ecam) >> 32));
647     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32) MemLimit);
648     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, 0);
649     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, 0);
650     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_CONFIG0);
651     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_SHIIF_MODE);
652 
653     {
654       UINTN i;
655       for (i=0; i<0x20; i+=4) {
656         DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i)));
657       }
658     }
659 }
660 
SetAtuConfig1RW(PCI_ROOT_BRIDGE_INSTANCE * Private,UINT32 Index)661 void SetAtuConfig1RW (
662     PCI_ROOT_BRIDGE_INSTANCE *Private,
663     UINT32 Index
664     )
665 {
666     UINTN RbPciBase = Private->RbPciBar;
667     UINT64 MemLimit = GetPcieCfgAddress (Private->Ecam, Private->BusLimit + 1, 0, 0, 0) - 1;
668 
669 
670     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index);
671     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_CONFIG1);
672     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(Private->Ecam));
673     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)(Private->Ecam) >> 32));
674     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32) MemLimit);
675     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, 0);
676     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, 0);
677     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_SHIIF_MODE);
678 
679     {
680       UINTN i;
681       for (i=0; i<0x20; i+=4) {
682         DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i)));
683       }
684     }
685 }
686 
SetAtuIoRW(UINT64 RbPciBase,UINT64 IoBase,UINT64 CpuIoRegionLimit,UINT64 CpuIoRegionBase,UINT32 Index)687 void SetAtuIoRW(UINT64 RbPciBase,UINT64 IoBase,UINT64 CpuIoRegionLimit, UINT64 CpuIoRegionBase, UINT32 Index)
688 {
689 
690     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index);
691     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_IO);
692 
693     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(CpuIoRegionBase));
694     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)CpuIoRegionBase >> 32));
695     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32)(CpuIoRegionLimit));
696     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, (UINT32)(IoBase));
697     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, (UINT32)((UINT64)(IoBase) >> 32));
698 
699     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_NORMAL_MODE);
700 
701     {
702       UINTN i;
703       for (i=0; i<0x20; i+=4) {
704         DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i)));
705       }
706     }
707 }
708 
SetAtuMemRW(UINT64 RbPciBase,UINT64 MemBase,UINT64 CpuMemRegionLimit,UINT64 CpuMemRegionBase,UINT32 Index)709 void SetAtuMemRW(UINT64 RbPciBase,UINT64 MemBase,UINT64 CpuMemRegionLimit, UINT64 CpuMemRegionBase, UINT32 Index)
710 {
711 
712     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index);
713     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_MEM);
714 
715     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(CpuMemRegionBase));
716     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)(CpuMemRegionBase) >> 32));
717     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32)(CpuMemRegionLimit));
718     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, (UINT32)(MemBase));
719     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, (UINT32)((UINT64)(MemBase) >> 32));
720 
721     MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_NORMAL_MODE);
722 
723     {
724       UINTN i;
725       for (i=0; i<0x20; i+=4) {
726         DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i)));
727       }
728     }
729 }
730 
InitAtu(PCI_ROOT_BRIDGE_INSTANCE * Private)731 VOID InitAtu (PCI_ROOT_BRIDGE_INSTANCE *Private)
732 {
733   SetAtuMemRW (Private->RbPciBar, Private->PciRegionBase, Private->PciRegionLimit, Private->CpuMemRegionBase, 0);
734   SetAtuConfig0RW (Private, 1);
735   SetAtuConfig1RW (Private, 2);
736   SetAtuIoRW (Private->RbPciBar, Private->IoBase, Private->IoLimit, Private->CpuIoRegionBase, 3);
737 }
738 
739 
PcieIsLinkUp(UINT32 SocType,UINTN RbPciBar,UINTN Port)740 BOOLEAN PcieIsLinkUp (UINT32 SocType, UINTN RbPciBar, UINTN Port)
741 {
742     UINT32                     Value = 0;
743 
744     if (0x1610 == SocType)
745     {
746         Value = MmioRead32(RbPciBar + 0x131C);
747         if ((Value & 0x3F) == 0x11)
748         {
749             return TRUE;
750         }
751         return FALSE;
752     }
753     else
754     {
755         Value = MmioRead32 (0xb0000000 + 0x6818 + 0x100 * Port);
756         if ((Value & 0x3F) == 0x11)
757         {
758             return TRUE;
759         }
760         return FALSE;
761     }
762 }
763 
764 /**
765 
766   Construct the Pci Root Bridge Io protocol
767 
768   @param Protocol         Point to protocol instance
769   @param HostBridgeHandle Handle of host bridge
770   @param Attri            Attribute of host bridge
771   @param ResAppeture      ResourceAppeture for host bridge
772 
773   @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
774 
775 **/
776 EFI_STATUS
RootBridgeConstructor(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * Protocol,IN EFI_HANDLE HostBridgeHandle,IN UINT64 Attri,IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE * ResAppeture,IN UINT32 Seg)777 RootBridgeConstructor (
778   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    *Protocol,
779   IN EFI_HANDLE                         HostBridgeHandle,
780   IN UINT64                             Attri,
781   IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE  *ResAppeture,
782   IN UINT32                             Seg
783   )
784 {
785   EFI_STATUS                        Status;
786   PCI_ROOT_BRIDGE_INSTANCE          *PrivateData;
787   PCI_RESOURCE_TYPE                 Index;
788 
789   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
790 
791   //
792   // The host to pci bridge, the host memory and io addresses are
793   // direct mapped to pci addresses, so no need translate, set bases to 0.
794   //
795   PrivateData->MemBase = ResAppeture->MemBase;
796   PrivateData->IoBase  = ResAppeture->IoBase;
797   PrivateData->RbPciBar = ResAppeture->RbPciBar;
798   PrivateData->MemLimit = ResAppeture->MemLimit;
799   PrivateData->IoLimit  = ResAppeture->IoLimit;
800   PrivateData->Ecam = ResAppeture->Ecam;
801   PrivateData->CpuMemRegionBase = ResAppeture->CpuMemRegionBase;
802   PrivateData->CpuIoRegionBase = ResAppeture->CpuIoRegionBase;
803   PrivateData->PciRegionBase = ResAppeture->PciRegionBase;
804   PrivateData->PciRegionLimit = ResAppeture->PciRegionLimit;
805 
806   //
807   // Bus Appeture for this Root Bridge (Possible Range)
808   //
809   PrivateData->BusBase  = ResAppeture->BusBase;
810   PrivateData->BusLimit = ResAppeture->BusLimit;
811 
812   //
813   // Specific for this chipset
814   //
815   for (Index = TypeIo; Index < TypeMax; Index++) {
816     PrivateData->ResAllocNode[Index].Type      = Index;
817     PrivateData->ResAllocNode[Index].Base      = 0;
818     PrivateData->ResAllocNode[Index].Length    = 0;
819     PrivateData->ResAllocNode[Index].Status    = ResNone;
820   }
821 
822   PrivateData->RootBridgeAttrib = Attri;
823 
824   PrivateData->Supports    = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO | \
825                              EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO | \
826                              EFI_PCI_ATTRIBUTE_VGA_MEMORY | \
827                              EFI_PCI_ATTRIBUTE_VGA_IO_16  | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | \
828                              EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER;
829   PrivateData->Attributes  = PrivateData->Supports;
830 
831   Protocol->ParentHandle   = HostBridgeHandle;
832 
833   Protocol->PollMem        = RootBridgeIoPollMem;
834   Protocol->PollIo         = RootBridgeIoPollIo;
835 
836   Protocol->Mem.Read       = RootBridgeIoMemRead;
837   Protocol->Mem.Write      = RootBridgeIoMemWrite;
838 
839   Protocol->Io.Read        = RootBridgeIoIoRead;
840   Protocol->Io.Write       = RootBridgeIoIoWrite;
841 
842   Protocol->CopyMem        = RootBridgeIoCopyMem;
843 
844   Protocol->Pci.Read       = RootBridgeIoPciRead;
845   Protocol->Pci.Write      = RootBridgeIoPciWrite;
846 
847   Protocol->Map            = RootBridgeIoMap;
848   Protocol->Unmap          = RootBridgeIoUnmap;
849 
850   Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
851   Protocol->FreeBuffer     = RootBridgeIoFreeBuffer;
852 
853   Protocol->Flush          = RootBridgeIoFlush;
854 
855   Protocol->GetAttributes  = RootBridgeIoGetAttributes;
856   Protocol->SetAttributes  = RootBridgeIoSetAttributes;
857 
858   Protocol->Configuration  = RootBridgeIoConfiguration;
859 
860   Protocol->SegmentNumber  = Seg;
861 
862   InitAtu (PrivateData);
863 
864   Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome);
865   if (EFI_ERROR(Status))
866   {
867       DEBUG((EFI_D_ERROR,"LocateProtocol MetronomeArchProtocol Error\n"));
868   }
869 
870   return EFI_SUCCESS;
871 }
872 
873 /**
874   Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
875 
876   The I/O operations are carried out exactly as requested. The caller is responsible
877   for satisfying any alignment and I/O width restrictions that a PI System on a
878   platform might require. For example on some platforms, width requests of
879   EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
880   be handled by the driver.
881 
882   @param[in] This           A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
883   @param[in] OperationType  I/O operation type: IO/MMIO/PCI.
884   @param[in] Width          Signifies the width of the I/O or Memory operation.
885   @param[in] Address        The base address of the I/O operation.
886   @param[in] Count          The number of I/O operations to perform. The number of
887                             bytes moved is Width size * Count, starting at Address.
888   @param[in] Buffer         For read operations, the destination buffer to store the results.
889                             For write operations, the source buffer from which to write data.
890 
891   @retval EFI_SUCCESS            The parameters for this request pass the checks.
892   @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
893   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
894   @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
895   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
896                                  and Count is not valid for this PI system.
897 
898 **/
899 EFI_STATUS
RootBridgeIoCheckParameter(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN OPERATION_TYPE OperationType,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)900 RootBridgeIoCheckParameter (
901   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
902   IN OPERATION_TYPE                         OperationType,
903   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
904   IN UINT64                                 Address,
905   IN UINTN                                  Count,
906   IN VOID                                   *Buffer
907   )
908 {
909   PCI_ROOT_BRIDGE_INSTANCE                     *PrivateData;
910   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  *PciRbAddr;
911   UINT64                                       MaxCount;
912   UINT64                                       Base;
913   UINT64                                       Limit;
914 
915   //
916   // Check to see if Buffer is NULL
917   //
918   if (Buffer == NULL) {
919     return EFI_INVALID_PARAMETER;
920   }
921 
922   //
923   // Check to see if Width is in the valid range
924   //
925   if ((UINT32)Width >= EfiPciWidthMaximum) {
926     return EFI_INVALID_PARAMETER;
927   }
928 
929   //
930   // For FIFO type, the target address won't increase during the access,
931   // so treat Count as 1
932   //
933   if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
934     Count = 1;
935   }
936 
937   //
938   // Check to see if Width is in the valid range for I/O Port operations
939   //
940   Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
941   if ((OperationType != MemOperation) && (Width == EfiPciWidthUint64)) {
942     ASSERT (FALSE);
943     return EFI_INVALID_PARAMETER;
944   }
945 
946   //
947   // Check to see if Address is aligned
948   //
949   if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {
950     return EFI_UNSUPPORTED;
951   }
952 
953   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
954 
955   //
956   // Check to see if any address associated with this transfer exceeds the maximum
957   // allowed address.  The maximum address implied by the parameters passed in is
958   // Address + Size * Count.  If the following condition is met, then the transfer
959   // is not supported.
960   //
961   //    Address + Size * Count > Limit + 1
962   //
963   // Since Limit can be the maximum integer value supported by the CPU and Count
964   // can also be the maximum integer value supported by the CPU, this range
965   // check must be adjusted to avoid all oveflow conditions.
966   //
967   // The following form of the range check is equivalent but assumes that
968   // Limit is of the form (2^n - 1).
969   //
970   if (OperationType == IoOperation) {
971     Base = PrivateData->IoBase;
972     Limit = PrivateData->IoLimit;
973   } else if (OperationType == MemOperation) {
974     Base = PrivateData->MemBase;
975     Limit = PrivateData->MemLimit;
976   } else {
977     PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
978     if (PciRbAddr->Bus < PrivateData->BusBase || PciRbAddr->Bus > PrivateData->BusLimit) {
979       return EFI_INVALID_PARAMETER;
980     }
981 
982     /* The root complex has only one device / function */
983     if (PciRbAddr->Bus == PrivateData->BusBase && PciRbAddr->Device != 0) {
984       return EFI_INVALID_PARAMETER;
985     }
986 
987     /* The other side of the RC has only one device as well */
988     if (PciRbAddr->Bus == (PrivateData->BusBase + 1 ) && PciRbAddr->Device != 0) {
989       return EFI_INVALID_PARAMETER;
990     }
991 
992     if (PciRbAddr->Device > MAX_PCI_DEVICE_NUMBER || PciRbAddr->Function > MAX_PCI_FUNCTION_NUMBER) {
993       return EFI_INVALID_PARAMETER;
994     }
995 
996     if (PciRbAddr->ExtendedRegister != 0) {
997       Address = PciRbAddr->ExtendedRegister;
998     } else {
999       Address = PciRbAddr->Register;
1000     }
1001     Base = 0;
1002     Limit = MAX_PCI_REG_ADDRESS;
1003   }
1004 
1005   if (Address < Base) {
1006       return EFI_INVALID_PARAMETER;
1007   }
1008 
1009   if (Count == 0) {
1010     if (Address > Limit) {
1011       return EFI_UNSUPPORTED;
1012     }
1013   } else {
1014     MaxCount = RShiftU64 (Limit, Width);
1015     if (MaxCount < (Count - 1)) {
1016       return EFI_UNSUPPORTED;
1017     }
1018     if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
1019       return EFI_UNSUPPORTED;
1020     }
1021   }
1022 
1023   return EFI_SUCCESS;
1024 }
1025 
1026 /**
1027    Internal help function for read and write memory space.
1028 
1029    @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1030    @param[in]   Write         Switch value for Read or Write.
1031    @param[in]   Width         Signifies the width of the memory operations.
1032    @param[in]   UserAddress   The address within the PCI configuration space for the PCI controller.
1033    @param[in]   Count         The number of PCI configuration operations to perform. Bytes
1034                               moved is Width size * Count, starting at Address.
1035    @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
1036                               write operations, the source buffer to write data from.
1037 
1038    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1039    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1040    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1041    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1042 
1043 **/
1044 EFI_STATUS
RootBridgeIoMemRW(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN BOOLEAN Write,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)1045 RootBridgeIoMemRW (
1046   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1047   IN     BOOLEAN                                Write,
1048   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1049   IN     UINT64                                 Address,
1050   IN     UINTN                                  Count,
1051   IN OUT VOID                                   *Buffer
1052   )
1053 {
1054   EFI_STATUS                             Status;
1055   UINT8                                  InStride;
1056   UINT8                                  OutStride;
1057   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  OperationWidth;
1058   UINT8                                  *Uint8Buffer;
1059   PCI_ROOT_BRIDGE_INSTANCE              *PrivateData;
1060 
1061   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
1062   /* Address is bus resource */
1063   Address -= PrivateData->PciRegionBase;
1064   Address += PrivateData->CpuMemRegionBase;
1065 
1066   PCIE_DEBUG("RootBridgeIoMemRW Address:0x%llx\n", Address);
1067   PCIE_DEBUG("RootBridgeIoMemRW Count:0x%llx\n", Count);
1068   PCIE_DEBUG("RootBridgeIoMemRW Write:0x%llx\n", Write);
1069   PCIE_DEBUG("RootBridgeIoMemRW Width:0x%llx\n", Width);
1070 
1071   Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address, Count, Buffer);
1072   if (EFI_ERROR (Status)) {
1073     return Status;
1074   }
1075 
1076   InStride = mInStride[Width];
1077   OutStride = mOutStride[Width];
1078   OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
1079   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
1080     if (Write) {
1081       switch (OperationWidth) {
1082         case EfiPciWidthUint8:
1083           MmioWrite8 ((UINTN)Address, *Uint8Buffer);
1084           break;
1085         case EfiPciWidthUint16:
1086           MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
1087           break;
1088         case EfiPciWidthUint32:
1089           MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
1090           break;
1091         case EfiPciWidthUint64:
1092           MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
1093           break;
1094         default:
1095           //
1096           // The RootBridgeIoCheckParameter call above will ensure that this
1097           // path is not taken.
1098           //
1099           ASSERT (FALSE);
1100           break;
1101       }
1102     } else {
1103       switch (OperationWidth) {
1104         case EfiPciWidthUint8:
1105           *Uint8Buffer = MmioRead8 ((UINTN)Address);
1106           break;
1107         case EfiPciWidthUint16:
1108           *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
1109           break;
1110         case EfiPciWidthUint32:
1111           *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
1112           break;
1113         case EfiPciWidthUint64:
1114           *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
1115           break;
1116         default:
1117           //
1118           // The RootBridgeIoCheckParameter call above will ensure that this
1119           // path is not taken.
1120           //
1121           ASSERT (FALSE);
1122           break;
1123       }
1124     }
1125   }
1126   return EFI_SUCCESS;
1127 }
1128 
1129 /**
1130    Internal help function for read and write IO space.
1131 
1132    @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1133    @param[in]   Write         Switch value for Read or Write.
1134    @param[in]   Width         Signifies the width of the memory operations.
1135    @param[in]   UserAddress   The address within the PCI configuration space for the PCI controller.
1136    @param[in]   Count         The number of PCI configuration operations to perform. Bytes
1137                               moved is Width size * Count, starting at Address.
1138    @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
1139                               write operations, the source buffer to write data from.
1140 
1141    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1142    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1143    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1144    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1145 
1146 **/
1147 EFI_STATUS
RootBridgeIoIoRW(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN BOOLEAN Write,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)1148 RootBridgeIoIoRW (
1149   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1150   IN     BOOLEAN                                Write,
1151   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1152   IN     UINT64                                 Address,
1153   IN     UINTN                                  Count,
1154   IN OUT VOID                                   *Buffer
1155   )
1156 {
1157   EFI_STATUS                             Status;
1158   UINT8                                  InStride;
1159   UINT8                                  OutStride;
1160   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  OperationWidth;
1161   UINT8                                  *Uint8Buffer;
1162   PCI_ROOT_BRIDGE_INSTANCE              *PrivateData;
1163 
1164   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
1165   /* Address is bus resource */
1166   Address -= PrivateData->IoBase;
1167   Address += PrivateData->CpuIoRegionBase;
1168 
1169   Status = RootBridgeIoCheckParameter (This, IoOperation, Width, Address, Count, Buffer);
1170   if (EFI_ERROR (Status)) {
1171     return Status;
1172   }
1173 
1174   InStride = mInStride[Width];
1175   OutStride = mOutStride[Width];
1176   OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
1177 
1178   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
1179     if (Write) {
1180       switch (OperationWidth) {
1181         case EfiPciWidthUint8:
1182           MmioWrite8 ((UINTN)Address, *Uint8Buffer);
1183           break;
1184         case EfiPciWidthUint16:
1185           MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
1186           break;
1187         case EfiPciWidthUint32:
1188           MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
1189           break;
1190         case EfiPciWidthUint64:
1191           MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
1192           break;
1193         default:
1194           //
1195           // The RootBridgeIoCheckParameter call above will ensure that this
1196           // path is not taken.
1197           //
1198           ASSERT (FALSE);
1199           break;
1200       }
1201     } else {
1202       switch (OperationWidth) {
1203         case EfiPciWidthUint8:
1204           *Uint8Buffer = MmioRead8 ((UINTN)Address);
1205           break;
1206         case EfiPciWidthUint16:
1207           *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
1208           break;
1209         case EfiPciWidthUint32:
1210           *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
1211           break;
1212         case EfiPciWidthUint64:
1213           *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
1214           break;
1215         default:
1216           //
1217           // The RootBridgeIoCheckParameter call above will ensure that this
1218           // path is not taken.
1219           //
1220           ASSERT (FALSE);
1221           break;
1222       }
1223     }
1224   }
1225   return EFI_SUCCESS;
1226 }
1227 
1228 
1229 /**
1230    Polls an address in memory mapped I/O space until an exit condition is met, or
1231    a timeout occurs.
1232 
1233    This function provides a standard way to poll a PCI memory location. A PCI memory read
1234    operation is performed at the PCI memory address specified by Address for the width specified
1235    by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
1236    read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
1237    Mask) is equal to Value.
1238 
1239    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1240    @param[in]   Width     Signifies the width of the memory operations.
1241    @param[in]   Address   The base address of the memory operations. The caller is
1242                           responsible for aligning Address if required.
1243    @param[in]   Mask      Mask used for the polling criteria. Bytes above Width in Mask
1244                           are ignored. The bits in the bytes below Width which are zero in
1245                           Mask are ignored when polling the memory address.
1246    @param[in]   Value     The comparison value used for the polling exit criteria.
1247    @param[in]   Delay     The number of 100 ns units to poll. Note that timer available may
1248                           be of poorer granularity.
1249    @param[out]  Result    Pointer to the last value read from the memory location.
1250 
1251    @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
1252    @retval EFI_INVALID_PARAMETER  Width is invalid.
1253    @retval EFI_INVALID_PARAMETER  Result is NULL.
1254    @retval EFI_TIMEOUT            Delay expired before a match occurred.
1255    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1256 
1257 **/
1258 EFI_STATUS
1259 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)1260 RootBridgeIoPollMem (
1261   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1262   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1263   IN  UINT64                                 Address,
1264   IN  UINT64                                 Mask,
1265   IN  UINT64                                 Value,
1266   IN  UINT64                                 Delay,
1267   OUT UINT64                                 *Result
1268   )
1269 {
1270   EFI_STATUS  Status;
1271   UINT64      NumberOfTicks;
1272   UINT32      Remainder;
1273 
1274   if (Result == NULL) {
1275     return EFI_INVALID_PARAMETER;
1276   }
1277 
1278   //
1279   // No matter what, always do a single poll.
1280   //
1281   Status = This->Mem.Read (This, Width, Address, 1, Result);
1282   if (EFI_ERROR (Status)) {
1283     return Status;
1284   }
1285   if ((*Result & Mask) == Value) {
1286     return EFI_SUCCESS;
1287   }
1288 
1289   if (Delay == 0) {
1290     return EFI_TIMEOUT;
1291 
1292   } else {
1293 
1294     //
1295     // Determine the proper # of metronome ticks to wait for polling the
1296     // location.  The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
1297     // The "+1" to account for the possibility of the first tick being short
1298     // because we started in the middle of a tick.
1299     //
1300     // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
1301     // protocol definition is updated.
1302     //
1303     NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
1304     if (Remainder != 0) {
1305       NumberOfTicks += 1;
1306     }
1307     NumberOfTicks += 1;
1308 
1309     while (NumberOfTicks != 0) {
1310 
1311       mMetronome->WaitForTick (mMetronome, 1);
1312 
1313       Status = This->Mem.Read (This, Width, Address, 1, Result);
1314       if (EFI_ERROR (Status)) {
1315         return Status;
1316       }
1317 
1318       if ((*Result & Mask) == Value) {
1319         return EFI_SUCCESS;
1320       }
1321 
1322       NumberOfTicks -= 1;
1323     }
1324   }
1325   return EFI_TIMEOUT;
1326 }
1327 
1328 /**
1329    Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
1330    satisfied or after a defined duration.
1331 
1332    This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
1333    performed at the PCI I/O address specified by Address for the width specified by Width.
1334    The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
1335    repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
1336    to Value.
1337 
1338    @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1339    @param[in] Width     Signifies the width of the I/O operations.
1340    @param[in] Address   The base address of the I/O operations. The caller is responsible
1341                         for aligning Address if required.
1342    @param[in] Mask      Mask used for the polling criteria. Bytes above Width in Mask
1343                         are ignored. The bits in the bytes below Width which are zero in
1344                         Mask are ignored when polling the I/O address.
1345    @param[in] Value     The comparison value used for the polling exit criteria.
1346    @param[in] Delay     The number of 100 ns units to poll. Note that timer available may
1347                         be of poorer granularity.
1348    @param[out] Result   Pointer to the last value read from the memory location.
1349 
1350    @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
1351    @retval EFI_INVALID_PARAMETER  Width is invalid.
1352    @retval EFI_INVALID_PARAMETER  Result is NULL.
1353    @retval EFI_TIMEOUT            Delay expired before a match occurred.
1354    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1355 
1356 **/
1357 EFI_STATUS
1358 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)1359 RootBridgeIoPollIo (
1360   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1361   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1362   IN  UINT64                                 Address,
1363   IN  UINT64                                 Mask,
1364   IN  UINT64                                 Value,
1365   IN  UINT64                                 Delay,
1366   OUT UINT64                                 *Result
1367   )
1368 {
1369   EFI_STATUS  Status;
1370   UINT64      NumberOfTicks;
1371   UINT32      Remainder;
1372 
1373   //
1374   // No matter what, always do a single poll.
1375   //
1376 
1377   if (Result == NULL) {
1378     return EFI_INVALID_PARAMETER;
1379   }
1380 
1381   Status = This->Io.Read (This, Width, Address, 1, Result);
1382   if (EFI_ERROR (Status)) {
1383     return Status;
1384   }
1385   if ((*Result & Mask) == Value) {
1386     return EFI_SUCCESS;
1387   }
1388 
1389   if (Delay == 0) {
1390     return EFI_SUCCESS;
1391 
1392   } else {
1393 
1394     //
1395     // Determine the proper # of metronome ticks to wait for polling the
1396     // location.  The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
1397     // The "+1" to account for the possibility of the first tick being short
1398     // because we started in the middle of a tick.
1399     //
1400     NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod, &Remainder);
1401     if (Remainder != 0) {
1402       NumberOfTicks += 1;
1403     }
1404     NumberOfTicks += 1;
1405 
1406     while (NumberOfTicks != 0) {
1407 
1408       mMetronome->WaitForTick (mMetronome, 1);
1409 
1410       Status = This->Io.Read (This, Width, Address, 1, Result);
1411       if (EFI_ERROR (Status)) {
1412         return Status;
1413       }
1414 
1415       if ((*Result & Mask) == Value) {
1416         return EFI_SUCCESS;
1417       }
1418 
1419       NumberOfTicks -= 1;
1420     }
1421   }
1422   return EFI_TIMEOUT;
1423 }
1424 
1425 /**
1426    Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
1427 
1428    The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
1429    registers in the PCI root bridge memory space.
1430    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
1431    any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
1432 
1433    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1434    @param[in]   Width     Signifies the width of the memory operation.
1435    @param[in]   Address   The base address of the memory operation. The caller is
1436                           responsible for aligning the Address if required.
1437    @param[in]   Count     The number of memory operations to perform. Bytes moved is
1438                           Width size * Count, starting at Address.
1439    @param[out]  Buffer    For read operations, the destination buffer to store the results. For
1440                           write operations, the source buffer to write data from.
1441 
1442    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1443    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1444    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1445    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1446 
1447 **/
1448 EFI_STATUS
1449 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,OUT VOID * Buffer)1450 RootBridgeIoMemRead (
1451   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1452   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1453   IN     UINT64                                 Address,
1454   IN     UINTN                                  Count,
1455   OUT    VOID                                   *Buffer
1456   )
1457 {
1458   return RootBridgeIoMemRW (This, FALSE, Width, Address, Count, Buffer);
1459 }
1460 
1461 /**
1462    Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
1463 
1464    The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
1465    registers in the PCI root bridge memory space.
1466    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
1467    any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
1468 
1469    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1470    @param[in]   Width     Signifies the width of the memory operation.
1471    @param[in]   Address   The base address of the memory operation. The caller is
1472                           responsible for aligning the Address if required.
1473    @param[in]   Count     The number of memory operations to perform. Bytes moved is
1474                           Width size * Count, starting at Address.
1475    @param[in]   Buffer    For read operations, the destination buffer to store the results. For
1476                           write operations, the source buffer to write data from.
1477 
1478    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1479    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1480    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1481    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1482 **/
1483 EFI_STATUS
1484 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 VOID * Buffer)1485 RootBridgeIoMemWrite (
1486   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1487   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1488   IN     UINT64                                 Address,
1489   IN     UINTN                                  Count,
1490   IN     VOID                                   *Buffer
1491   )
1492 {
1493   return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer);
1494 }
1495 
1496 /**
1497    Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
1498 
1499    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1500    @param[in]   Width       Signifies the width of the memory operations.
1501    @param[in]   Address     The base address of the I/O operation. The caller is responsible for
1502                             aligning the Address if required.
1503    @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
1504                             size * Count, starting at Address.
1505    @param[out]  Buffer      For read operations, the destination buffer to store the results. For
1506                             write operations, the source buffer to write data from.
1507 
1508    @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
1509    @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
1510    @retval EFI_INVALID_PARAMETER    Buffer is NULL.
1511    @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
1512 
1513 **/
1514 EFI_STATUS
1515 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,OUT VOID * Buffer)1516 RootBridgeIoIoRead (
1517   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1518   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1519   IN     UINT64                                 Address,
1520   IN     UINTN                                  Count,
1521   OUT    VOID                                   *Buffer
1522   )
1523 {
1524   return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer);
1525 }
1526 
1527 /**
1528    Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
1529 
1530    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1531    @param[in]   Width       Signifies the width of the memory operations.
1532    @param[in]   Address     The base address of the I/O operation. The caller is responsible for
1533                             aligning the Address if required.
1534    @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
1535                             size * Count, starting at Address.
1536    @param[in]   Buffer       For read operations, the destination buffer to store the results. For
1537                             write operations, the source buffer to write data from.
1538 
1539    @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
1540    @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
1541    @retval EFI_INVALID_PARAMETER    Buffer is NULL.
1542    @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
1543 
1544 **/
1545 EFI_STATUS
1546 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 VOID * Buffer)1547 RootBridgeIoIoWrite (
1548   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL         *This,
1549   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH   Width,
1550   IN       UINT64                                  Address,
1551   IN       UINTN                                   Count,
1552   IN       VOID                                    *Buffer
1553   )
1554 {
1555   return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer);
1556 }
1557 
1558 /**
1559    Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
1560    root bridge memory space.
1561 
1562    The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
1563    space to another region of PCI root bridge memory space. This is especially useful for video scroll
1564    operation on a memory mapped video buffer.
1565    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
1566    any alignment and memory width restrictions that a PCI root bridge on a platform might require.
1567 
1568    @param[in] This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1569    @param[in] Width       Signifies the width of the memory operations.
1570    @param[in] DestAddress The destination address of the memory operation. The caller is
1571                           responsible for aligning the DestAddress if required.
1572    @param[in] SrcAddress  The source address of the memory operation. The caller is
1573                           responsible for aligning the SrcAddress if required.
1574    @param[in] Count       The number of memory operations to perform. Bytes moved is
1575                           Width size * Count, starting at DestAddress and SrcAddress.
1576 
1577    @retval  EFI_SUCCESS             The data was copied from one memory region to another memory region.
1578    @retval  EFI_INVALID_PARAMETER   Width is invalid for this PCI root bridge.
1579    @retval  EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.
1580 
1581 **/
1582 EFI_STATUS
1583 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)1584 RootBridgeIoCopyMem (
1585   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
1586   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH        Width,
1587   IN UINT64                                       DestAddress,
1588   IN UINT64                                       SrcAddress,
1589   IN UINTN                                        Count
1590   )
1591 {
1592   EFI_STATUS  Status;
1593   BOOLEAN     Direction;
1594   UINTN       Stride;
1595   UINTN       Index;
1596   UINT64      Result;
1597 
1598   if ((UINT32)Width > EfiPciWidthUint64) {
1599     return EFI_INVALID_PARAMETER;
1600   }
1601 
1602   if (DestAddress == SrcAddress) {
1603     return EFI_SUCCESS;
1604   }
1605 
1606   Stride = (UINTN)((UINTN)1 << Width);
1607 
1608   Direction = TRUE;
1609   if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
1610     Direction   = FALSE;
1611     SrcAddress  = SrcAddress  + (Count-1) * Stride;
1612     DestAddress = DestAddress + (Count-1) * Stride;
1613   }
1614 
1615   for (Index = 0;Index < Count;Index++) {
1616     Status = RootBridgeIoMemRead (
1617                This,
1618                Width,
1619                SrcAddress,
1620                1,
1621                &Result
1622                );
1623     if (EFI_ERROR (Status)) {
1624       return Status;
1625     }
1626     Status = RootBridgeIoMemWrite (
1627                This,
1628                Width,
1629                DestAddress,
1630                1,
1631                &Result
1632                );
1633     if (EFI_ERROR (Status)) {
1634       return Status;
1635     }
1636     if (Direction) {
1637       SrcAddress  += Stride;
1638       DestAddress += Stride;
1639     } else {
1640       SrcAddress  -= Stride;
1641       DestAddress -= Stride;
1642     }
1643   }
1644   return EFI_SUCCESS;
1645 }
1646 
1647 /**
1648   Reads memory-mapped registers.
1649   @param[in]  Width    Signifies the width of the I/O or Memory operation.
1650   @param[in]  Address  The base address of the I/O operation.
1651   @param[in]  Count    The number of I/O operations to perform. The number of
1652                        bytes moved is Width size * Count, starting at Address.
1653   @param[out] Buffer   For read operations, the destination buffer to store the results.
1654                        For write operations, the source buffer from which to write data.
1655 
1656   @retval EFI_SUCCESS            The data was read from or written to the PI system.
1657   @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
1658   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1659   @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
1660   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
1661                                  and Count is not valid for this PI system.
1662 
1663 **/
1664 EFI_STATUS
CpuMemoryServiceRead(IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)1665 CpuMemoryServiceRead (
1666   IN  EFI_CPU_IO_PROTOCOL_WIDTH  Width,
1667   IN  UINT64                     Address,
1668   IN  UINTN                      Count,
1669   OUT VOID                       *Buffer
1670   )
1671 {
1672 
1673   UINT8                      InStride;
1674   UINT8                      OutStride;
1675   EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
1676   UINT8                      *Uint8Buffer;
1677   UINT32                     Uint32Buffer = 0;
1678 
1679   //
1680   // Select loop based on the width of the transfer
1681   //
1682   InStride = mInStride[Width];
1683   OutStride = mOutStride[Width];
1684   OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
1685   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
1686     if (OperationWidth == EfiCpuIoWidthUint8) {
1687       Uint32Buffer = MmioRead32((UINTN)(Address & (~0x3)));
1688       Uint32Buffer &= (0xFF << ((Address & 0x3) * 8));
1689       *((UINT8*)Uint8Buffer) = (UINT8)(Uint32Buffer >> (((Address & 0x3) * 8)));
1690     } else if (OperationWidth == EfiCpuIoWidthUint16) {
1691       if (((Address & 0x3) == 1) || ((Address & 0x3) == 3)) {
1692         return EFI_INVALID_PARAMETER;
1693       }
1694       Uint32Buffer = MmioRead32((UINTN)(Address & (~0x3)));
1695       Uint32Buffer &= (0xFFFF << ((Address & 0x3) * 8));
1696       *(UINT16 *)Uint8Buffer = (UINT16)(Uint32Buffer >> (((Address & 0x3) * 8)));
1697     } else if (OperationWidth == EfiCpuIoWidthUint32) {
1698       *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
1699     } else if (OperationWidth == EfiCpuIoWidthUint64) {
1700       *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
1701     }
1702   }
1703   return EFI_SUCCESS;
1704 }
1705 
1706 /**
1707    Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
1708 
1709    The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
1710    registers for a PCI controller.
1711    The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
1712    any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
1713    require.
1714 
1715    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1716    @param[in]   Width     Signifies the width of the memory operations.
1717    @param[in]   Address   The address within the PCI configuration space for the PCI controller.
1718    @param[in]   Count     The number of PCI configuration operations to perform. Bytes
1719                           moved is Width size * Count, starting at Address.
1720    @param[out]  Buffer    For read operations, the destination buffer to store the results. For
1721                           write operations, the source buffer to write data from.
1722 
1723    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1724    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1725    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1726    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1727 
1728 **/
1729 EFI_STATUS
1730 EFIAPI
RootBridgeIoPciRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 EfiAddress,IN UINTN Count,OUT VOID * Buffer)1731 RootBridgeIoPciRead (
1732   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1733   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1734   IN       UINT64                                 EfiAddress,
1735   IN       UINTN                                  Count,
1736   OUT      VOID                                   *Buffer
1737   )
1738 {
1739   UINT32                      Offset;
1740   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
1741   UINT64                      Address;
1742   PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
1743 
1744   EfiPciAddress  = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
1745   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
1746 
1747   if (Buffer == NULL) {
1748     return EFI_INVALID_PARAMETER;
1749   }
1750 
1751   if (Width >= EfiPciWidthMaximum) {
1752     return EFI_INVALID_PARAMETER;
1753   }
1754 
1755   if (EfiPciAddress->ExtendedRegister) {
1756     Offset = EfiPciAddress->ExtendedRegister;
1757   } else {
1758     Offset = EfiPciAddress->Register;
1759   }
1760 
1761   PCIE_DEBUG ("[%a:%d] - bus %x dev %x func %x Off %x\n", __FUNCTION__, __LINE__,
1762          EfiPciAddress->Bus,
1763          EfiPciAddress->Device,
1764          EfiPciAddress->Function,
1765          Offset
1766         );
1767   if (EfiPciAddress->Bus < PrivateData->BusBase || EfiPciAddress->Bus > PrivateData->BusLimit) {
1768     PCIE_DEBUG ("[%a:%d] - Bus number out of range %d\n", __FUNCTION__, __LINE__, EfiPciAddress->Bus);
1769     SetMem (Buffer, mOutStride[Width] * Count, 0xFF);
1770     return EFI_INVALID_PARAMETER;
1771   }
1772 
1773   // The UEFI PCI enumerator scans for devices at all possible addresses,
1774   // and ignores some PCI rules - this results in some hardware being
1775   // detected multiple times. We work around this by faking absent
1776   // devices
1777   if(EfiPciAddress->Bus == PrivateData->BusBase)
1778   {
1779     if((EfiPciAddress->Device != 0x0) || (EfiPciAddress->Function != 0)) {
1780       SetMem (Buffer, mOutStride[Width] * Count, 0xFF);
1781       return EFI_UNSUPPORTED;
1782     }
1783   }
1784 
1785   if (EfiPciAddress->Bus == PrivateData->BusBase){
1786     Address = PrivateData->RbPciBar + Offset;
1787   }
1788   else if(EfiPciAddress->Bus == PrivateData->BusBase + 1)
1789   {
1790     if (!PcieIsLinkUp(PrivateData->SocType,PrivateData->RbPciBar, PrivateData->Port))
1791     {
1792       SetMem (Buffer, mOutStride[Width] * Count, 0xFF);
1793       return EFI_NOT_READY;
1794     }
1795     Address = GetPcieCfgAddress (
1796         PrivateData->Ecam,
1797         EfiPciAddress->Bus,
1798         EfiPciAddress->Device,
1799         EfiPciAddress->Function,
1800         Offset
1801         );
1802   }
1803   else
1804   {
1805     Address = GetPcieCfgAddress (
1806          PrivateData->Ecam,
1807          EfiPciAddress->Bus,
1808          EfiPciAddress->Device,
1809          EfiPciAddress->Function,
1810          Offset
1811          );
1812   }
1813 
1814   (VOID)CpuMemoryServiceRead((EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
1815   PCIE_DEBUG ("[%a:%d] - %x\n", __FUNCTION__, __LINE__, *(UINT32 *)Buffer);
1816 
1817   return EFI_SUCCESS;
1818 }
1819 
1820 /**
1821   Writes memory-mapped registers.
1822   @param[in]  Width    Signifies the width of the I/O or Memory operation.
1823   @param[in]  Address  The base address of the I/O operation.
1824   @param[in]  Count    The number of I/O operations to perform. The number of
1825                        bytes moved is Width size * Count, starting at Address.
1826   @param[in]  Buffer   For read operations, the destination buffer to store the results.
1827                        For write operations, the source buffer from which to write data.
1828 
1829   @retval EFI_SUCCESS            The data was read from or written to the PI system.
1830   @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
1831   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1832   @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
1833   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
1834                                  and Count is not valid for this PI system.
1835 
1836 **/
1837 EFI_STATUS
CpuMemoryServiceWrite(IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)1838 CpuMemoryServiceWrite (
1839   IN EFI_CPU_IO_PROTOCOL_WIDTH  Width,
1840   IN UINT64                     Address,
1841   IN UINTN                      Count,
1842   IN VOID                       *Buffer
1843   )
1844 {
1845   UINT8                      InStride;
1846   UINT8                      OutStride;
1847   EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
1848   UINT8                      *Uint8Buffer;
1849   UINT32                     Uint32Buffer;
1850 
1851   //
1852   // Select loop based on the width of the transfer
1853   //
1854   InStride = mInStride[Width];
1855   OutStride = mOutStride[Width];
1856   OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
1857   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
1858     if (OperationWidth == EfiCpuIoWidthUint8) {
1859       Uint32Buffer = MmioRead32 ((UINTN)(Address & (~0x03)));
1860       Uint32Buffer &= ~(UINT32)(0xFF << ((Address & 0x3) * 8));
1861       Uint32Buffer |= (UINT32)(*(UINT8 *)Uint8Buffer) << ((Address & 0x3) * 8);
1862       MmioWrite32 ((UINTN)(Address & (~0x03)), Uint32Buffer);
1863     } else if (OperationWidth == EfiCpuIoWidthUint16) {
1864       if (((Address & 0x3) == 1) || ((Address & 0x3) == 3)) {
1865         return EFI_INVALID_PARAMETER;
1866       }
1867       Uint32Buffer = MmioRead32 ((UINTN)(Address & (~0x03)));
1868       Uint32Buffer &= ~(UINT32)(0xFFFF << ((Address & 0x3) * 8));
1869       Uint32Buffer |= (UINT32)(*(UINT16 *)Uint8Buffer) << ((Address & 0x3) * 8);
1870       MmioWrite32 ((UINTN)(Address & (~0x03)), Uint32Buffer);
1871     } else if (OperationWidth == EfiCpuIoWidthUint32) {
1872       MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
1873     } else if (OperationWidth == EfiCpuIoWidthUint64) {
1874       MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
1875     }
1876   }
1877   return EFI_SUCCESS;
1878 }
1879 
1880 /**
1881    Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
1882 
1883    The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
1884    registers for a PCI controller.
1885    The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
1886    any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
1887    require.
1888 
1889    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1890    @param[in]   Width     Signifies the width of the memory operations.
1891    @param[in]   Address   The address within the PCI configuration space for the PCI controller.
1892    @param[in]   Count     The number of PCI configuration operations to perform. Bytes
1893                           moved is Width size * Count, starting at Address.
1894    @param[in]   Buffer    For read operations, the destination buffer to store the results. For
1895                           write operations, the source buffer to write data from.
1896 
1897    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1898    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1899    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1900    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1901 
1902 **/
1903 EFI_STATUS
1904 EFIAPI
RootBridgeIoPciWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 EfiAddress,IN UINTN Count,IN VOID * Buffer)1905 RootBridgeIoPciWrite (
1906   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1907   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1908   IN       UINT64                                 EfiAddress,
1909   IN       UINTN                                  Count,
1910   IN       VOID                                   *Buffer
1911   )
1912 {
1913   UINT32                      Offset;
1914   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
1915   UINT64                      Address;
1916   PCI_ROOT_BRIDGE_INSTANCE    *PrivateData;
1917 
1918   EfiPciAddress  = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
1919   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
1920 
1921   if (Buffer == NULL) {
1922     return EFI_INVALID_PARAMETER;
1923   }
1924 
1925   if (Width >= EfiPciWidthMaximum) {
1926     return EFI_INVALID_PARAMETER;
1927   }
1928 
1929   if (EfiPciAddress->ExtendedRegister)
1930     Offset = EfiPciAddress->ExtendedRegister;
1931   else
1932     Offset = EfiPciAddress->Register;
1933 
1934   PCIE_DEBUG ("[%a:%d] - bus %x dev %x func %x Off %x\n", __FUNCTION__, __LINE__,
1935          EfiPciAddress->Bus,
1936          EfiPciAddress->Device,
1937          EfiPciAddress->Function,
1938          Offset
1939         );
1940   if (((EfiPciAddress->Bus == PrivateData->BusBase) && (EfiPciAddress->Device == 0x00) && (EfiPciAddress->Function == 0))){
1941     Address = PrivateData->RbPciBar + Offset;
1942     if ((Offset == 0x14) || (Offset == 0x10)) {
1943       return EFI_SUCCESS;
1944     }
1945   }
1946   else if (EfiPciAddress->Bus == PrivateData->BusBase + 1)
1947   {
1948      if (!PcieIsLinkUp(PrivateData->SocType,PrivateData->RbPciBar, PrivateData->Port)) {
1949       return EFI_NOT_READY;
1950     }
1951     Address = GetPcieCfgAddress (
1952         PrivateData->Ecam,
1953         EfiPciAddress->Bus,
1954         EfiPciAddress->Device,
1955         EfiPciAddress->Function,
1956         Offset
1957     );
1958   }
1959   else
1960   {
1961     Address = GetPcieCfgAddress (
1962        PrivateData->Ecam,
1963        EfiPciAddress->Bus,
1964        EfiPciAddress->Device,
1965        EfiPciAddress->Function,
1966        Offset
1967        );
1968   }
1969 
1970   (VOID)CpuMemoryServiceWrite ((EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
1971   PCIE_DEBUG ("[%a:%d] - 0x%08x\n", __FUNCTION__, __LINE__, *(UINT32 *)Buffer);
1972   return EFI_SUCCESS;
1973 }
1974 
1975 /**
1976    Provides the PCI controller-specific addresses required to access system memory from a
1977    DMA bus master.
1978 
1979    The Map() function provides the PCI controller specific addresses needed to access system
1980    memory. This function is used to map system memory for PCI bus master DMA accesses.
1981 
1982    @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1983    @param[in]       Operation       Indicates if the bus master is going to read or write to system memory.
1984    @param[in]       HostAddress     The system memory address to map to the PCI controller.
1985    @param[in, out]  NumberOfBytes   On input the number of bytes to map. On output the number of bytes that were mapped.
1986    @param[out]      DeviceAddress   The resulting map address for the bus master PCI controller to use
1987                                     to access the system memory's HostAddress.
1988    @param[out]      Mapping         The value to pass to Unmap() when the bus master DMA operation is complete.
1989 
1990    @retval EFI_SUCCESS            The range was mapped for the returned NumberOfBytes.
1991    @retval EFI_INVALID_PARAMETER  Operation is invalid.
1992    @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
1993    @retval EFI_INVALID_PARAMETER  NumberOfBytes is NULL.
1994    @retval EFI_INVALID_PARAMETER  DeviceAddress is NULL.
1995    @retval EFI_INVALID_PARAMETER  Mapping is NULL.
1996    @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common buffer.
1997    @retval EFI_DEVICE_ERROR       The system hardware could not map the requested address.
1998    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1999 
2000 **/
2001 EFI_STATUS
2002 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)2003 RootBridgeIoMap (
2004   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
2005   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
2006   IN     VOID                                       *HostAddress,
2007   IN OUT UINTN                                      *NumberOfBytes,
2008   OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
2009   OUT    VOID                                       **Mapping
2010   )
2011 {
2012   DMA_MAP_OPERATION   DmaOperation;
2013 
2014   if (Operation == EfiPciOperationBusMasterRead) {
2015     DmaOperation = MapOperationBusMasterRead;
2016   } else if (Operation == EfiPciOperationBusMasterWrite) {
2017     DmaOperation = MapOperationBusMasterWrite;
2018   } else if (Operation == EfiPciOperationBusMasterCommonBuffer) {
2019     DmaOperation = MapOperationBusMasterCommonBuffer;
2020   } else if (Operation == EfiPciOperationBusMasterRead64) {
2021     DmaOperation = MapOperationBusMasterRead;
2022   } else if (Operation == EfiPciOperationBusMasterWrite64) {
2023      DmaOperation = MapOperationBusMasterWrite;
2024   } else if (Operation == EfiPciOperationBusMasterCommonBuffer64) {
2025     DmaOperation = MapOperationBusMasterCommonBuffer;
2026   } else {
2027     return EFI_INVALID_PARAMETER;
2028   }
2029   (VOID)DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
2030   return EFI_SUCCESS;
2031 }
2032 
2033 /**
2034    Completes the Map() operation and releases any corresponding resources.
2035 
2036    The Unmap() function completes the Map() operation and releases any corresponding resources.
2037    If the operation was an EfiPciOperationBusMasterWrite or
2038    EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
2039    Any resources used for the mapping are freed.
2040 
2041    @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2042    @param[in] Mapping   The mapping value returned from Map().
2043 
2044    @retval EFI_SUCCESS            The range was unmapped.
2045    @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
2046    @retval EFI_DEVICE_ERROR       The data was not committed to the target system memory.
2047 
2048 **/
2049 EFI_STATUS
2050 EFIAPI
RootBridgeIoUnmap(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN VOID * Mapping)2051 RootBridgeIoUnmap (
2052   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
2053   IN VOID                             *Mapping
2054   )
2055 {
2056   return DmaUnmap (Mapping);
2057 }
2058 
2059 /**
2060    Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
2061    EfiPciOperationBusMasterCommonBuffer64 mapping.
2062 
2063    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2064    @param Type        This parameter is not used and must be ignored.
2065    @param MemoryType  The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
2066    @param Pages       The number of pages to allocate.
2067    @param HostAddress A pointer to store the base system memory address of the allocated range.
2068    @param Attributes  The requested bit mask of attributes for the allocated range. Only
2069                       the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
2070                       and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
2071 
2072    @retval EFI_SUCCESS            The requested memory pages were allocated.
2073    @retval EFI_INVALID_PARAMETER  MemoryType is invalid.
2074    @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
2075    @retval EFI_UNSUPPORTED        Attributes is unsupported. The only legal attribute bits are
2076                                   MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
2077    @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
2078 
2079 **/
2080 EFI_STATUS
2081 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)2082 RootBridgeIoAllocateBuffer (
2083   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
2084   IN  EFI_ALLOCATE_TYPE                Type,
2085   IN  EFI_MEMORY_TYPE                  MemoryType,
2086   IN  UINTN                            Pages,
2087   OUT VOID                             **HostAddress,
2088   IN  UINT64                           Attributes
2089   )
2090 {
2091   if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
2092     return EFI_UNSUPPORTED;
2093   }
2094 
2095   return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
2096 
2097 }
2098 
2099 /**
2100    Frees memory that was allocated with AllocateBuffer().
2101 
2102    The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
2103 
2104    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2105    @param Pages       The number of pages to free.
2106    @param HostAddress The base system memory address of the allocated range.
2107 
2108    @retval EFI_SUCCESS            The requested memory pages were freed.
2109    @retval EFI_INVALID_PARAMETER  The memory range specified by HostAddress and Pages
2110                                   was not allocated with AllocateBuffer().
2111 
2112 **/
2113 EFI_STATUS
2114 EFIAPI
RootBridgeIoFreeBuffer(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN UINTN Pages,OUT VOID * HostAddress)2115 RootBridgeIoFreeBuffer (
2116   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
2117   IN  UINTN                            Pages,
2118   OUT VOID                             *HostAddress
2119   )
2120 {
2121   return DmaFreeBuffer (Pages, HostAddress);
2122 }
2123 
2124 /**
2125    Flushes all PCI posted write transactions from a PCI host bridge to system memory.
2126 
2127    The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
2128    memory. Posted write transactions are generated by PCI bus masters when they perform write
2129    transactions to target addresses in system memory.
2130    This function does not flush posted write transactions from any PCI bridges. A PCI controller
2131    specific action must be taken to guarantee that the posted write transactions have been flushed from
2132    the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
2133    a PCI read transaction from the PCI controller prior to calling Flush().
2134 
2135    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2136 
2137    @retval EFI_SUCCESS        The PCI posted write transactions were flushed from the PCI host
2138                               bridge to system memory.
2139    @retval EFI_DEVICE_ERROR   The PCI posted write transactions were not flushed from the PCI
2140                               host bridge due to a hardware error.
2141 
2142 **/
2143 EFI_STATUS
2144 EFIAPI
RootBridgeIoFlush(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This)2145 RootBridgeIoFlush (
2146   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This
2147   )
2148 {
2149   //
2150   // not supported yet
2151   //
2152   return EFI_SUCCESS;
2153 }
2154 
2155 /**
2156    Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
2157    attributes that a PCI root bridge is currently using.
2158 
2159    The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
2160    and the mask of attributes that the PCI root bridge is currently using.
2161 
2162    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2163    @param Supported   A pointer to the mask of attributes that this PCI root bridge
2164                       supports setting with SetAttributes().
2165    @param Attributes  A pointer to the mask of attributes that this PCI root bridge is
2166                       currently using.
2167 
2168    @retval  EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI root
2169                                   bridge supports is returned in Supports. If Attributes is
2170                                   not NULL, then the attributes that the PCI root bridge is currently
2171                                   using is returned in Attributes.
2172    @retval  EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
2173 
2174 **/
2175 EFI_STATUS
2176 EFIAPI
RootBridgeIoGetAttributes(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,OUT UINT64 * Supported,OUT UINT64 * Attributes)2177 RootBridgeIoGetAttributes (
2178   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
2179   OUT UINT64                           *Supported,
2180   OUT UINT64                           *Attributes
2181   )
2182 {
2183   PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
2184 
2185   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
2186 
2187   if (Attributes == NULL && Supported == NULL) {
2188     return EFI_INVALID_PARAMETER;
2189   }
2190 
2191   //
2192   // Set the return value for Supported and Attributes
2193   //
2194   if (Supported != NULL) {
2195     *Supported  = PrivateData->Supports;
2196   }
2197 
2198   if (Attributes != NULL) {
2199     *Attributes = PrivateData->Attributes;
2200   }
2201 
2202   return EFI_SUCCESS;
2203 }
2204 
2205 /**
2206    Sets attributes for a resource range on a PCI root bridge.
2207 
2208    The SetAttributes() function sets the attributes specified in Attributes for the PCI root
2209    bridge on the resource range specified by ResourceBase and ResourceLength. Since the
2210    granularity of setting these attributes may vary from resource type to resource type, and from
2211    platform to platform, the actual resource range and the one passed in by the caller may differ. As a
2212    result, this function may set the attributes specified by Attributes on a larger resource range
2213    than the caller requested. The actual range is returned in ResourceBase and
2214    ResourceLength. The caller is responsible for verifying that the actual range for which the
2215    attributes were set is acceptable.
2216 
2217    @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2218    @param[in]       Attributes      The mask of attributes to set. If the attribute bit
2219                                     MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
2220                                     MEMORY_DISABLE is set, then the resource range is specified by
2221                                     ResourceBase and ResourceLength. If
2222                                     MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
2223                                     MEMORY_DISABLE are not set, then ResourceBase and
2224                                     ResourceLength are ignored, and may be NULL.
2225    @param[in, out]  ResourceBase    A pointer to the base address of the resource range to be modified
2226                                     by the attributes specified by Attributes.
2227    @param[in, out]  ResourceLength  A pointer to the length of the resource range to be modified by the
2228                                     attributes specified by Attributes.
2229 
2230    @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
2231    @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
2232    @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
2233 
2234 **/
2235 EFI_STATUS
2236 EFIAPI
RootBridgeIoSetAttributes(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN UINT64 Attributes,IN OUT UINT64 * ResourceBase,IN OUT UINT64 * ResourceLength)2237 RootBridgeIoSetAttributes (
2238   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
2239   IN     UINT64                           Attributes,
2240   IN OUT UINT64                           *ResourceBase,
2241   IN OUT UINT64                           *ResourceLength
2242   )
2243 {
2244   PCI_ROOT_BRIDGE_INSTANCE            *PrivateData;
2245 
2246   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
2247 
2248   if (Attributes != 0) {
2249     if ((Attributes & (~(PrivateData->Supports))) != 0) {
2250       return EFI_UNSUPPORTED;
2251     }
2252   }
2253 
2254   //
2255   // This is a generic driver for a PC-AT class system.  It does not have any
2256   // chipset specific knowlegde, so none of the attributes can be set or
2257   // cleared.  Any attempt to set attribute that are already set will succeed,
2258   // and any attempt to set an attribute that is not supported will fail.
2259   //
2260   if (Attributes & (~PrivateData->Attributes)) {
2261     /* FIXME: */
2262     return EFI_UNSUPPORTED;
2263   }
2264 
2265   return EFI_SUCCESS;
2266 }
2267 
2268 /**
2269    Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
2270    resource descriptors.
2271 
2272    There are only two resource descriptor types from the ACPI Specification that may be used to
2273    describe the current resources allocated to a PCI root bridge. These are the QWORD Address
2274    Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
2275    QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
2276    or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
2277    Address Space Descriptors followed by an End Tag.
2278 
2279    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2280    @param[out]  Resources   A pointer to the ACPI 2.0 resource descriptors that describe the
2281                             current configuration of this PCI root bridge. The storage for the
2282                             ACPI 2.0 resource descriptors is allocated by this function. The
2283                             caller must treat the return buffer as read-only data, and the buffer
2284                             must not be freed by the caller.
2285 
2286    @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
2287    @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
2288    @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
2289 
2290 **/
2291 EFI_STATUS
2292 EFIAPI
RootBridgeIoConfiguration(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,OUT VOID ** Resources)2293 RootBridgeIoConfiguration (
2294   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *This,
2295   OUT VOID                                **Resources
2296   )
2297 {
2298   PCI_ROOT_BRIDGE_INSTANCE              *PrivateData;
2299   UINTN                                 Index;
2300 
2301   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
2302   for (Index = 0; Index < TypeMax; Index++) {
2303     if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
2304       Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
2305       Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;
2306       Configuration.SpaceDesp[Index].AddrLen      = PrivateData->ResAllocNode[Index].Length;
2307     }
2308   }
2309 
2310   *Resources = &Configuration;
2311   return EFI_SUCCESS;
2312 }
2313 
2314