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