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