summaryrefslogtreecommitdiff
path: root/gpxe/src/core/console.c
diff options
context:
space:
mode:
Diffstat (limited to 'gpxe/src/core/console.c')
-rw-r--r--gpxe/src/core/console.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/gpxe/src/core/console.c b/gpxe/src/core/console.c
new file mode 100644
index 00000000..6f55d558
--- /dev/null
+++ b/gpxe/src/core/console.c
@@ -0,0 +1,137 @@
+#include "stddef.h"
+#include "console.h"
+#include <gpxe/process.h>
+
+/** @file */
+
+#include "bios.h"
+
+static struct console_driver console_drivers[0]
+ __table_start ( struct console_driver, console );
+static struct console_driver console_drivers_end[0]
+ __table_end ( struct console_driver, console );
+
+/**
+ * Write a single character to each console device.
+ *
+ * @v character Character to be written
+ * @ret None -
+ * @err None -
+ *
+ * The character is written out to all enabled console devices, using
+ * each device's console_driver::putchar() method.
+ *
+ */
+void putchar ( int character ) {
+ struct console_driver *console;
+
+ /* Automatic LF -> CR,LF translation */
+ if ( character == '\n' )
+ putchar ( '\r' );
+
+ for ( console = console_drivers; console < console_drivers_end ;
+ console++ ) {
+ if ( ( ! console->disabled ) && console->putchar )
+ console->putchar ( character );
+ }
+}
+
+/**
+ * Check to see if any input is available on any console.
+ *
+ * @v None -
+ * @ret console Console device that has input available, if any.
+ * @ret NULL No console device has input available.
+ * @err None -
+ *
+ * All enabled console devices are checked once for available input
+ * using each device's console_driver::iskey() method. The first
+ * console device that has available input will be returned, if any.
+ *
+ */
+static struct console_driver * has_input ( void ) {
+ struct console_driver *console;
+
+ for ( console = console_drivers; console < console_drivers_end ;
+ console++ ) {
+ if ( ( ! console->disabled ) && console->iskey ) {
+ if ( console->iskey () )
+ return console;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Read a single character from any console.
+ *
+ * @v None -
+ * @ret character Character read from a console.
+ * @err None -
+ *
+ * A character will be read from the first enabled console device that
+ * has input available using that console's console_driver::getchar()
+ * method. If no console has input available to be read, this method
+ * will block. To perform a non-blocking read, use something like
+ *
+ * @code
+ *
+ * int key = iskey() ? getchar() : -1;
+ *
+ * @endcode
+ *
+ * The character read will not be echoed back to any console.
+ *
+ * @bug We need a cleaner way to pick up cpu_nap(). It makes a
+ * real-mode call, and so we don't want to use it with LinuxBIOS.
+ *
+ */
+int getchar ( void ) {
+ struct console_driver *console;
+ int character = 256;
+
+ while ( character == 256 ) {
+ /* Doze for a while (until the next interrupt). This works
+ * fine, because the keyboard is interrupt-driven, and the
+ * timer interrupt (approx. every 50msec) takes care of the
+ * serial port, which is read by polling. This reduces the
+ * power dissipation of a modern CPU considerably, and also
+ * makes Etherboot waiting for user interaction waste a lot
+ * less CPU time in a VMware session.
+ */
+ cpu_nap();
+
+ /* Keep processing background tasks while we wait for
+ * input.
+ */
+ step();
+
+ console = has_input();
+ if ( console && console->getchar )
+ character = console->getchar ();
+ }
+
+ /* CR -> LF translation */
+ if ( character == '\r' )
+ character = '\n';
+
+ return character;
+}
+
+/** Check for available input on any console.
+ *
+ * @v None -
+ * @ret True Input is available on a console
+ * @ret False Input is not available on any console
+ * @err None -
+ *
+ * All enabled console devices are checked once for available input
+ * using each device's console_driver::iskey() method. If any console
+ * device has input available, this call will return True. If this
+ * call returns True, you can then safely call getchar() without
+ * blocking.
+ *
+ */
+int iskey ( void ) {
+ return has_input() ? 1 : 0;
+}