]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/PciHostBridgeDxe/PciRootBridgeIo.c
OvmfPkg: PciHostBridgeDxe: use private buffer in RootBridgeIoConfiguration()
[mirror_edk2.git] / OvmfPkg / PciHostBridgeDxe / PciRootBridgeIo.c
CommitLineData
d52bde1c
LE
1/** @file\r
2 PCI Root Bridge Io Protocol implementation\r
3\r
20f7840e 4 Copyright (C) 2015, Red Hat, Inc.\r
d52bde1c
LE
5 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
6\r
7 This program and the accompanying materials are licensed and made available\r
8 under the terms and conditions of the BSD License which accompanies this\r
9 distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
13 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14**/\r
15\r
16#include "PciHostBridge.h"\r
17#include "IoFifo.h"\r
18\r
20f7840e
LE
19STATIC\r
20CONST\r
21RESOURCE_CONFIGURATION mConfigurationTemplate = {\r
22 {\r
23 { 0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0 }, // SpaceDesc[TypeIo]\r
24 { 0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0 }, // SpaceDesc[TypeMem32]\r
25 { 0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0 }, // SpaceDesc[TypePMem32]\r
26 { 0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0 }, // SpaceDesc[TypeMem64]\r
27 { 0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0 }, // SpaceDesc[TypePMem64]\r
28 { 0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0 } // SpaceDesc[TypeBus]\r
29 },\r
30 { 0x79, 0 } // EndDesc\r
d52bde1c
LE
31};\r
32\r
33//\r
34// Protocol Member Function Prototypes\r
35//\r
36\r
37/**\r
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
73\r
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
80**/\r
81EFI_STATUS\r
82EFIAPI\r
83RootBridgeIoPollMem (\r
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
92\r
93/**\r
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
117\r
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
135**/\r
136EFI_STATUS\r
137EFIAPI\r
138RootBridgeIoPollIo (\r
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
147\r
148/**\r
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
157\r
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
181**/\r
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
189 OUT VOID *Buffer\r
190 );\r
191\r
192/**\r
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
225**/\r
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
233 IN VOID *Buffer\r
234 );\r
235\r
236/**\r
237 Enables a PCI driver to access PCI controller registers in the PCI root\r
238 bridge I/O space.\r
239\r
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
264**/\r
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
272 OUT VOID *UserBuffer\r
273 );\r
274\r
275/**\r
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
280\r
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
303**/\r
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
311 IN VOID *UserBuffer\r
312 );\r
313\r
314/**\r
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
328\r
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
351**/\r
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
362/**\r
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
375\r
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
397**/\r
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
405 OUT VOID *Buffer\r
406 );\r
407\r
408/**\r
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
419\r
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
443**/\r
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
451 IN VOID *Buffer\r
452 );\r
453\r
454/**\r
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
461\r
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
502**/\r
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
514/**\r
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
523\r
524 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
525\r
526 @param[in] Mapping The mapping value returned from Map().\r
527\r
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
535**/\r
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
543/**\r
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
550\r
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
577**/\r
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
589/**\r
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
596\r
597 @param Pages The number of pages to free.\r
598\r
599 @param HostAddress The base system memory address of the allocated range.\r
600\r
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
605**/\r
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
614/**\r
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
635**/\r
636EFI_STATUS\r
637EFIAPI\r
638RootBridgeIoFlush (\r
639 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
640 );\r
641\r
642/**\r
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
655\r
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
667**/\r
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
676/**\r
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
718\r
719**/\r
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
726 IN OUT UINT64 *ResourceLength\r
727 );\r
728\r
729/**\r
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
759**/\r
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
768// Memory Controller Pci Root Bridge Io Module Variables\r
769//\r
770EFI_METRONOME_ARCH_PROTOCOL *mMetronome;\r
771\r
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
789\r
790//\r
791// Lookup table for increment values based on transfer widths\r
792//\r
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
807\r
808/**\r
809 Construct the Pci Root Bridge Io protocol\r
810\r
811 @param Protocol Point to protocol instance\r
812\r
813 @param HostBridgeHandle Handle of host bridge\r
814\r
815 @param Attri Attribute of host bridge\r
816\r
817 @param ResAperture ResourceAperture for host bridge\r
818\r
819 @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.\r
820**/\r
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
826 IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture\r
827 )\r
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
839 PrivateData->MemBase = ResAperture->MemBase;\r
840 PrivateData->IoBase = ResAperture->IoBase;\r
841\r
842 //\r
843 // The host bridge only supports 32bit addressing for memory\r
844 // and standard IA32 16bit io\r
845 //\r
846 PrivateData->MemLimit = ResAperture->MemLimit;\r
847 PrivateData->IoLimit = ResAperture->IoLimit;\r
848\r
849 //\r
850 // Bus Aperture for this Root Bridge (Possible Range)\r
851 //\r
852 PrivateData->BusBase = ResAperture->BusBase;\r
853 PrivateData->BusLimit = ResAperture->BusLimit;\r
854\r
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
864\r
865 PrivateData->RootBridgeAttrib = Attri;\r
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
874 PrivateData->Attributes = PrivateData->Supports;\r
875\r
876 Protocol->ParentHandle = HostBridgeHandle;\r
877\r
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
907 Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL,\r
908 (VOID **)&mMetronome);\r
909 ASSERT_EFI_ERROR (Status);\r
910\r
911 return EFI_SUCCESS;\r
912}\r
913\r
914/**\r
915 Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.\r
916\r
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
923 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
924\r
925 @param[in] OperationType I/O operation type: IO/MMIO/PCI.\r
926\r
927 @param[in] Width Signifies the width of the I/O or Memory operation.\r
928\r
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
942 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
943\r
944 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
945\r
946 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
947\r
948 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
949 and Count is not valid for this PI system.\r
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
977 if ((UINT32)Width >= EfiPciWidthMaximum) {\r
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
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
1012 //\r
1013 // Address + Size * Count > Limit + 1\r
1014 //\r
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
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
1030 if (PciRbAddr->Bus < PrivateData->BusBase ||\r
1031 PciRbAddr->Bus > PrivateData->BusLimit) {\r
1032 return EFI_INVALID_PARAMETER;\r
1033 }\r
1034\r
1035 if (PciRbAddr->Device > MAX_PCI_DEVICE_NUMBER ||\r
1036 PciRbAddr->Function > MAX_PCI_FUNCTION_NUMBER) {\r
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
1057 } else {\r
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
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
1081\r
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
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
1116 Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,\r
1117 Count, Buffer);\r
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
1125 for (Uint8Buffer = Buffer;\r
1126 Count > 0;\r
1127 Address += InStride, Uint8Buffer += OutStride, Count--) {\r
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
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
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
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
1171 }\r
1172 }\r
1173 }\r
1174 return EFI_SUCCESS;\r
1175}\r
1176\r
1177/**\r
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
1188\r
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
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
1224 Status = RootBridgeIoCheckParameter (This, IoOperation, Width, Address,\r
1225 Count, Buffer);\r
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
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
1278 for (Uint8Buffer = Buffer;\r
1279 Count > 0;\r
1280 Address += InStride, Uint8Buffer += OutStride, Count--) {\r
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
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
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
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
1318 }\r
1319 }\r
1320 }\r
1321 return EFI_SUCCESS;\r
1322}\r
1323\r
1324/**\r
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
1332\r
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
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
1373 Status = RootBridgeIoCheckParameter (This, PciOperation, Width, Address,\r
1374 Count, Buffer);\r
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
1393 for (Uint8Buffer = Buffer;\r
1394 Count > 0;\r
1395 PcieRegAddr += InStride, Uint8Buffer += OutStride, Count--) {\r
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
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
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
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
1433 }\r
1434 }\r
1435 }\r
1436\r
1437 return EFI_SUCCESS;\r
1438}\r
1439\r
1440/**\r
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
1480\r
1481 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
1482 lack of resources.\r
1483**/\r
1484EFI_STATUS\r
1485EFIAPI\r
1486RootBridgeIoPollMem (\r
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
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
1504 if ((UINT32)Width > EfiPciWidthUint64) {\r
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
1514 }\r
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
1521\r
1522 } else {\r
1523\r
1524 //\r
1525 // Determine the proper # of metronome ticks to wait for polling the\r
1526 // location. The nuber of ticks is Roundup (Delay /\r
1527 // mMetronome->TickPeriod)+1\r
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
1534 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod,\r
1535 &Remainder);\r
1536 if (Remainder != 0) {\r
1537 NumberOfTicks += 1;\r
1538 }\r
1539 NumberOfTicks += 1;\r
1540\r
1541 while (NumberOfTicks != 0) {\r
1542\r
1543 mMetronome->WaitForTick (mMetronome, 1);\r
1544\r
1545 Status = This->Mem.Read (This, Width, Address, 1, Result);\r
1546 if (EFI_ERROR (Status)) {\r
1547 return Status;\r
1548 }\r
1549\r
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
1559\r
1560/**\r
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
1589\r
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
1601**/\r
1602EFI_STATUS\r
1603EFIAPI\r
1604RootBridgeIoPollIo (\r
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
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
1626 if ((UINT32)Width > EfiPciWidthUint64) {\r
1627 return EFI_INVALID_PARAMETER;\r
1628 }\r
1629\r
1630 Status = This->Io.Read (This, Width, Address, 1, Result);\r
1631 if (EFI_ERROR (Status)) {\r
1632 return Status;\r
1633 }\r
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
1640\r
1641 } else {\r
1642\r
1643 //\r
1644 // Determine the proper # of metronome ticks to wait for polling the\r
1645 // location. The number of ticks is Roundup (Delay /\r
1646 // mMetronome->TickPeriod)+1\r
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
1650 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod,\r
1651 &Remainder);\r
1652 if (Remainder != 0) {\r
1653 NumberOfTicks += 1;\r
1654 }\r
1655 NumberOfTicks += 1;\r
1656\r
1657 while (NumberOfTicks != 0) {\r
1658\r
1659 mMetronome->WaitForTick (mMetronome, 1);\r
1660\r
1661 Status = This->Io.Read (This, Width, Address, 1, Result);\r
1662 if (EFI_ERROR (Status)) {\r
1663 return Status;\r
1664 }\r
1665\r
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
1676/**\r
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
1699\r
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
1709**/\r
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
1717 OUT VOID *Buffer\r
1718 )\r
1719{\r
1720 return RootBridgeIoMemRW (This, FALSE, Width, Address, Count, Buffer);\r
1721}\r
1722\r
1723/**\r
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
1756**/\r
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
1764 IN VOID *Buffer\r
1765 )\r
1766{\r
1767 return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer);\r
1768}\r
1769\r
1770/**\r
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
1787\r
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
1798**/\r
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
1806 OUT VOID *Buffer\r
1807 )\r
1808{\r
1809 return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer);\r
1810}\r
1811\r
1812/**\r
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
1832\r
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
1839**/\r
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
1847 IN VOID *Buffer\r
1848 )\r
1849{\r
1850 return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer);\r
1851}\r
1852\r
1853/**\r
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
1886\r
1887 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
1888 lack of resources.\r
1889**/\r
1890EFI_STATUS\r
1891EFIAPI\r
1892RootBridgeIoCopyMem (\r
1893 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
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
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
1906 if ((UINT32)Width > EfiPciWidthUint64) {\r
1907 return EFI_INVALID_PARAMETER;\r
1908 }\r
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
1917 if ((DestAddress > SrcAddress) &&\r
1918 (DestAddress < (SrcAddress + Count * Stride))) {\r
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
1956/**\r
1957 Enables a PCI driver to access PCI controller registers in a PCI root\r
1958 bridge's configuration space.\r
1959\r
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
1990**/\r
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
1998 OUT VOID *Buffer\r
1999 )\r
2000{\r
2001 return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);\r
2002}\r
2003\r
2004/**\r
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
2035\r
2036 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
2037 lack of resources.\r
2038**/\r
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
2046 IN VOID *Buffer\r
2047 )\r
2048{\r
2049 return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);\r
2050}\r
2051\r
2052/**\r
2053 Provides the PCI controller-specific addresses required to access system\r
2054 memory from a DMA bus master.\r
2055\r
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
2100**/\r
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
2111{\r
2112 EFI_STATUS Status;\r
2113 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
2114 MAP_INFO *MapInfo;\r
2115\r
2116 if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL ||\r
2117 Mapping == NULL) {\r
2118 return EFI_INVALID_PARAMETER;\r
2119 }\r
2120\r
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
2129 if ((UINT32)Operation >= EfiPciOperationMaximum) {\r
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
2143 // if above 4GB, then it is not possible to generate a mapping, so return\r
2144 // an error.\r
2145 //\r
2146 if (Operation == EfiPciOperationBusMasterCommonBuffer ||\r
2147 Operation == EfiPciOperationBusMasterCommonBuffer64) {\r
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
2156 EfiBootServicesData,\r
2157 sizeof(MAP_INFO),\r
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
2183 AllocateMaxAddress,\r
2184 EfiBootServicesData,\r
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
2199 if (Operation == EfiPciOperationBusMasterRead ||\r
2200 Operation == EfiPciOperationBusMasterRead64) {\r
2201 CopyMem (\r
2202 (VOID *)(UINTN)MapInfo->MappedHostAddress,\r
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
2214 // The transfer is below 4GB, so the DeviceAddress is simply the\r
2215 // HostAddress\r
2216 //\r
2217 *DeviceAddress = PhysicalAddress;\r
2218 }\r
2219\r
2220 return EFI_SUCCESS;\r
2221}\r
2222\r
2223/**\r
2224 Completes the Map() operation and releases any corresponding resources.\r
2225\r
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
2232\r
2233 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2234\r
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
2244**/\r
2245EFI_STATUS\r
2246EFIAPI\r
2247RootBridgeIoUnmap (\r
2248 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
2249 IN VOID *Mapping\r
2250 )\r
2251{\r
2252 MAP_INFO *MapInfo;\r
2253\r
2254 //\r
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
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
2270 if (MapInfo->Operation == EfiPciOperationBusMasterWrite ||\r
2271 MapInfo->Operation == EfiPciOperationBusMasterWrite64) {\r
2272 CopyMem (\r
2273 (VOID *)(UINTN)MapInfo->HostAddress,\r
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
2288/**\r
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
2293\r
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
2322**/\r
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
2333{\r
2334 EFI_STATUS Status;\r
2335 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
2336\r
2337 //\r
2338 // Validate Attributes\r
2339 //\r
2340 if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {\r
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
2350\r
2351 //\r
2352 // The only valid memory types are EfiBootServicesData and\r
2353 // EfiRuntimeServicesData\r
2354 //\r
2355 if (MemoryType != EfiBootServicesData &&\r
2356 MemoryType != EfiRuntimeServicesData) {\r
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
2365 Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages,\r
2366 &PhysicalAddress);\r
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
2376/**\r
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
2381\r
2382 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2383\r
2384 @param Pages The number of pages to free.\r
2385\r
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
2392**/\r
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
2400{\r
2401 return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
2402}\r
2403\r
2404/**\r
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
2425**/\r
2426EFI_STATUS\r
2427EFIAPI\r
2428RootBridgeIoFlush (\r
2429 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
2430 )\r
2431{\r
2432 //\r
2433 // not supported yet\r
2434 //\r
2435 return EFI_SUCCESS;\r
2436}\r
2437\r
2438/**\r
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
2448\r
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
2462**/\r
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
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
2482 if (Supported != NULL) {\r
2483 *Supported = PrivateData->Supports;\r
2484 }\r
2485\r
2486 if (Attributes != NULL) {\r
2487 *Attributes = PrivateData->Attributes;\r
2488 }\r
2489\r
2490 return EFI_SUCCESS;\r
2491}\r
2492\r
2493/**\r
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
2535**/\r
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
2542 IN OUT UINT64 *ResourceLength\r
2543 )\r
2544{\r
2545 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
2546\r
2547 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
2548\r
2549 if (Attributes != 0) {\r
2550 if ((Attributes & (~(PrivateData->Supports))) != 0) {\r
2551 return EFI_UNSUPPORTED;\r
2552 }\r
2553 }\r
2554\r
2555 //\r
2556 // This is a generic driver for a PC-AT class system. It does not have any\r
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
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
2568/**\r
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
2598**/\r
2599EFI_STATUS\r
2600EFIAPI\r
2601RootBridgeIoConfiguration (\r
2602 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
2603 OUT VOID **Resources\r
2604 )\r
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
20f7840e
LE
2610 CopyMem (&PrivateData->ConfigBuffer, &mConfigurationTemplate,\r
2611 sizeof mConfigurationTemplate);\r
d52bde1c
LE
2612\r
2613 for (Index = 0; Index < TypeMax; Index++) {\r
2614 if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {\r
2615 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
2616\r
20f7840e 2617 Desc = &PrivateData->ConfigBuffer.SpaceDesc[Index];\r
d52bde1c
LE
2618 Desc->AddrRangeMin = PrivateData->ResAllocNode[Index].Base;\r
2619 Desc->AddrRangeMax = PrivateData->ResAllocNode[Index].Base +\r
2620 PrivateData->ResAllocNode[Index].Length - 1;\r
2621 Desc->AddrLen = PrivateData->ResAllocNode[Index].Length;\r
2622 }\r
2623 }\r
2624\r
20f7840e 2625 *Resources = &PrivateData->ConfigBuffer;\r
d52bde1c
LE
2626 return EFI_SUCCESS;\r
2627}\r
2628\r