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