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