From 9a1b5d0ff2177f3ef4f15c66d6aaf04b2c76df4e Mon Sep 17 00:00:00 2001
From: Dor Laor <dor@cloudius-systems.com>
Date: Sun, 7 Apr 2013 11:42:31 +0300
Subject: [PATCH] Adding read line support to the console

Now our Isa serial device can read characters.
Using it by calling readln(char *msg, size_t len);
Note that the calls block until the len input chars or a newline.
---
 core/debug.cc            |  5 +++++
 drivers/console.cc       | 10 ++++++++++
 drivers/console.hh       |  2 ++
 drivers/debug-console.cc |  5 +++++
 drivers/debug-console.hh |  1 +
 drivers/isa-serial.cc    | 15 +++++++++++++++
 drivers/isa-serial.hh    |  8 ++++++++
 include/debug.hh         |  3 +++
 8 files changed, 49 insertions(+)

diff --git a/core/debug.cc b/core/debug.cc
index e01c5cf19..136345b4d 100644
--- a/core/debug.cc
+++ b/core/debug.cc
@@ -153,6 +153,11 @@ extern "C" {
         console::write(msg, strlen(msg), true);
     }
 
+    void readln(char *msg, size_t size)
+    {
+        console::read(msg, size);
+    }
+
     void debug_write(const char *msg, size_t len)
     {
         console::write(msg, len, false);
diff --git a/drivers/console.cc b/drivers/console.cc
index e4bc08526..69934611b 100755
--- a/drivers/console.cc
+++ b/drivers/console.cc
@@ -18,6 +18,16 @@ void write(const char *msg, size_t len, bool lf)
         console.newline();
 }
 
+void read(char *msg, size_t len)
+{
+    for (size_t i = 0; i < len; i++) {
+        msg[i] = console.readch();
+        write(&msg[i],1,false);
+        if (msg[i] == '\r')
+            break;
+    }
+}
+
 }
 
 static int
diff --git a/drivers/console.hh b/drivers/console.hh
index 6c338a4ae..bb8f9d698 100644
--- a/drivers/console.hh
+++ b/drivers/console.hh
@@ -7,12 +7,14 @@ class Console {
 public:
     virtual ~Console() {}
     virtual void write(const char *str, size_t len) = 0;
+    virtual char readch() = 0;
     virtual void newline() = 0;
 };
 
 namespace console {
 
 void write(const char *msg, size_t len, bool lf);
+void read(char *msg, size_t len);
 
 }
 
diff --git a/drivers/debug-console.cc b/drivers/debug-console.cc
index 523fc6b82..e1647f54d 100644
--- a/drivers/debug-console.cc
+++ b/drivers/debug-console.cc
@@ -14,3 +14,8 @@ void debug_console::newline()
 {
     with_lock(_lock, [=] { _impl.newline(); });
 }
+
+char debug_console::readch()
+{
+    return with_lock(_lock, [=] { return _impl.readch(); });
+ }
diff --git a/drivers/debug-console.hh b/drivers/debug-console.hh
index be87481de..97be35a2a 100644
--- a/drivers/debug-console.hh
+++ b/drivers/debug-console.hh
@@ -12,6 +12,7 @@ public:
     explicit debug_console(Console& impl);
     virtual void write(const char *str, size_t len);
     virtual void newline();
+    virtual char readch();
 private:
     Console& _impl;
     spinlock _lock;
diff --git a/drivers/isa-serial.cc b/drivers/isa-serial.cc
index 7777f47ad..fcec8a124 100644
--- a/drivers/isa-serial.cc
+++ b/drivers/isa-serial.cc
@@ -1,4 +1,5 @@
 #include "isa-serial.hh"
+#include <string.h>
 
 IsaSerialConsole::IsaSerialConsole() {
 	reset();
@@ -12,6 +13,20 @@ void IsaSerialConsole::write(const char *str, size_t len)
     }
 }
 
+char IsaSerialConsole::readch()
+{
+    u8 lsr;
+    char letter;
+
+    do {
+        lsr = pci::inb(ioport + LSR_ADDRESS);
+    } while (!(lsr & (LSR_RECEIVE_DATA_READY | LSR_OVERRUN | LSR_PARITY_ERROR | LSR_FRAME_ERROR)));
+
+    letter = pci::inb(ioport);
+
+    return letter;
+}
+
 void IsaSerialConsole::writeByte(const char letter)
 {
 	u8 lsr;
diff --git a/drivers/isa-serial.hh b/drivers/isa-serial.hh
index c9e8b0021..5160aea99 100644
--- a/drivers/isa-serial.hh
+++ b/drivers/isa-serial.hh
@@ -10,6 +10,7 @@ public:
 	IsaSerialConsole();
     virtual void write(const char *str, size_t len);
     virtual void newline();
+    virtual char readch();
 private:
     static const u16 ioport = 0x3f8;
     u8 lcr;
@@ -21,7 +22,14 @@ private:
         BAUD_GEN0_ADDRESS = 0x0,
         BAUD_GEN1_ADDRESS = 0x1,
         LSR_ADDRESS = 0x5,
+        LSR_RECEIVE_DATA_READY = 0x1,
+        LSR_OVERRUN = 0x2,
+        LSR_PARITY_ERROR = 0x4,
+        LSR_FRAME_ERROR = 0x8,
+        LSR_BREAK_INTERRUPT = 0x10,
         LSR_TRANSMIT_HOLD_EMPTY = 0x20,
+        LSR_TRANSMIT_EMPTY = 0x40,
+        LSR_FIFO_ERROR = 0x80,
     };
 
     void reset();
diff --git a/include/debug.hh b/include/debug.hh
index 14bed4715..ac0a78088 100644
--- a/include/debug.hh
+++ b/include/debug.hh
@@ -55,4 +55,7 @@ extern "C" {void debug(const char *msg); }
 void debug(const boost::format& fmt, bool lf=true);
 void debug(std::string str, bool lf=true);
 
+extern "C" {void readln(char *msg, size_t size); }
+
+
 #endif // DEBUG_H
-- 
GitLab