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