Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / qemu-palcode / console.c
diff --git a/qemu/roms/qemu-palcode/console.c b/qemu/roms/qemu-palcode/console.c
new file mode 100644 (file)
index 0000000..382cf54
--- /dev/null
@@ -0,0 +1,145 @@
+/* The SRM console prompt.
+
+   Copyright (C) 2011 Richard Henderson
+
+   This file is part of QEMU PALcode.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the text
+   of the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "protos.h"
+#include "console.h"
+#include "vgatables.h"
+
+
+static void
+output_crnl(void)
+{
+  crb_puts(0, "\r\n", 2);
+}
+
+static void
+output_bell(void)
+{
+  crb_puts(0, "\a", 1);
+}
+
+static void
+backspace_and_erase(void)
+{
+  crb_puts(0, "\b \b", 3);
+}
+
+static unsigned long
+getline(char *buf, unsigned long bufsize)
+{
+  unsigned long len = 0;
+  long c;
+
+  while (1)
+    {
+      c = crb_getc(0);
+      if (c < 0)
+       continue;
+      switch ((int)c)
+       {
+       case '\r':
+       case '\n':
+         output_crnl();
+         buf[len] = 0;
+         return len;
+
+        case '\b':
+       case 0x7f: /* Delete */
+          if (len > 0)
+           {
+             backspace_and_erase();
+              len--;
+            }
+         else
+           output_bell();
+          break;
+
+        default:
+         if (len + 1 < bufsize)
+           {
+             buf[len] = c;
+              crb_puts(0, buf+len, 1);
+             len++;
+           }
+         else
+           output_bell();
+         break;
+        }
+    }
+}
+
+static inline void set_console_alarm(void)
+{
+  /* Just set a new timeout for 10ms = 10M ns.  */
+  set_alarm_rel(10 * 1000 * 1000);
+}
+
+void
+do_entInt(unsigned long type, unsigned long vector)
+{
+  switch (type)
+    {
+    case 0:
+      /* ??? SMP interrupt.  We're going to need this for starting up
+         secondary cpus.  */
+      break;
+    case 1:
+      /* Timer interrupt.  */
+      set_console_alarm();
+      break;
+    case 2:
+      /* ??? Device interrupt.  We're going to need this for virtio disk
+         operations at minimum.  */
+      break;
+    }
+}
+
+void
+do_console(void)
+{
+  char line[256];
+  unsigned long len;
+
+  wrkgp();
+  wrent(entInt, 0);
+  set_console_alarm();
+  swpipl(0);
+
+  if (have_vga)
+  {
+    unsigned short *vga, attr;
+    vga = pci_mem_base + SEG_CTEXT *16;
+    attr = 0x2000;
+    vga[0] = 'H' + attr;
+    vga[1] = 'e' + attr;
+    vga[2] = 'l' + attr;
+    vga[3] = 'l' + attr;
+    vga[4] = 'o' + attr;
+  }
+
+  while (1)
+    {
+      crb_puts(0, ">>> ", 4);
+      len = getline(line, sizeof(line));
+      crb_puts(0, "got: ", 5);
+      crb_puts(0, line, len);
+      output_crnl();
+    }
+}