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