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