Doxygenation
[people/xl0/gpxe.git] / src / core / console.c
1 #include "stddef.h"
2 #include "console.h"
3
4 /** @file */
5
6 #include "bios.h"
7
8 static struct console_driver console_drivers[0] __table_start ( console );
9 static struct console_driver console_drivers_end[0] __table_end ( console );
10
11 /**
12  * Write a single character to each console device.
13  *
14  * @v character         Character to be written
15  * @ret None
16  * @err None
17  *
18  * The character is written out to all enabled console devices, using
19  * each device's console_driver::putchar() method.
20  *
21  */
22 void putchar ( int character ) {
23         struct console_driver *console;
24
25         /* Automatic LF -> CR,LF translation */
26         if ( character == '\n' )
27                 putchar ( '\r' );
28
29         for ( console = console_drivers; console < console_drivers_end ;
30               console++ ) {
31                 if ( ( ! console->disabled ) && console->putchar )
32                         console->putchar ( character );
33         }
34 }
35
36 /**
37  * Check to see if any input is available on any console.
38  *
39  * @v None
40  * @ret console         Console device that has input available, if any.
41  * @ret NULL            No console device has input available.
42  * @err None
43  *
44  * All enabled console devices are checked once for available input
45  * using each device's console_driver::iskey() method.  The first
46  * console device that has available input will be returned, if any.
47  *
48  */
49 static struct console_driver * has_input ( void ) {
50         struct console_driver *console;
51
52         for ( console = console_drivers; console < console_drivers_end ;
53               console++ ) {
54                 if ( ( ! console->disabled ) && console->iskey ) {
55                         if ( console->iskey () )
56                                 return console;
57                 }
58         }
59         return NULL;
60 }
61
62 /**
63  * Read a single character from any console.
64  *
65  * @v None
66  * @ret character       Character read from a console.
67  * @err None
68  *
69  * A character will be read from the first enabled console device that
70  * has input available using that console's console_driver::getchar()
71  * method.  If no console has input available to be read, this method
72  * will block.  To perform a non-blocking read, use something like
73  *
74  * @code
75  *
76  *   int key = iskey() ? getchar() : -1;
77  *
78  * @endcode
79  *
80  * The character read will not be echoed back to any console.
81  *
82  * @bug We need a cleaner way to pick up cpu_nap().  It makes a
83  * real-mode call, and so we don't want to use it with LinuxBIOS.
84  *
85  */
86 int getchar ( void ) {
87         struct console_driver *console;
88         int character = 256;
89
90         while ( character == 256 ) {
91                 /* Doze for a while (until the next interrupt).  This works
92                  * fine, because the keyboard is interrupt-driven, and the
93                  * timer interrupt (approx. every 50msec) takes care of the
94                  * serial port, which is read by polling.  This reduces the
95                  * power dissipation of a modern CPU considerably, and also
96                  * makes Etherboot waiting for user interaction waste a lot
97                  * less CPU time in a VMware session.
98                  */
99                 cpu_nap();
100                 
101                 console = has_input();
102                 if ( console && console->getchar )
103                         character = console->getchar ();
104         }
105
106         /* CR -> LF translation */
107         if ( character == '\r' )
108                 character = '\n';
109
110         return character;
111 }
112
113 /** Check for available input on any console.
114  *
115  * @v None
116  * @ret True            Input is available on a console
117  * @ret False           Input is not available on any console
118  * @err None
119  *
120  * All enabled console devices are checked once for available input
121  * using each device's console_driver::iskey() method.  If any console
122  * device has input available, this call will return True.  If this
123  * call returns True, you can then safely call getchar() without
124  * blocking.
125  *
126  */
127 int iskey ( void ) {
128         return has_input() ? 1 : 0;
129 }