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