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