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