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