]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/CpuIoDxe/CpuIo.c
Clean up to update the reference of the these macros:
[mirror_edk2.git] / DuetPkg / CpuIoDxe / CpuIo.c
CommitLineData
c69dd9df 1/*++\r
2\r
3Copyright (c) 2004 - 2007, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13 CpuIo.c\r
14\r
15Abstract:\r
16\r
17 This is the code that publishes the CPU I/O Protocol.\r
18 The intent herein is to have a single I/O service that can load\r
19 as early as possible, extend into runtime, and be layered upon by\r
20 the implementations of architectural protocols and the PCI Root\r
21 Bridge I/O Protocol.\r
22\r
23--*/\r
24\r
25#include "CpuIo.h"\r
26#include "CpuIoAccess.h"\r
27\r
28#define IA32_MAX_IO_ADDRESS 0xFFFF\r
29\r
30EFI_CPU_IO_PROTOCOL mCpuIo = {\r
31 {\r
32 CpuMemoryServiceRead,\r
33 CpuMemoryServiceWrite\r
34 },\r
35 {\r
36 CpuIoServiceRead,\r
37 CpuIoServiceWrite\r
38 }\r
39};\r
40\r
c69dd9df 41EFI_STATUS\r
42CpuIoMemRW (\r
43 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
44 IN UINTN Count,\r
45 IN BOOLEAN DestinationStrideFlag,\r
46 OUT PTR Destination,\r
47 IN BOOLEAN SourceStrideFlag,\r
48 IN PTR Source\r
49 )\r
50/*++\r
51\r
52Routine Description:\r
53\r
54 Private service to perform memory mapped I/O read/write\r
55\r
56Arguments:\r
57\r
58 Width - Width of the memory mapped I/O operation\r
59 Count - Count of the number of accesses to perform\r
60 DestinationStrideFlag - Boolean flag indicates if the destination is to be incremented\r
61 Destination - Destination of the memory mapped I/O operation\r
62 SourceStrideFlag - Boolean flag indicates if the source is to be incremented\r
63 Source - Source of the memory mapped I/O operation\r
64\r
65Returns:\r
66\r
67 EFI_SUCCESS - Successful operation\r
68 EFI_INVALID_PARAMETER - Width is invalid\r
69\r
70--*/\r
71{\r
72 UINTN Stride;\r
73 UINTN DestinationStride;\r
74 UINTN SourceStride;\r
75\r
e188a609 76 Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
c69dd9df 77 Stride = (UINTN)1 << Width;\r
78 DestinationStride = DestinationStrideFlag ? Stride : 0;\r
79 SourceStride = SourceStrideFlag ? Stride : 0;\r
80\r
81 //\r
82 // Loop for each iteration and move the data\r
83 //\r
84 switch (Width) {\r
85 case EfiCpuIoWidthUint8:\r
86 for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {\r
87 MemoryFence();\r
88 *Destination.ui8 = *Source.ui8;\r
89 MemoryFence();\r
90 }\r
91 break;\r
92\r
93 case EfiCpuIoWidthUint16:\r
94 for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {\r
95 MemoryFence ();\r
96 *Destination.ui16 = *Source.ui16;\r
97 MemoryFence ();\r
98 }\r
99 break;\r
100\r
101 case EfiCpuIoWidthUint32:\r
102 for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {\r
103 MemoryFence ();\r
104 *Destination.ui32 = *Source.ui32;\r
105 MemoryFence ();\r
106 }\r
107 break;\r
108\r
109 case EfiCpuIoWidthUint64:\r
110 for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {\r
111 MemoryFence ();\r
112 *Destination.ui64 = *Source.ui64;\r
113 MemoryFence ();\r
114 }\r
115 break;\r
116\r
117 default:\r
118 return EFI_INVALID_PARAMETER;\r
119 }\r
120\r
121 return EFI_SUCCESS;\r
122}\r
123\r
124EFI_STATUS\r
125EFIAPI\r
126CpuMemoryServiceRead (\r
127 IN EFI_CPU_IO_PROTOCOL *This,\r
128 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
129 IN UINT64 Address,\r
130 IN UINTN Count,\r
131 OUT VOID *Buffer\r
132 )\r
133/*++\r
134\r
135Routine Description:\r
136\r
137 Perform the memory mapped I/O read service\r
138\r
139Arguments:\r
140\r
141 This - Pointer to an instance of the CPU I/O Protocol\r
142 Width - Width of the memory mapped I/O operation\r
143 Address - Base address of the memory mapped I/O operation\r
144 Count - Count of the number of accesses to perform\r
145 Buffer - Pointer to the destination buffer to store the results\r
146\r
147Returns:\r
148\r
149 EFI_SUCCESS - The data was read.\r
150 EFI_INVALID_PARAMETER - Width is invalid.\r
151 EFI_INVALID_PARAMETER - Buffer is NULL.\r
152 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
153 EFI_UNSUPPORTED - The address range specified by Address, Width,\r
154 and Count is not valid.\r
155\r
156--*/\r
157{\r
158 PTR Source;\r
159 PTR Destination;\r
160 EFI_STATUS Status;\r
161\r
162 Status = CpuIoCheckParameter (Width, Address, Count, Buffer, EFI_MAX_ADDRESS);\r
163 if (EFI_ERROR (Status)) {\r
164 return Status;\r
165 }\r
166\r
167 Destination.buf = Buffer;\r
168 Source.buf = (VOID *) (UINTN) Address;\r
169\r
170 if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) {\r
171 return CpuIoMemRW (Width, Count, TRUE, Destination, TRUE, Source);\r
172 }\r
173\r
174 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
175 return CpuIoMemRW (Width, Count, TRUE, Destination, FALSE, Source);\r
176 }\r
177\r
178 if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
179 return CpuIoMemRW (Width, Count, FALSE, Destination, TRUE, Source);\r
180 }\r
181\r
182 return EFI_INVALID_PARAMETER;\r
183}\r
184\r
185EFI_STATUS\r
186EFIAPI\r
187CpuMemoryServiceWrite (\r
188 IN EFI_CPU_IO_PROTOCOL *This,\r
189 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
190 IN UINT64 Address,\r
191 IN UINTN Count,\r
192 IN VOID *Buffer\r
193 )\r
194/*++\r
195\r
196Routine Description:\r
197\r
198 Perform the memory mapped I/O write service\r
199\r
200Arguments:\r
201\r
202 This - Pointer to an instance of the CPU I/O Protocol\r
203 Width - Width of the memory mapped I/O operation\r
204 Address - Base address of the memory mapped I/O operation\r
205 Count - Count of the number of accesses to perform\r
206 Buffer - Pointer to the source buffer from which to write data\r
207\r
208Returns:\r
209\r
210 EFI_SUCCESS - The data was written.\r
211 EFI_INVALID_PARAMETER - Width is invalid.\r
212 EFI_INVALID_PARAMETER - Buffer is NULL.\r
213 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
214 EFI_UNSUPPORTED - The address range specified by Address, Width,\r
215 and Count is not valid.\r
216\r
217--*/\r
218{\r
219 PTR Source;\r
220 PTR Destination;\r
221 EFI_STATUS Status;\r
222\r
223 Status = CpuIoCheckParameter (Width, Address, Count, Buffer, EFI_MAX_ADDRESS);\r
224 if (EFI_ERROR (Status)) {\r
225 return Status;\r
226 }\r
227\r
228 Destination.buf = (VOID *) (UINTN) Address;\r
229 Source.buf = Buffer;\r
230\r
231 if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) {\r
232 return CpuIoMemRW (Width, Count, TRUE, Destination, TRUE, Source);\r
233 }\r
234\r
235 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
236 return CpuIoMemRW (Width, Count, FALSE, Destination, TRUE, Source);\r
237 }\r
238\r
239 if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
240 return CpuIoMemRW (Width, Count, TRUE, Destination, FALSE, Source);\r
241 }\r
242\r
243 return EFI_INVALID_PARAMETER;\r
244}\r
245\r
246EFI_STATUS\r
247EFIAPI\r
248CpuIoServiceRead (\r
249 IN EFI_CPU_IO_PROTOCOL *This,\r
250 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
251 IN UINT64 UserAddress,\r
252 IN UINTN Count,\r
253 OUT VOID *UserBuffer\r
254 )\r
255/*++\r
256\r
257Routine Description:\r
258\r
259 Perform the port I/O read service\r
260\r
261Arguments:\r
262\r
263 This - Pointer to an instance of the CPU I/O Protocol\r
264 Width - Width of the port I/O operation\r
265 Address - Base address of the port I/O operation\r
266 Count - Count of the number of accesses to perform\r
267 Buffer - Pointer to the destination buffer to store the results\r
268\r
269Returns:\r
270\r
271 EFI_SUCCESS - The data was read.\r
272 EFI_INVALID_PARAMETER - Width is invalid.\r
273 EFI_INVALID_PARAMETER - Buffer is NULL.\r
274 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
275 EFI_UNSUPPORTED - The address range specified by Address, Width,\r
276 and Count is not valid.\r
277\r
278--*/\r
279{\r
280 UINTN InStride;\r
281 UINTN OutStride;\r
282 UINTN Address;\r
283 PTR Buffer;\r
284 EFI_STATUS Status;\r
285\r
286 Buffer.buf = (UINT8 *) UserBuffer;\r
287\r
288 if (Width >= EfiCpuIoWidthMaximum) {\r
289 return EFI_INVALID_PARAMETER;\r
290 }\r
291\r
292 Status = CpuIoCheckParameter (Width, UserAddress, Count, UserBuffer, IA32_MAX_IO_ADDRESS);\r
293 if (EFI_ERROR (Status)) {\r
294 return Status;\r
295 }\r
296\r
297 Address = (UINTN) UserAddress;\r
298 InStride = (UINTN)1 << (Width & 0x03);\r
299 OutStride = InStride;\r
300 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
301 InStride = 0;\r
302 }\r
303\r
304 if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
305 OutStride = 0;\r
306 }\r
307\r
e188a609 308 Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
c69dd9df 309\r
310 //\r
311 // Loop for each iteration and move the data\r
312 //\r
313 switch (Width) {\r
314 case EfiCpuIoWidthUint8:\r
315 for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
316 *Buffer.ui8 = CpuIoRead8 ((UINT16) Address);\r
317 }\r
318 break;\r
319\r
320 case EfiCpuIoWidthUint16:\r
321 for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
322 *Buffer.ui16 = CpuIoRead16 ((UINT16) Address);\r
323 }\r
324 break;\r
325\r
326 case EfiCpuIoWidthUint32:\r
327 for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
328 *Buffer.ui32 = CpuIoRead32 ((UINT16) Address);\r
329 }\r
330 break;\r
331\r
332 default:\r
333 return EFI_INVALID_PARAMETER;\r
334 }\r
335\r
336 return EFI_SUCCESS;\r
337}\r
338\r
339EFI_STATUS\r
340EFIAPI\r
341CpuIoServiceWrite (\r
342 IN EFI_CPU_IO_PROTOCOL *This,\r
343 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
344 IN UINT64 UserAddress,\r
345 IN UINTN Count,\r
346 IN VOID *UserBuffer\r
347 )\r
348/*++\r
349\r
350Routine Description:\r
351\r
352 Perform the port I/O write service\r
353\r
354Arguments:\r
355\r
356 This - Pointer to an instance of the CPU I/O Protocol\r
357 Width - Width of the port I/O operation\r
358 Address - Base address of the port I/O operation\r
359 Count - Count of the number of accesses to perform\r
360 Buffer - Pointer to the source buffer from which to write data\r
361\r
362Returns:\r
363\r
364 EFI_SUCCESS - The data was written.\r
365 EFI_INVALID_PARAMETER - Width is invalid.\r
366 EFI_INVALID_PARAMETER - Buffer is NULL.\r
367 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
368 EFI_UNSUPPORTED - The address range specified by Address, Width,\r
369 and Count is not valid.\r
370\r
371--*/\r
372{\r
373 UINTN InStride;\r
374 UINTN OutStride;\r
375 UINTN Address;\r
376 PTR Buffer;\r
377 EFI_STATUS Status;\r
378\r
379 Buffer.buf = (UINT8 *) UserBuffer;\r
380\r
381 if (Width >= EfiCpuIoWidthMaximum) {\r
382 return EFI_INVALID_PARAMETER;\r
383 }\r
384\r
385 Status = CpuIoCheckParameter (Width, UserAddress, Count, UserBuffer, IA32_MAX_IO_ADDRESS);\r
386 if (EFI_ERROR (Status)) {\r
387 return Status;\r
388 }\r
389\r
390 Address = (UINTN) UserAddress;\r
391 InStride = (UINTN)1 << (Width & 0x03);\r
392 OutStride = InStride;\r
393 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
394 InStride = 0;\r
395 }\r
396\r
397 if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
398 OutStride = 0;\r
399 }\r
400\r
e188a609 401 Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
c69dd9df 402\r
403 //\r
404 // Loop for each iteration and move the data\r
405 //\r
406 switch (Width) {\r
407 case EfiCpuIoWidthUint8:\r
408 for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
409 CpuIoWrite8 ((UINT16) Address, *Buffer.ui8);\r
410 }\r
411 break;\r
412\r
413 case EfiCpuIoWidthUint16:\r
414 for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
415 CpuIoWrite16 ((UINT16) Address, *Buffer.ui16);\r
416 }\r
417 break;\r
418\r
419 case EfiCpuIoWidthUint32:\r
420 for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
421 CpuIoWrite32 ((UINT16) Address, *Buffer.ui32);\r
422 }\r
423 break;\r
424\r
425 default:\r
426 return EFI_INVALID_PARAMETER;\r
427 }\r
428\r
429 return EFI_SUCCESS;\r
430}\r
431\r
432EFI_STATUS\r
433EFIAPI\r
434CpuIoInitialize (\r
435 IN EFI_HANDLE ImageHandle,\r
436 IN EFI_SYSTEM_TABLE *SystemTable\r
437 )\r
438/*++\r
439\r
440Routine Description:\r
441\r
442 CpuIo driver entry point.\r
443\r
444Arguments:\r
445\r
446 ImageHandle - The firmware allocated handle for the EFI image.\r
447 SystemTable - A pointer to the EFI System Table.\r
448\r
449Returns:\r
450\r
451 EFI_SUCCESS - The driver was initialized.\r
452 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.\r
453\r
454--*/\r
455{\r
456 EFI_STATUS Status;\r
457 EFI_HANDLE Handle;\r
458\r
459 Handle = NULL;\r
460 Status = SystemTable->BootServices->InstallProtocolInterface (\r
461 &Handle,\r
462 &gEfiCpuIoProtocolGuid,\r
463 EFI_NATIVE_INTERFACE,\r
464 &mCpuIo\r
465 );\r
466 ASSERT_EFI_ERROR (Status);\r
467\r
468 return Status;\r
469}\r
470\r
471EFI_STATUS\r
472CpuIoCheckParameter (\r
473 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
474 IN UINT64 Address,\r
475 IN UINTN Count,\r
476 IN VOID *Buffer,\r
477 IN UINT64 Limit\r
478 )\r
479/*++\r
480\r
481Routine Description:\r
482\r
483 Check the validation of parameters for CPU I/O interface functions.\r
484\r
485Arguments:\r
486\r
487 Width - Width of the Memory Access\r
488 Address - Address of the Memory access\r
489 Count - Count of the number of accesses to perform\r
490 Buffer - Pointer to the buffer to read from memory\r
491 Buffer - Memory buffer for the I/O operation\r
492 Limit - Maximum address supported\r
493\r
494Returns:\r
495\r
496 EFI_INVALID_PARAMETER - Buffer is NULL\r
497 EFI_UNSUPPORTED - The address range specified by Width, Address and Count is invalid\r
498 EFI_UNSUPPORTED - The memory buffer is not aligned\r
499 EFI_SUCCESS - Parameters are OK\r
500\r
501--*/\r
502{\r
503 UINTN AlignMask;\r
504\r
505 if (Buffer == NULL) {\r
506 return EFI_INVALID_PARAMETER;\r
507 }\r
508\r
509 if (Address > Limit) {\r
510 return EFI_UNSUPPORTED;\r
511 }\r
512\r
513 //\r
514 // For FiFo type, the target address won't increase during the access,\r
515 // so treat count as 1\r
516 //\r
517 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
518 Count = 1;\r
519 }\r
520\r
e188a609 521 Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
c69dd9df 522 if (Address - 1 + ((UINTN)1 << Width) * Count > Limit) {\r
523 return EFI_UNSUPPORTED;\r
524 }\r
525\r
526 AlignMask = ((UINTN)1 << Width) - 1;\r
527 if ((UINTN) Buffer & AlignMask) {\r
528 return EFI_UNSUPPORTED;\r
529 }\r
530\r
531 return EFI_SUCCESS;\r
532}\r