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