1 /** @file
2   I/O Library.
3   The implementation of I/O operation for this library instance
4   are based on EFI_CPU_IO_PROTOCOL.
5 
6   Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
7   This program and the accompanying materials
8   are licensed and made available under the terms and conditions of the BSD License
9   which accompanies this distribution.  The full text of the license may be found at
10   http://opensource.org/licenses/bsd-license.php
11 
12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15   Module Name:  IoLib.c
16 
17 **/
18 
19 
20 #include "DxeCpuIoLibInternal.h"
21 
22 //
23 // Globle varible to cache pointer to CpuIo protocol.
24 //
25 EFI_CPU_IO_PROTOCOL  *mCpuIo = NULL;
26 
27 /**
28   The constructor function caches the pointer to CpuIo protocol.
29 
30   The constructor function locates CpuIo protocol from protocol database.
31   It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
32 
33   @param  ImageHandle   The firmware allocated handle for the EFI image.
34   @param  SystemTable   A pointer to the EFI System Table.
35 
36   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
37 
38 **/
39 EFI_STATUS
40 EFIAPI
IoLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)41 IoLibConstructor (
42   IN      EFI_HANDLE                ImageHandle,
43   IN      EFI_SYSTEM_TABLE          *SystemTable
44   )
45 {
46   EFI_STATUS  Status;
47 
48   Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, (VOID **) &mCpuIo);
49   ASSERT_EFI_ERROR (Status);
50 
51   return Status;
52 }
53 
54 /**
55   Reads registers in the EFI CPU I/O space.
56 
57   Reads the I/O port specified by Port with registers width specified by Width.
58   The read value is returned. If such operations are not supported, then ASSERT().
59   This function must guarantee that all I/O read and write operations are serialized.
60 
61   @param  Port          The base address of the I/O operation.
62                         The caller is responsible for aligning the Address if required.
63   @param  Width         The width of the I/O operation.
64 
65   @return Data read from registers in the EFI CPU I/O space.
66 
67 **/
68 UINT64
69 EFIAPI
IoReadWorker(IN UINTN Port,IN EFI_CPU_IO_PROTOCOL_WIDTH Width)70 IoReadWorker (
71   IN      UINTN                      Port,
72   IN      EFI_CPU_IO_PROTOCOL_WIDTH  Width
73   )
74 {
75   EFI_STATUS                        Status;
76   UINT64                            Data;
77 
78   Status = mCpuIo->Io.Read (mCpuIo, Width, Port, 1, &Data);
79   ASSERT_EFI_ERROR (Status);
80 
81   return Data;
82 }
83 
84 /**
85   Writes registers in the EFI CPU I/O space.
86 
87   Writes the I/O port specified by Port with registers width and value specified by Width
88   and Data respectively.  Data is returned. If such operations are not supported, then ASSERT().
89   This function must guarantee that all I/O read and write operations are serialized.
90 
91   @param  Port          The base address of the I/O operation.
92                         The caller is responsible for aligning the Address if required.
93   @param  Width         The width of the I/O operation.
94   @param  Data          The value to write to the I/O port.
95 
96   @return The paramter of Data.
97 
98 **/
99 UINT64
100 EFIAPI
IoWriteWorker(IN UINTN Port,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Data)101 IoWriteWorker (
102   IN      UINTN                      Port,
103   IN      EFI_CPU_IO_PROTOCOL_WIDTH  Width,
104   IN      UINT64                     Data
105   )
106 {
107   EFI_STATUS  Status;
108 
109   Status = mCpuIo->Io.Write (mCpuIo, Width, Port, 1, &Data);
110   ASSERT_EFI_ERROR (Status);
111 
112   return Data;
113 }
114 
115 /**
116   Reads memory-mapped registers in the EFI system memory space.
117 
118   Reads the MMIO registers specified by Address with registers width specified by Width.
119   The read value is returned. If such operations are not supported, then ASSERT().
120   This function must guarantee that all MMIO read and write operations are serialized.
121 
122   @param  Address       The MMIO register to read.
123                         The caller is responsible for aligning the Address if required.
124   @param  Width         The width of the I/O operation.
125 
126   @return Data read from registers in the EFI system memory space.
127 
128 **/
129 UINT64
130 EFIAPI
MmioReadWorker(IN UINTN Address,IN EFI_CPU_IO_PROTOCOL_WIDTH Width)131 MmioReadWorker (
132   IN      UINTN                      Address,
133   IN      EFI_CPU_IO_PROTOCOL_WIDTH  Width
134   )
135 {
136   EFI_STATUS  Status;
137   UINT64      Data;
138 
139   Status = mCpuIo->Mem.Read (mCpuIo, Width, Address, 1, &Data);
140   ASSERT_EFI_ERROR (Status);
141 
142   return Data;
143 }
144 
145 /**
146   Writes memory-mapped registers in the EFI system memory space.
147 
148   Writes the MMIO registers specified by Address with registers width and value specified by Width
149   and Data respectively. Data is returned. If such operations are not supported, then ASSERT().
150   This function must guarantee that all MMIO read and write operations are serialized.
151 
152   @param  Address       The MMIO register to read.
153                         The caller is responsible for aligning the Address if required.
154   @param  Width         The width of the I/O operation.
155   @param  Data          The value to write to the I/O port.
156 
157   @return Data read from registers in the EFI system memory space.
158 
159 **/
160 UINT64
161 EFIAPI
MmioWriteWorker(IN UINTN Address,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Data)162 MmioWriteWorker (
163   IN      UINTN                      Address,
164   IN      EFI_CPU_IO_PROTOCOL_WIDTH  Width,
165   IN      UINT64                     Data
166   )
167 {
168   EFI_STATUS  Status;
169 
170   Status = mCpuIo->Mem.Write (mCpuIo, Width, Address, 1, &Data);
171   ASSERT_EFI_ERROR (Status);
172 
173   return Data;
174 }
175 
176 /**
177   Reads an 8-bit I/O port.
178 
179   Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned.
180   This function must guarantee that all I/O read and write operations are
181   serialized.
182 
183   If 8-bit I/O port operations are not supported, then ASSERT().
184 
185   @param  Port  The I/O port to read.
186 
187   @return The value read.
188 
189 **/
190 UINT8
191 EFIAPI
IoRead8(IN UINTN Port)192 IoRead8 (
193   IN      UINTN                     Port
194   )
195 {
196   return (UINT8)IoReadWorker (Port, EfiCpuIoWidthUint8);
197 }
198 
199 /**
200   Writes an 8-bit I/O port.
201 
202   Writes the 8-bit I/O port specified by Port with the value specified by Value
203   and returns Value. This function must guarantee that all I/O read and write
204   operations are serialized.
205 
206   If 8-bit I/O port operations are not supported, then ASSERT().
207 
208   @param  Port  The I/O port to write.
209   @param  Value The value to write to the I/O port.
210 
211   @return The value written the I/O port.
212 
213 **/
214 UINT8
215 EFIAPI
IoWrite8(IN UINTN Port,IN UINT8 Value)216 IoWrite8 (
217   IN      UINTN                     Port,
218   IN      UINT8                     Value
219   )
220 {
221   return (UINT8)IoWriteWorker (Port, EfiCpuIoWidthUint8, Value);
222 }
223 
224 /**
225   Reads a 16-bit I/O port.
226 
227   Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned.
228   This function must guarantee that all I/O read and write operations are
229   serialized.
230 
231   If Port is not aligned on a 16-bit boundary, then ASSERT().
232 
233   If 16-bit I/O port operations are not supported, then ASSERT().
234 
235   @param  Port  The I/O port to read.
236 
237   @return The value read.
238 
239 **/
240 UINT16
241 EFIAPI
IoRead16(IN UINTN Port)242 IoRead16 (
243   IN      UINTN                     Port
244   )
245 {
246   //
247   // Make sure Port is aligned on a 16-bit boundary.
248   //
249   ASSERT ((Port & 1) == 0);
250   return (UINT16)IoReadWorker (Port, EfiCpuIoWidthUint16);
251 }
252 
253 /**
254   Writes a 16-bit I/O port.
255 
256   Writes the 16-bit I/O port specified by Port with the value specified by Value
257   and returns Value. This function must guarantee that all I/O read and write
258   operations are serialized.
259 
260   If Port is not aligned on a 16-bit boundary, then ASSERT().
261 
262   If 16-bit I/O port operations are not supported, then ASSERT().
263 
264   @param  Port  The I/O port to write.
265   @param  Value The value to write to the I/O port.
266 
267   @return The value written the I/O port.
268 
269 **/
270 UINT16
271 EFIAPI
IoWrite16(IN UINTN Port,IN UINT16 Value)272 IoWrite16 (
273   IN      UINTN                     Port,
274   IN      UINT16                    Value
275   )
276 {
277   //
278   // Make sure Port is aligned on a 16-bit boundary.
279   //
280   ASSERT ((Port & 1) == 0);
281   return (UINT16)IoWriteWorker (Port, EfiCpuIoWidthUint16, Value);
282 }
283 
284 /**
285   Reads a 32-bit I/O port.
286 
287   Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned.
288   This function must guarantee that all I/O read and write operations are
289   serialized.
290 
291   If Port is not aligned on a 32-bit boundary, then ASSERT().
292 
293   If 32-bit I/O port operations are not supported, then ASSERT().
294 
295   @param  Port  The I/O port to read.
296 
297   @return The value read.
298 
299 **/
300 UINT32
301 EFIAPI
IoRead32(IN UINTN Port)302 IoRead32 (
303   IN      UINTN                     Port
304   )
305 {
306   //
307   // Make sure Port is aligned on a 32-bit boundary.
308   //
309   ASSERT ((Port & 3) == 0);
310   return (UINT32)IoReadWorker (Port, EfiCpuIoWidthUint32);
311 }
312 
313 /**
314   Writes a 32-bit I/O port.
315 
316   Writes the 32-bit I/O port specified by Port with the value specified by Value
317   and returns Value. This function must guarantee that all I/O read and write
318   operations are serialized.
319 
320   If Port is not aligned on a 32-bit boundary, then ASSERT().
321 
322   If 32-bit I/O port operations are not supported, then ASSERT().
323 
324   @param  Port  The I/O port to write.
325   @param  Value The value to write to the I/O port.
326 
327   @return The value written the I/O port.
328 
329 **/
330 UINT32
331 EFIAPI
IoWrite32(IN UINTN Port,IN UINT32 Value)332 IoWrite32 (
333   IN      UINTN                     Port,
334   IN      UINT32                    Value
335   )
336 {
337   //
338   // Make sure Port is aligned on a 32-bit boundary.
339   //
340   ASSERT ((Port & 3) == 0);
341   return (UINT32)IoWriteWorker (Port, EfiCpuIoWidthUint32, Value);
342 }
343 
344 /**
345   Reads a 64-bit I/O port.
346 
347   Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned.
348   This function must guarantee that all I/O read and write operations are
349   serialized.
350 
351   If Port is not aligned on a 64-bit boundary, then ASSERT().
352 
353   If 64-bit I/O port operations are not supported, then ASSERT().
354 
355   @param  Port  The I/O port to read.
356 
357   @return The value read.
358 
359 **/
360 UINT64
361 EFIAPI
IoRead64(IN UINTN Port)362 IoRead64 (
363   IN      UINTN                     Port
364   )
365 {
366   //
367   // Make sure Port is aligned on a 64-bit boundary.
368   //
369   ASSERT ((Port & 7) == 0);
370   return IoReadWorker (Port, EfiCpuIoWidthUint64);
371 }
372 
373 /**
374   Writes a 64-bit I/O port.
375 
376   Writes the 64-bit I/O port specified by Port with the value specified by Value
377   and returns Value. This function must guarantee that all I/O read and write
378   operations are serialized.
379 
380   If Port is not aligned on a 64-bit boundary, then ASSERT().
381 
382   If 64-bit I/O port operations are not supported, then ASSERT().
383 
384   @param  Port  The I/O port to write.
385   @param  Value The value to write to the I/O port.
386 
387   @return The value written the I/O port.
388 
389 **/
390 UINT64
391 EFIAPI
IoWrite64(IN UINTN Port,IN UINT64 Value)392 IoWrite64 (
393   IN      UINTN                     Port,
394   IN      UINT64                    Value
395   )
396 {
397   //
398   // Make sure Port is aligned on a 64-bit boundary.
399   //
400   ASSERT ((Port & 7) == 0);
401   return IoWriteWorker (Port, EfiCpuIoWidthUint64, Value);
402 }
403 
404 /**
405   Reads an 8-bit MMIO register.
406 
407   Reads the 8-bit MMIO register specified by Address. The 8-bit read value is
408   returned. This function must guarantee that all MMIO read and write
409   operations are serialized.
410 
411   If 8-bit MMIO register operations are not supported, then ASSERT().
412 
413   @param  Address The MMIO register to read.
414 
415   @return The value read.
416 
417 **/
418 UINT8
419 EFIAPI
MmioRead8(IN UINTN Address)420 MmioRead8 (
421   IN      UINTN                     Address
422   )
423 {
424   return (UINT8)MmioReadWorker (Address, EfiCpuIoWidthUint8);
425 }
426 
427 /**
428   Writes an 8-bit MMIO register.
429 
430   Writes the 8-bit MMIO register specified by Address with the value specified
431   by Value and returns Value. This function must guarantee that all MMIO read
432   and write operations are serialized.
433 
434   If 8-bit MMIO register operations are not supported, then ASSERT().
435 
436   @param  Address The MMIO register to write.
437   @param  Value   The value to write to the MMIO register.
438 
439 **/
440 UINT8
441 EFIAPI
MmioWrite8(IN UINTN Address,IN UINT8 Value)442 MmioWrite8 (
443   IN      UINTN                     Address,
444   IN      UINT8                     Value
445   )
446 {
447   return (UINT8)MmioWriteWorker (Address, EfiCpuIoWidthUint8, Value);
448 }
449 
450 /**
451   Reads a 16-bit MMIO register.
452 
453   Reads the 16-bit MMIO register specified by Address. The 16-bit read value is
454   returned. This function must guarantee that all MMIO read and write
455   operations are serialized.
456 
457   If Address is not aligned on a 16-bit boundary, then ASSERT().
458 
459   If 16-bit MMIO register operations are not supported, then ASSERT().
460 
461   @param  Address The MMIO register to read.
462 
463   @return The value read.
464 
465 **/
466 UINT16
467 EFIAPI
MmioRead16(IN UINTN Address)468 MmioRead16 (
469   IN      UINTN                     Address
470   )
471 {
472   //
473   // Make sure Address is aligned on a 16-bit boundary.
474   //
475   ASSERT ((Address & 1) == 0);
476   return (UINT16)MmioReadWorker (Address, EfiCpuIoWidthUint16);
477 }
478 
479 /**
480   Writes a 16-bit MMIO register.
481 
482   Writes the 16-bit MMIO register specified by Address with the value specified
483   by Value and returns Value. This function must guarantee that all MMIO read
484   and write operations are serialized.
485 
486   If Address is not aligned on a 16-bit boundary, then ASSERT().
487 
488   If 16-bit MMIO register operations are not supported, then ASSERT().
489 
490   @param  Address The MMIO register to write.
491   @param  Value   The value to write to the MMIO register.
492 
493 **/
494 UINT16
495 EFIAPI
MmioWrite16(IN UINTN Address,IN UINT16 Value)496 MmioWrite16 (
497   IN      UINTN                     Address,
498   IN      UINT16                    Value
499   )
500 {
501   //
502   // Make sure Address is aligned on a 16-bit boundary.
503   //
504   ASSERT ((Address & 1) == 0);
505   return (UINT16)MmioWriteWorker (Address, EfiCpuIoWidthUint16, Value);
506 }
507 
508 /**
509   Reads a 32-bit MMIO register.
510 
511   Reads the 32-bit MMIO register specified by Address. The 32-bit read value is
512   returned. This function must guarantee that all MMIO read and write
513   operations are serialized.
514 
515   If Address is not aligned on a 32-bit boundary, then ASSERT().
516 
517   If 32-bit MMIO register operations are not supported, then ASSERT().
518 
519   @param  Address The MMIO register to read.
520 
521   @return The value read.
522 
523 **/
524 UINT32
525 EFIAPI
MmioRead32(IN UINTN Address)526 MmioRead32 (
527   IN      UINTN                     Address
528   )
529 {
530   //
531   // Make sure Address is aligned on a 32-bit boundary.
532   //
533   ASSERT ((Address & 3) == 0);
534   return (UINT32)MmioReadWorker (Address, EfiCpuIoWidthUint32);
535 }
536 
537 /**
538   Writes a 32-bit MMIO register.
539 
540   Writes the 32-bit MMIO register specified by Address with the value specified
541   by Value and returns Value. This function must guarantee that all MMIO read
542   and write operations are serialized.
543 
544   If Address is not aligned on a 32-bit boundary, then ASSERT().
545 
546   If 32-bit MMIO register operations are not supported, then ASSERT().
547 
548   @param  Address The MMIO register to write.
549   @param  Value   The value to write to the MMIO register.
550 
551 **/
552 UINT32
553 EFIAPI
MmioWrite32(IN UINTN Address,IN UINT32 Value)554 MmioWrite32 (
555   IN      UINTN                     Address,
556   IN      UINT32                    Value
557   )
558 {
559   //
560   // Make sure Address is aligned on a 32-bit boundary.
561   //
562   ASSERT ((Address & 3) == 0);
563   return (UINT32)MmioWriteWorker (Address, EfiCpuIoWidthUint32, Value);
564 }
565 
566 /**
567   Reads a 64-bit MMIO register.
568 
569   Reads the 64-bit MMIO register specified by Address. The 64-bit read value is
570   returned. This function must guarantee that all MMIO read and write
571   operations are serialized.
572 
573   If Address is not aligned on a 64-bit boundary, then ASSERT().
574 
575   If 64-bit MMIO register operations are not supported, then ASSERT().
576 
577   @param  Address The MMIO register to read.
578 
579   @return The value read.
580 
581 **/
582 UINT64
583 EFIAPI
MmioRead64(IN UINTN Address)584 MmioRead64 (
585   IN      UINTN                     Address
586   )
587 {
588   //
589   // Make sure Address is aligned on a 64-bit boundary.
590   //
591   ASSERT ((Address & 7) == 0);
592   return (UINT64)MmioReadWorker (Address, EfiCpuIoWidthUint64);
593 }
594 
595 /**
596   Writes a 64-bit MMIO register.
597 
598   Writes the 64-bit MMIO register specified by Address with the value specified
599   by Value and returns Value. This function must guarantee that all MMIO read
600   and write operations are serialized.
601 
602   If Address is not aligned on a 64-bit boundary, then ASSERT().
603 
604   If 64-bit MMIO register operations are not supported, then ASSERT().
605 
606   @param  Address The MMIO register to write.
607   @param  Value   The value to write to the MMIO register.
608 
609 **/
610 UINT64
611 EFIAPI
MmioWrite64(IN UINTN Address,IN UINT64 Value)612 MmioWrite64 (
613   IN      UINTN                     Address,
614   IN      UINT64                    Value
615   )
616 {
617   //
618   // Make sure Address is aligned on a 64-bit boundary.
619   //
620   ASSERT ((Address & 7) == 0);
621   return (UINT64)MmioWriteWorker (Address, EfiCpuIoWidthUint64, Value);
622 }
623