]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.c
StandaloneMmPkg: Apply uncrustify changes
[mirror_edk2.git] / UefiCpuPkg / CpuIo2Dxe / CpuIo2Dxe.c
CommitLineData
3ca55ed4 1/** @file\r
2 Produces the CPU I/O 2 Protocol.\r
3\r
7367cc6c 4Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
200b4223
LD
5Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
6\r
0acd8697 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
3ca55ed4 8\r
9**/\r
10\r
430fbbe0 11#include "CpuIo2Dxe.h"\r
3ea1d3e6 12\r
13//\r
14// Handle for the CPU I/O 2 Protocol\r
15//\r
16EFI_HANDLE mHandle = NULL;\r
17\r
18//\r
19// CPU I/O 2 Protocol instance\r
20//\r
21EFI_CPU_IO2_PROTOCOL mCpuIo2 = {\r
3ca55ed4 22 {\r
23 CpuMemoryServiceRead,\r
24 CpuMemoryServiceWrite\r
25 },\r
26 {\r
27 CpuIoServiceRead,\r
28 CpuIoServiceWrite\r
29 }\r
30};\r
31\r
3ea1d3e6 32//\r
33// Lookup table for increment values based on transfer widths\r
34//\r
35UINT8 mInStride[] = {\r
36 1, // EfiCpuIoWidthUint8\r
37 2, // EfiCpuIoWidthUint16\r
38 4, // EfiCpuIoWidthUint32\r
39 8, // EfiCpuIoWidthUint64\r
40 0, // EfiCpuIoWidthFifoUint8\r
41 0, // EfiCpuIoWidthFifoUint16\r
42 0, // EfiCpuIoWidthFifoUint32\r
43 0, // EfiCpuIoWidthFifoUint64\r
44 1, // EfiCpuIoWidthFillUint8\r
45 2, // EfiCpuIoWidthFillUint16\r
46 4, // EfiCpuIoWidthFillUint32\r
47 8 // EfiCpuIoWidthFillUint64\r
48};\r
3ca55ed4 49\r
3ea1d3e6 50//\r
51// Lookup table for increment values based on transfer widths\r
52//\r
53UINT8 mOutStride[] = {\r
54 1, // EfiCpuIoWidthUint8\r
55 2, // EfiCpuIoWidthUint16\r
56 4, // EfiCpuIoWidthUint32\r
57 8, // EfiCpuIoWidthUint64\r
58 1, // EfiCpuIoWidthFifoUint8\r
59 2, // EfiCpuIoWidthFifoUint16\r
60 4, // EfiCpuIoWidthFifoUint32\r
61 8, // EfiCpuIoWidthFifoUint64\r
62 0, // EfiCpuIoWidthFillUint8\r
63 0, // EfiCpuIoWidthFillUint16\r
64 0, // EfiCpuIoWidthFillUint32\r
65 0 // EfiCpuIoWidthFillUint64\r
66};\r
3ca55ed4 67\r
3ea1d3e6 68/**\r
69 Check parameters to a CPU I/O 2 Protocol service request.\r
3ca55ed4 70\r
7367cc6c
LG
71 The I/O operations are carried out exactly as requested. The caller is responsible\r
72 for satisfying any alignment and I/O width restrictions that a PI System on a\r
73 platform might require. For example on some platforms, width requests of\r
74 EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will\r
3ea1d3e6 75 be handled by the driver.\r
7367cc6c 76\r
3ea1d3e6 77 @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.\r
78 @param[in] Width Signifies the width of the I/O or Memory operation.\r
7367cc6c
LG
79 @param[in] Address The base address of the I/O operation.\r
80 @param[in] Count The number of I/O operations to perform. The number of\r
3ea1d3e6 81 bytes moved is Width size * Count, starting at Address.\r
82 @param[in] Buffer For read operations, the destination buffer to store the results.\r
83 For write operations, the source buffer from which to write data.\r
84\r
85 @retval EFI_SUCCESS The parameters for this request pass the checks.\r
86 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
87 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
88 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
7367cc6c 89 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
3ea1d3e6 90 and Count is not valid for this PI system.\r
3ca55ed4 91\r
92**/\r
93EFI_STATUS\r
94CpuIoCheckParameter (\r
3ea1d3e6 95 IN BOOLEAN MmioOperation,\r
3ca55ed4 96 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
97 IN UINT64 Address,\r
98 IN UINTN Count,\r
3ea1d3e6 99 IN VOID *Buffer\r
3ca55ed4 100 )\r
101{\r
3ea1d3e6 102 UINT64 MaxCount;\r
103 UINT64 Limit;\r
3ca55ed4 104\r
3ea1d3e6 105 //\r
106 // Check to see if Buffer is NULL\r
107 //\r
3ca55ed4 108 if (Buffer == NULL) {\r
109 return EFI_INVALID_PARAMETER;\r
110 }\r
111\r
3ea1d3e6 112 //\r
113 // Check to see if Width is in the valid range\r
114 //\r
3d78c020 115 if ((UINT32)Width >= EfiCpuIoWidthMaximum) {\r
3ea1d3e6 116 return EFI_INVALID_PARAMETER;\r
3ca55ed4 117 }\r
118\r
119 //\r
3ea1d3e6 120 // For FIFO type, the target address won't increase during the access,\r
121 // so treat Count as 1\r
3ca55ed4 122 //\r
123 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
124 Count = 1;\r
125 }\r
126\r
3ea1d3e6 127 //\r
128 // Check to see if Width is in the valid range for I/O Port operations\r
129 //\r
44fdeb35 130 Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
3ea1d3e6 131 if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {\r
132 return EFI_INVALID_PARAMETER;\r
3ca55ed4 133 }\r
7367cc6c 134\r
3ea1d3e6 135 //\r
44fdeb35 136 // Check to see if Address is aligned\r
3ea1d3e6 137 //\r
8491e302 138 if ((Address & ((UINT64)mInStride[Width] - 1)) != 0) {\r
3ca55ed4 139 return EFI_UNSUPPORTED;\r
140 }\r
141\r
3ea1d3e6 142 //\r
7367cc6c 143 // Check to see if any address associated with this transfer exceeds the maximum\r
3ea1d3e6 144 // allowed address. The maximum address implied by the parameters passed in is\r
145 // Address + Size * Count. If the following condition is met, then the transfer\r
146 // is not supported.\r
147 //\r
148 // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1\r
149 //\r
7367cc6c 150 // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count\r
3ea1d3e6 151 // can also be the maximum integer value supported by the CPU, this range\r
152 // check must be adjusted to avoid all oveflow conditions.\r
7367cc6c
LG
153 //\r
154 // The following form of the range check is equivalent but assumes that\r
3ea1d3e6 155 // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).\r
156 //\r
157 Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);\r
158 if (Count == 0) {\r
159 if (Address > Limit) {\r
160 return EFI_UNSUPPORTED;\r
3ca55ed4 161 }\r
7367cc6c 162 } else {\r
3ea1d3e6 163 MaxCount = RShiftU64 (Limit, Width);\r
164 if (MaxCount < (Count - 1)) {\r
165 return EFI_UNSUPPORTED;\r
3ca55ed4 166 }\r
3ea1d3e6 167 if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {\r
168 return EFI_UNSUPPORTED;\r
3ca55ed4 169 }\r
3ca55ed4 170 }\r
171\r
3ca55ed4 172 //\r
44fdeb35 173 // Check to see if Buffer is aligned\r
36de8606 174 // (IA-32 allows UINT64 and INT64 data types to be 32-bit aligned.)\r
3ca55ed4 175 //\r
36de8606 176 if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) {\r
3ea1d3e6 177 return EFI_UNSUPPORTED;\r
3ca55ed4 178 }\r
179\r
180 return EFI_SUCCESS;\r
181}\r
182\r
183/**\r
3ea1d3e6 184 Reads memory-mapped registers.\r
3ca55ed4 185\r
7367cc6c
LG
186 The I/O operations are carried out exactly as requested. The caller is responsible\r
187 for satisfying any alignment and I/O width restrictions that a PI System on a\r
188 platform might require. For example on some platforms, width requests of\r
189 EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will\r
3ea1d3e6 190 be handled by the driver.\r
7367cc6c
LG
191\r
192 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
193 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
3ea1d3e6 194 each of the Count operations that is performed.\r
7367cc6c
LG
195\r
196 If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,\r
197 EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is\r
198 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 199 write operation is performed Count times on the same Address.\r
7367cc6c
LG
200\r
201 If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,\r
202 EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is\r
203 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 204 write operation is performed Count times from the first element of Buffer.\r
7367cc6c 205\r
3ea1d3e6 206 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
207 @param[in] Width Signifies the width of the I/O or Memory operation.\r
7367cc6c
LG
208 @param[in] Address The base address of the I/O operation.\r
209 @param[in] Count The number of I/O operations to perform. The number of\r
3ea1d3e6 210 bytes moved is Width size * Count, starting at Address.\r
211 @param[out] Buffer For read operations, the destination buffer to store the results.\r
212 For write operations, the source buffer from which to write data.\r
213\r
214 @retval EFI_SUCCESS The data was read from or written to the PI system.\r
215 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
216 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
217 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
7367cc6c 218 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
3ea1d3e6 219 and Count is not valid for this PI system.\r
3ca55ed4 220\r
221**/\r
222EFI_STATUS\r
223EFIAPI\r
224CpuMemoryServiceRead (\r
3ea1d3e6 225 IN EFI_CPU_IO2_PROTOCOL *This,\r
226 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
227 IN UINT64 Address,\r
228 IN UINTN Count,\r
229 OUT VOID *Buffer\r
3ca55ed4 230 )\r
231{\r
3ea1d3e6 232 EFI_STATUS Status;\r
233 UINT8 InStride;\r
234 UINT8 OutStride;\r
235 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
236 UINT8 *Uint8Buffer;\r
3ca55ed4 237\r
3ea1d3e6 238 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
3ca55ed4 239 if (EFI_ERROR (Status)) {\r
240 return Status;\r
241 }\r
242\r
3ca55ed4 243 //\r
3ea1d3e6 244 // Select loop based on the width of the transfer\r
3ca55ed4 245 //\r
3ea1d3e6 246 InStride = mInStride[Width];\r
247 OutStride = mOutStride[Width];\r
44fdeb35 248 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
3ea1d3e6 249 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
250 if (OperationWidth == EfiCpuIoWidthUint8) {\r
251 *Uint8Buffer = MmioRead8 ((UINTN)Address);\r
252 } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
253 *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);\r
254 } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
255 *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);\r
256 } else if (OperationWidth == EfiCpuIoWidthUint64) {\r
257 *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);\r
258 }\r
3ca55ed4 259 }\r
3ea1d3e6 260 return EFI_SUCCESS;\r
3ca55ed4 261}\r
262\r
263/**\r
3ea1d3e6 264 Writes memory-mapped registers.\r
3ca55ed4 265\r
7367cc6c
LG
266 The I/O operations are carried out exactly as requested. The caller is responsible\r
267 for satisfying any alignment and I/O width restrictions that a PI System on a\r
268 platform might require. For example on some platforms, width requests of\r
269 EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will\r
3ea1d3e6 270 be handled by the driver.\r
7367cc6c
LG
271\r
272 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
273 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
3ea1d3e6 274 each of the Count operations that is performed.\r
7367cc6c
LG
275\r
276 If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,\r
277 EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is\r
278 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 279 write operation is performed Count times on the same Address.\r
7367cc6c
LG
280\r
281 If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,\r
282 EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is\r
283 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 284 write operation is performed Count times from the first element of Buffer.\r
7367cc6c 285\r
3ea1d3e6 286 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
287 @param[in] Width Signifies the width of the I/O or Memory operation.\r
7367cc6c
LG
288 @param[in] Address The base address of the I/O operation.\r
289 @param[in] Count The number of I/O operations to perform. The number of\r
3ea1d3e6 290 bytes moved is Width size * Count, starting at Address.\r
291 @param[in] Buffer For read operations, the destination buffer to store the results.\r
292 For write operations, the source buffer from which to write data.\r
293\r
294 @retval EFI_SUCCESS The data was read from or written to the PI system.\r
295 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
296 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
297 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
7367cc6c 298 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
3ea1d3e6 299 and Count is not valid for this PI system.\r
3ca55ed4 300\r
301**/\r
302EFI_STATUS\r
303EFIAPI\r
304CpuMemoryServiceWrite (\r
3ea1d3e6 305 IN EFI_CPU_IO2_PROTOCOL *This,\r
306 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
307 IN UINT64 Address,\r
308 IN UINTN Count,\r
309 IN VOID *Buffer\r
3ca55ed4 310 )\r
311{\r
3ca55ed4 312 EFI_STATUS Status;\r
3ea1d3e6 313 UINT8 InStride;\r
314 UINT8 OutStride;\r
315 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
316 UINT8 *Uint8Buffer;\r
3ca55ed4 317\r
3ea1d3e6 318 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
3ca55ed4 319 if (EFI_ERROR (Status)) {\r
320 return Status;\r
321 }\r
322\r
3ca55ed4 323 //\r
3ea1d3e6 324 // Select loop based on the width of the transfer\r
3ca55ed4 325 //\r
3ea1d3e6 326 InStride = mInStride[Width];\r
327 OutStride = mOutStride[Width];\r
44fdeb35 328 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
3ea1d3e6 329 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
330 if (OperationWidth == EfiCpuIoWidthUint8) {\r
331 MmioWrite8 ((UINTN)Address, *Uint8Buffer);\r
332 } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
333 MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));\r
334 } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
335 MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));\r
336 } else if (OperationWidth == EfiCpuIoWidthUint64) {\r
337 MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));\r
338 }\r
3ca55ed4 339 }\r
3ea1d3e6 340 return EFI_SUCCESS;\r
3ca55ed4 341}\r
342\r
343/**\r
3ea1d3e6 344 Reads I/O registers.\r
3ca55ed4 345\r
7367cc6c
LG
346 The I/O operations are carried out exactly as requested. The caller is responsible\r
347 for satisfying any alignment and I/O width restrictions that a PI System on a\r
348 platform might require. For example on some platforms, width requests of\r
349 EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will\r
3ea1d3e6 350 be handled by the driver.\r
7367cc6c
LG
351\r
352 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
353 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
3ea1d3e6 354 each of the Count operations that is performed.\r
7367cc6c
LG
355\r
356 If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,\r
357 EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is\r
358 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 359 write operation is performed Count times on the same Address.\r
7367cc6c
LG
360\r
361 If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,\r
362 EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is\r
363 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 364 write operation is performed Count times from the first element of Buffer.\r
7367cc6c 365\r
3ea1d3e6 366 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
367 @param[in] Width Signifies the width of the I/O or Memory operation.\r
7367cc6c
LG
368 @param[in] Address The base address of the I/O operation.\r
369 @param[in] Count The number of I/O operations to perform. The number of\r
3ea1d3e6 370 bytes moved is Width size * Count, starting at Address.\r
371 @param[out] Buffer For read operations, the destination buffer to store the results.\r
372 For write operations, the source buffer from which to write data.\r
373\r
374 @retval EFI_SUCCESS The data was read from or written to the PI system.\r
375 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
376 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
377 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
7367cc6c 378 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
3ea1d3e6 379 and Count is not valid for this PI system.\r
3ca55ed4 380\r
381**/\r
382EFI_STATUS\r
383EFIAPI\r
384CpuIoServiceRead (\r
3ea1d3e6 385 IN EFI_CPU_IO2_PROTOCOL *This,\r
386 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
387 IN UINT64 Address,\r
388 IN UINTN Count,\r
389 OUT VOID *Buffer\r
3ca55ed4 390 )\r
391{\r
3ea1d3e6 392 EFI_STATUS Status;\r
393 UINT8 InStride;\r
394 UINT8 OutStride;\r
395 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
396 UINT8 *Uint8Buffer;\r
3ca55ed4 397\r
3ea1d3e6 398 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
3ca55ed4 399 if (EFI_ERROR (Status)) {\r
400 return Status;\r
401 }\r
402\r
403 //\r
3ea1d3e6 404 // Select loop based on the width of the transfer\r
3ca55ed4 405 //\r
3ea1d3e6 406 InStride = mInStride[Width];\r
407 OutStride = mOutStride[Width];\r
44fdeb35 408 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
fb8b5469 409\r
200b4223
LD
410 //\r
411 // Fifo operations supported for (mInStride[Width] == 0)\r
412 //\r
fb8b5469
LE
413 if (InStride == 0) {\r
414 switch (OperationWidth) {\r
415 case EfiCpuIoWidthUint8:\r
416 IoReadFifo8 ((UINTN)Address, Count, Buffer);\r
417 return EFI_SUCCESS;\r
418 case EfiCpuIoWidthUint16:\r
419 IoReadFifo16 ((UINTN)Address, Count, Buffer);\r
420 return EFI_SUCCESS;\r
421 case EfiCpuIoWidthUint32:\r
422 IoReadFifo32 ((UINTN)Address, Count, Buffer);\r
423 return EFI_SUCCESS;\r
424 default:\r
425 //\r
426 // The CpuIoCheckParameter call above will ensure that this\r
427 // path is not taken.\r
428 //\r
429 ASSERT (FALSE);\r
430 break;\r
431 }\r
432 }\r
fb8b5469 433\r
3ea1d3e6 434 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
435 if (OperationWidth == EfiCpuIoWidthUint8) {\r
436 *Uint8Buffer = IoRead8 ((UINTN)Address);\r
437 } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
438 *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);\r
439 } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
440 *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);\r
3ca55ed4 441 }\r
3ca55ed4 442 }\r
443\r
444 return EFI_SUCCESS;\r
445}\r
446\r
447/**\r
3ea1d3e6 448 Write I/O registers.\r
3ca55ed4 449\r
7367cc6c
LG
450 The I/O operations are carried out exactly as requested. The caller is responsible\r
451 for satisfying any alignment and I/O width restrictions that a PI System on a\r
452 platform might require. For example on some platforms, width requests of\r
453 EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will\r
3ea1d3e6 454 be handled by the driver.\r
7367cc6c
LG
455\r
456 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
457 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
3ea1d3e6 458 each of the Count operations that is performed.\r
7367cc6c
LG
459\r
460 If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,\r
461 EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is\r
462 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 463 write operation is performed Count times on the same Address.\r
7367cc6c
LG
464\r
465 If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,\r
466 EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is\r
467 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 468 write operation is performed Count times from the first element of Buffer.\r
7367cc6c 469\r
3ea1d3e6 470 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
471 @param[in] Width Signifies the width of the I/O or Memory operation.\r
7367cc6c
LG
472 @param[in] Address The base address of the I/O operation.\r
473 @param[in] Count The number of I/O operations to perform. The number of\r
3ea1d3e6 474 bytes moved is Width size * Count, starting at Address.\r
475 @param[in] Buffer For read operations, the destination buffer to store the results.\r
476 For write operations, the source buffer from which to write data.\r
477\r
478 @retval EFI_SUCCESS The data was read from or written to the PI system.\r
479 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
480 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
481 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
7367cc6c 482 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
3ea1d3e6 483 and Count is not valid for this PI system.\r
7367cc6c 484\r
3ca55ed4 485**/\r
486EFI_STATUS\r
487EFIAPI\r
488CpuIoServiceWrite (\r
3ea1d3e6 489 IN EFI_CPU_IO2_PROTOCOL *This,\r
490 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
491 IN UINT64 Address,\r
492 IN UINTN Count,\r
493 IN VOID *Buffer\r
3ca55ed4 494 )\r
495{\r
3ea1d3e6 496 EFI_STATUS Status;\r
497 UINT8 InStride;\r
498 UINT8 OutStride;\r
499 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
500 UINT8 *Uint8Buffer;\r
3ca55ed4 501\r
502 //\r
3ea1d3e6 503 // Make sure the parameters are valid\r
3ca55ed4 504 //\r
3ea1d3e6 505 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
506 if (EFI_ERROR (Status)) {\r
507 return Status;\r
3ca55ed4 508 }\r
509\r
510 //\r
3ea1d3e6 511 // Select loop based on the width of the transfer\r
3ca55ed4 512 //\r
3ea1d3e6 513 InStride = mInStride[Width];\r
514 OutStride = mOutStride[Width];\r
44fdeb35 515 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
fb8b5469 516\r
200b4223
LD
517 //\r
518 // Fifo operations supported for (mInStride[Width] == 0)\r
519 //\r
fb8b5469
LE
520 if (InStride == 0) {\r
521 switch (OperationWidth) {\r
522 case EfiCpuIoWidthUint8:\r
523 IoWriteFifo8 ((UINTN)Address, Count, Buffer);\r
524 return EFI_SUCCESS;\r
525 case EfiCpuIoWidthUint16:\r
526 IoWriteFifo16 ((UINTN)Address, Count, Buffer);\r
527 return EFI_SUCCESS;\r
528 case EfiCpuIoWidthUint32:\r
529 IoWriteFifo32 ((UINTN)Address, Count, Buffer);\r
530 return EFI_SUCCESS;\r
531 default:\r
532 //\r
533 // The CpuIoCheckParameter call above will ensure that this\r
534 // path is not taken.\r
535 //\r
536 ASSERT (FALSE);\r
537 break;\r
538 }\r
539 }\r
fb8b5469 540\r
3ea1d3e6 541 for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
542 if (OperationWidth == EfiCpuIoWidthUint8) {\r
543 IoWrite8 ((UINTN)Address, *Uint8Buffer);\r
544 } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
545 IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));\r
546 } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
547 IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));\r
3ca55ed4 548 }\r
3ca55ed4 549 }\r
7367cc6c 550\r
3ca55ed4 551 return EFI_SUCCESS;\r
552}\r
553\r
554/**\r
3ea1d3e6 555 The user Entry Point for module CpuIo2Dxe. The user code starts with this function.\r
556\r
7367cc6c 557 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
3ea1d3e6 558 @param[in] SystemTable A pointer to the EFI System Table.\r
7367cc6c 559\r
3ea1d3e6 560 @retval EFI_SUCCESS The entry point is executed successfully.\r
561 @retval other Some error occurs when executing this entry point.\r
3ca55ed4 562\r
563**/\r
564EFI_STATUS\r
565EFIAPI\r
566CpuIo2Initialize (\r
567 IN EFI_HANDLE ImageHandle,\r
568 IN EFI_SYSTEM_TABLE *SystemTable\r
569 )\r
570{\r
3ea1d3e6 571 EFI_STATUS Status;\r
3ca55ed4 572\r
3ea1d3e6 573 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);\r
574 Status = gBS->InstallMultipleProtocolInterfaces (\r
3ca55ed4 575 &mHandle,\r
3ea1d3e6 576 &gEfiCpuIo2ProtocolGuid, &mCpuIo2,\r
577 NULL\r
3ca55ed4 578 );\r
579 ASSERT_EFI_ERROR (Status);\r
580\r
581 return Status;\r
582}\r