]> Joshua Wise's Git repositories - netwatch.git/commitdiff
First pass of 410watch UI code. 410watch
authorJoshua Wise <joshua@escape.wv.cc.cmu.edu>
Sat, 10 Oct 2009 08:36:53 +0000 (04:36 -0400)
committerJoshua Wise <joshua@escape.wv.cc.cmu.edu>
Sat, 10 Oct 2009 08:36:53 +0000 (04:36 -0400)
cs410/cs410.c [new file with mode: 0644]
cs410/keyb.c [new file with mode: 0644]
cs410/keyhelp.c [new file with mode: 0644]
cs410/keyhelp.h [new file with mode: 0644]
netwatch/Makefile
netwatch/firstrun.c
netwatch/smi.c

diff --git a/cs410/cs410.c b/cs410/cs410.c
new file mode 100644 (file)
index 0000000..6cc1763
--- /dev/null
@@ -0,0 +1,199 @@
+/* cs410.c
+ * Entry points for 15-410 extensions
+ * NetWatch system management mode administration console
+ *
+ * Copyright (c) 2008 Jacob Potter and Joshua Wise.  All rights reserved.
+ * This program is free software; you can redistribute and/or modify it under
+ * the terms found in the file LICENSE in the root of this source tree.
+ *
+ */
+
+#include <io.h>
+#include <smi.h>
+#include <smram.h>
+#include <video_defines.h>
+#include <output.h>
+#include <minilib.h>
+
+#define CONSCOLOR 0x1F
+
+unsigned char oldcons[80 * 25 * 2];
+
+static unsigned char vga_read(unsigned char idx)
+{
+       outb(CRTC_IDX_REG, idx);
+       return inb(CRTC_DATA_REG);
+}
+
+static char * vga_base()
+{
+       return (char *) (
+               0xB8000
+               + (((unsigned int) vga_read(CRTC_START_ADDR_MSB_IDX)) << 9)
+               + (((unsigned int) vga_read(CRTC_START_ADDR_LSB_IDX)) << 1)
+       );
+}
+
+static void grey_console()
+{
+       int i;
+       char *p = vga_base();
+       
+       for (i = 0; i < 80*25; i++, p+=2)
+               p[1] &= ~0xF8;  /* Clear the background and any brightness. */
+}
+
+#define CHAR(x, y) (base[((y)*80+(x))*2])
+#define COLOR(x, y) (base[((y)*80+(x))*2+1])
+
+static void ui_frame(int xp, int yp, int xs, int ys, char *title)
+{
+       int x, y;
+       char *base = vga_base();
+       
+       /* Blank and fill the region. */
+       for (y = yp; y <= (yp + ys); y++)
+               for (x = xp; x <= (xp + xs); x++)
+               {
+                       CHAR(x, y) = ' ';
+                       COLOR(x, y) = CONSCOLOR;
+               }
+
+       /* Draw the top and the bottom (and the bar if need be). */     
+       for (x = xp; x <= (xp + xs); x++)
+       {
+               CHAR(x, yp) = 0xCD /* double line horizontal */;
+               CHAR(x, yp+ys) = 0xCD /* double line horizontal */;
+               if (title)
+                       CHAR(x, yp+2) = 0xC4 /* single line horizontal */;
+       }
+       
+       /* Draw the left and right. */
+       for (y = yp; y <= (yp + ys); y++)
+       {
+               CHAR(xp, y) = 0xBA /* double line vertical */;
+               CHAR(xp+xs, y) = 0xBA /* double line vertical */;
+       }
+       
+       /* Drop in the corners. */
+       CHAR(xp, yp) = 0xC9;
+       CHAR(xp+xs, yp) = 0xBB;
+       CHAR(xp, yp+ys) = 0xC8;
+       CHAR(xp+xs, yp+ys) = 0xBC;
+       if (title)
+       {
+               CHAR(xp, yp+2) = 0xC7;
+               CHAR(xp+xs, yp+2) = 0xB6;
+       }
+       
+       /* Drop in the text. */
+       if (title)
+               for (x = (xs - strlen(title)) / 2 + xp; *title; x++, title++)
+                       CHAR(x, yp+1) = *title;
+}
+
+static void ui_label(int xp, int yp, char *s)
+{
+       int x;
+       char *base = vga_base();
+       
+       for (x = xp; *s; x++, s++)
+               CHAR(x, yp) = *s;
+}
+
+typedef enum ui_element_type {
+       UI_FRAME = 0,
+       UI_LABEL = 1,
+       UI_END = -1
+} ui_element_type_t;
+
+typedef union ui_element {
+       ui_element_type_t type;
+       struct {
+               ui_element_type_t type;
+               int xp, yp;
+               int xs, ys;
+               char *title;
+       } frame;
+       struct {
+               ui_element_type_t type;
+               int xp, yp;
+               char *text;
+       } label;
+} ui_element_t;
+
+static ui_element_t mainmenu[] = {
+       { .frame = {
+               .type = UI_FRAME,
+               .xp = 10, .yp = 5,
+               .xs = 60, .ys = 15,
+               .title = "NetWatch main menu" } },
+       { .label = {
+               .type = UI_LABEL,
+               .xp = 12, .yp = 8,
+               .text = "Options:" } },
+       { .label = {
+               .type = UI_LABEL,
+               .xp = 12, .yp = 10,
+               .text = "q - Return to system" } },
+       { .type = UI_END }
+};
+
+static void ui_render(ui_element_t *ui)
+{
+       for (; ui->type != UI_END; ui++)
+               switch (ui->type)
+               {
+               case UI_FRAME:
+                       ui_frame(ui->frame.xp, ui->frame.yp,
+                                ui->frame.xs, ui->frame.ys,
+                                ui->frame.title);
+                       break;
+               case UI_LABEL:
+                       ui_label(ui->label.xp, ui->label.yp,
+                                ui->label.text);
+                       break;
+               case UI_END:
+               default:
+                       return; /* ??? */
+               }
+}
+
+void cs410_pwrbtn_handler(smi_event_t ev)
+{
+       smram_state_t old_state;
+       
+       outputf("410watch: Power button event");
+       
+       /* Save off the console. */
+       old_state = smram_save_state();
+       smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
+       memcpy(oldcons, vga_base(), 80*25*2);
+       
+       /* Pull a Simics, and grey out the console -- why not? */
+       grey_console();
+       
+       /* Show the main menu. */
+       ui_render(mainmenu);
+       
+       /* Allow access to data in ASEG. */
+       smram_restore_state(old_state);
+       
+       /* Now just sit for a while to show off our newly greyed console. */
+       char c;
+       char *p = vga_base() + (11*80+12)*2;
+       extern int getchar();
+       while ((c = getchar()) != 'q')
+       {
+               smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
+               *p = c;
+               p += 2;
+               smram_restore_state(old_state);
+       }
+       
+       /* Put the console back. */
+       smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
+       memcpy(vga_base(), oldcons, 80*25*2);
+       smram_restore_state(old_state);
+
+}
diff --git a/cs410/keyb.c b/cs410/keyb.c
new file mode 100644 (file)
index 0000000..8fd4c98
--- /dev/null
@@ -0,0 +1,39 @@
+#include <io.h>
+#include "keyhelp.h"
+#include "../net/net.h"
+#include <output.h>
+
+/* Takes over the i8042... oh well.  If we ever fully emulate the i8042,
+ * then we'll patch into that.
+ */
+
+#define KEYBOARD_PORT 0x60
+#define KEYB_STATUS_PORT 0x64
+#define KEYB_OBF 0x1
+
+int getchar()
+{
+       kh_type key;
+       unsigned char scancode;
+       
+       /* Ignore accesses -- XXX hack */
+       outl(0x840, 0x0);
+       outl(0x848, 0x0);
+       
+       do
+       {
+               while (!(inb(KEYB_STATUS_PORT) & KEYB_OBF))
+                       eth_poll();
+               
+               scancode = inb(KEYBOARD_PORT);
+               outputf("scancode: %02x", scancode);
+               key = process_scancode(scancode);
+       } while (!KH_HASDATA(key) || !KH_ISMAKE(key));
+       
+       /* XXX */
+       outl(0x840, 0x0);
+       outl(0x844, 0x1000);
+       outl(0x848, 0x1000);
+       
+       return KH_GETCHAR(key);
+}
diff --git a/cs410/keyhelp.c b/cs410/keyhelp.c
new file mode 100644 (file)
index 0000000..98748de
--- /dev/null
@@ -0,0 +1,655 @@
+/**
+ * The 15-410 reference kernel keyboard handling code.
+ *
+ * @author Steve Muckle <smuckle@andrew.cmu.edu>
+ *
+ * @author Edited by zra for the 2003-2004 season.
+ *
+ * @author Edited by mpa for spring 2004
+ *
+ * @author Rewritten by nwf for spring 2007.
+ *
+ * Functions for turning keyboard scancodes
+ * into chars.
+ *
+ * Notice that we use Scancode Set 1
+ */
+/*@{*/
+
+#include "keyhelp.h"
+
+/**
+ * This is returned as the upper bits of the result of
+ * process_scancode and may be interrogated more readily by
+ * the KH_ macros in keyhelp.h
+ *
+ * WARNING:
+ * The bottom bits overlap with the KH_RESULT_ codes in the
+ * return value.
+ */
+static short key_state = 0;
+
+  /** Currently processing a PRINT SCREEN BREAK sequence */
+#define KH_PRSCR_UP_SCAN    0x0008
+  /** Currently processing a PRINT SCREEN MAKE sequence */
+#define KH_PRSCR_DOWN_SCAN  0x0004
+  /** Currently processing a PAUSE/BREAK (MAKE) sequence */
+#define KH_PAUSE_SCAN       0x0002
+  /** Currently processing an extended sequence (E0 prefix) */
+#define KH_EXTENDED_SCAN    0x0001
+static short key_internal_state = 0;
+
+static int key_sequence = 0;
+
+#define KHS_SHIFT_CORE (key_state & (KH_LSHIFT_KEY | KH_RSHIFT_KEY)) 
+#define KHS_CTL_CORE (key_state & (KH_LCONTROL_KEY | KH_RCONTROL_KEY)) 
+
+#define KHS_SHIFT(c,r,s,u) \
+  { c = KHS_SHIFT_CORE ? s : u; r = u; }
+#define KHS_SHIFTCTL(c,r,cc,s,u) \
+  { c = KHS_CTL_CORE ? cc : (KHS_SHIFT_CORE ? s : u); r = u; }
+#define KHS_SHIFTCAPSCTL(c,r,cc,s,u) \
+  { c = KHS_CTL_CORE ? cc : (((KHS_SHIFT_CORE || (key_state & KH_CAPS_LOCK)) && \
+    !(KHS_SHIFT_CORE && (key_state & KH_CAPS_LOCK))) ? s : u) ; r = u; }
+
+/**
+ * This function performs the mapping
+ * from simple scancodes to chars.
+ *
+ * @param scancode a simple scancode.
+ * @param pressed 0 if released, nonzero if pressed.
+ *
+ * @return A partially constructed kh_type.
+ */
+static kh_type
+process_simple_scan(int scancode, int pressed)
+{
+  unsigned char code = 0x80;
+  unsigned char rcode = 0x80;
+  kh_type res = 0;
+
+  switch(scancode & 0x7F)
+  {
+  case 0x1:
+    /* Escape key. */
+    rcode = code = 0x1B;
+    break;
+  case 0x2:
+    /* 1 or ! */
+    KHS_SHIFT(code, rcode, '!', '1');
+    break;
+  case 0x3:
+    /* 2 or @ */
+    KHS_SHIFTCTL(code, rcode, 0x00, '@', '2');
+    break;
+  case 0x4:
+    /* 3 or # */
+    KHS_SHIFT(code, rcode, '#', '3');
+    break;
+  case 0x5:
+    /* 4 or $ */
+    KHS_SHIFT(code, rcode, '$', '4');
+    break;
+  case 0x6:
+    /* 5 or % */
+    KHS_SHIFT(code, rcode, '%', '5');
+    break;
+  case 0x7:
+    /* 6 or ^ */
+    KHS_SHIFTCTL(code, rcode, 0x1E, '^', '6');
+    break;
+  case 0x8:
+    /* 7 or & */
+    KHS_SHIFT(code, rcode, '&', '7');
+    break;
+  case 0x9:
+    /* 8 or * */
+    KHS_SHIFT(code, rcode, '*', '8');
+    break;
+  case 0xA:
+    /* 9 or ( */
+    KHS_SHIFT(code, rcode, '(', '9');
+    break;
+  case 0xB:
+    /* 0 or ) */
+    KHS_SHIFT(code, rcode, ')', '0');
+    break;
+  case 0xC:
+    /* - or _ */
+    KHS_SHIFTCTL(code, rcode, 0x1F, '_', '-');
+    break;
+  case 0xD:
+    /* = or + */
+    KHS_SHIFT(code, rcode, '+', '=');
+    break;
+  case 0xE:
+    /* Backspace key. */
+    rcode = code = '\b';
+    break;
+  case 0xF:
+    /* Tab key. */
+    rcode = code = '\t';
+    break;
+  case 0x10:
+    /* q or Q. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x11, 'Q', 'q');
+    break;
+  case 0x11:
+    /* w or W. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x17, 'W', 'w');
+    break;
+  case 0x12:
+    /* e or E. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x05, 'E', 'e');
+    break;
+  case 0x13:
+    /* r or R. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x12, 'R', 'r');
+    break;
+  case 0x14:
+    /* t or T. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x14, 'T', 't');
+    break;
+  case 0x15:
+    /* y or Y. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x19, 'Y', 'y');
+    break;
+  case 0x16:
+    /* u or U. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x15, 'U', 'u');
+    break;
+  case 0x17:
+    /* i or I. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x09, 'I', 'i');
+    break;
+  case 0x18:
+    /* o or O. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x0F, 'O', 'o');
+    break;
+  case 0x19:
+    /* p or P. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x10, 'P', 'p');
+    break;
+  case 0x1A:
+    /* [ or {. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x1B, '{', '[');
+    break;
+  case 0x1B:
+    /* ] or }. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x1D, '}', ']');
+    break;
+  case 0x1C:
+    /* Enter key. */
+    rcode=code='\n';
+    break;
+  case 0x1D:
+    if((key_internal_state & KH_PAUSE_SCAN) && (key_sequence == 0))
+    {
+      /* Stage 1 of a pause sequence */
+      key_sequence++;
+      return 0;
+    } else {
+      key_internal_state &= ~KH_PAUSE_SCAN;
+      key_sequence = 0;
+    }
+    rcode=KHE_LCTL;
+    if(pressed)
+      key_state |= KH_LCONTROL_KEY;
+    else
+      key_state &= ~KH_LCONTROL_KEY;
+    break;
+  case 0x1E:
+    /* a or A. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x01, 'A', 'a');
+    break;
+  case 0x1F:
+    /* s or S. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x13, 'S', 's');
+    break;
+  case 0x20:
+    /* d or D. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x04, 'D', 'd');
+    break;
+  case 0x21:
+    /* f or F. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x06, 'F', 'f');
+    break;
+  case 0x22:
+    /* g or G. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x07, 'G', 'g');
+    break;
+  case 0x23:
+    /* h or H. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x08, 'H', 'h');
+    break;
+  case 0x24:
+    /* j or J. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x0A, 'J', 'j');
+    break;
+  case 0x25:
+    /* k or K. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x0B, 'K', 'k');
+    break;
+  case 0x26:
+    /* l or L. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x0C, 'L', 'l');
+    break;
+  case 0x27:
+    /* ; or :. */
+    KHS_SHIFT(code, rcode, ':', ';');
+    break;
+  case 0x28:
+    /* ' or " */
+    KHS_SHIFT(code, rcode, '\"', '\'');
+    break;
+  case 0x29:
+    KHS_SHIFT(code, rcode, '~', '`');
+    break;
+  case 0x2A:
+    rcode = KHE_LSHIFT;
+    if(pressed)
+      key_state |= KH_LSHIFT_KEY;
+    else
+      key_state &= ~KH_LSHIFT_KEY;
+    break;
+  case 0x2B:
+    /* \ or |. */
+    KHS_SHIFTCTL(code, rcode, 0x1C, '|', '\\');
+    break;
+  case 0x2C:
+    /* z or Z. */ 
+    KHS_SHIFTCAPSCTL(code, rcode, 0x1A, 'Z', 'z');
+    break;
+  case 0x2D:
+    /* x or X. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x18, 'X', 'x');
+    break;
+  case 0x2E:
+    /* c or C. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x03, 'C', 'c');
+    break;
+  case 0x2F:
+    /* v or V. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x16, 'V', 'v');
+    break;
+  case 0x30:
+    /* b or B. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x02, 'B', 'b');
+    break;
+  case 0x31:
+    /* n or N. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x0E, 'N', 'n');
+    break;
+  case 0x32:
+    /* m or M. */
+    KHS_SHIFTCAPSCTL(code, rcode, 0x0D, 'M', 'm');
+    break;
+  case 0x33:
+    /* , or <. */
+    KHS_SHIFT(code, rcode, '<', ',');
+    break;
+  case 0x34:
+    /* . or >. */
+    KHS_SHIFT(code, rcode, '>', '.');
+    break;
+  case 0x35:
+    /* / or ? */
+    KHS_SHIFT(code, rcode, '?', '/');
+    break;
+  case 0x36:
+    rcode = KHE_RSHIFT;
+    if(pressed)
+      key_state |= KH_RSHIFT_KEY;
+    else
+      key_state &= ~KH_RSHIFT_KEY;
+    break;
+  case 0x37:
+    /* NP * */
+    rcode = code = '*';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x38:
+    rcode = KHE_LALT;
+    if(pressed)
+      key_state |= KH_LALT_KEY;
+    else
+      key_state &= ~KH_LALT_KEY;
+    break;
+  case 0x39:
+    /* Space bar. */
+    rcode = code =' ';
+    break;
+  case 0x3A:
+    rcode = KHE_CAPSLOCK;
+    if(pressed)
+    {
+      if(key_state & KH_CAPS_LOCK)
+        key_state &= ~KH_CAPS_LOCK;
+      else
+        key_state |= KH_CAPS_LOCK;
+    }
+    break;
+  case 0x3B:
+    /* F1 key. */
+    rcode = code = KHE_F1;
+    break;
+  case 0x3C:
+    /* F2 key. */
+    rcode = code = KHE_F2;
+    break;
+  case 0x3D:
+    /* F3 key. */
+    rcode = code = KHE_F3;
+    break;
+  case 0x3E:
+    /* F4 key. */
+    rcode = code = KHE_F4;
+    break;
+  case 0x3F:
+    /* F5 key. */
+    rcode = code = KHE_F5;
+    break;
+  case 0x40:
+    /* F6 key. */
+    rcode = code = KHE_F6;
+    break;
+  case 0x41:
+    /* F7 key. */
+    rcode = code = KHE_F7;
+    break;
+  case 0x42:
+    /* F8 key. */
+    rcode = code = KHE_F8;
+    break;
+  case 0x43:
+    /* F9 key. */
+    rcode = code = KHE_F9;
+    break;
+  case 0x44:
+    /* F10 key. */
+    rcode = code = KHE_F10;
+    break;
+  case 0x45:
+    if((key_internal_state & KH_PAUSE_SCAN) && (key_sequence == 1))
+    {
+      /* Stage 2 of a pause sequence */
+      key_sequence++;
+      return 0;
+    } else {
+      key_internal_state &= ~KH_PAUSE_SCAN;
+      key_sequence = 0;
+    }
+    rcode = KHE_NUMLOCK;
+    if(pressed)
+    {
+      if(key_state & KH_NUM_LOCK)
+        key_state &= ~KH_NUM_LOCK;
+      else
+        key_state |= KH_NUM_LOCK;
+    }
+    break;
+  case 0x47:
+    rcode = code = '7';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x48:
+    rcode = code = '8';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x49:
+    rcode = code = '9';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x4A:
+    rcode = code = '-';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x4B:
+    rcode = code = '4';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x4C:
+    rcode = code = '5';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x4D:
+    rcode = code = '6';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x4E:
+    rcode = code = '+';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x4F:
+    rcode = code = '1';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x50:
+    rcode = code = '2';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x51:
+    rcode = code = '3';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x52:
+    rcode = code = '0';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x53:
+    rcode = code = '.';
+    res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+    break;
+  case 0x57:
+    /* F11 key. */
+    rcode = code = KHE_F11;
+    break;
+  case 0x58:
+    /* F12 key. */
+    rcode = code = KHE_F12;
+    break;
+  case 0xE1 & 0x7F:
+    if(!(key_internal_state & KH_PAUSE_SCAN))
+    {
+      /* Stage 0 of a pause sequence */
+      key_internal_state |= KH_PAUSE_SCAN;
+      key_sequence = 0;
+      return 0;
+    } else if ((key_internal_state & KH_PAUSE_SCAN) && (key_sequence == 2)) {
+      key_sequence++;
+      return 0;
+    } else {
+      key_internal_state &= ~KH_PAUSE_SCAN;
+      key_sequence = 0;
+    }
+    /* FALLTHROUGH */
+  default:
+    rcode = code = KHE_UNDEFINED;
+    break;
+  }
+
+  if ( rcode != KHE_UNDEFINED && code != KHE_UNDEFINED )
+    res |= (KH_RESULT_HASDATA << KH_RMODS_SHIFT);
+  else
+    code = 0x00;
+
+  return res | (code << KH_CHAR_SHIFT)
+            | (rcode << KH_RAWCHAR_SHIFT)
+            | (KH_RESULT_HASRAW << KH_RMODS_SHIFT);
+}
+
+/**
+ * Processes extended scan codes.  Notably, this includes
+ * the arrow keys as well as some of the more unusual keys
+ * on the keyboard.
+ *
+ * @param keypress the extended scancode.
+ * @param 0 if released. non-zero if pressed.
+ *
+ * @return A partially constructed kh_type.
+ */
+kh_type
+process_extended_scan(int keypress, int pressed)
+{
+  unsigned char code = 0x80;
+  unsigned char rcode = 0x80;
+  kh_type res = 0;
+
+  /* Intermediate states in multiple byte scancodes should return
+   * zero from this function, rather than returning a RESULT code.
+   */
+
+  switch(keypress & 0x7F)
+  {
+    case 0x1C:
+      /* NP '\n' */
+      rcode = code = '\n';
+      res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+      break;
+    case 0x1D:
+      /* Right control key */
+      rcode = KHE_RCTL;
+      if(pressed)
+        key_state |= KH_RCONTROL_KEY;
+      else
+        key_state &= ~KH_RCONTROL_KEY;
+      break;
+    case 0x2A:
+      /* Stage 0 of PRINT SCREEN MAKE and Stage 1 of PRINT SCREEN BREAK */
+      if(key_internal_state & KH_PRSCR_UP_SCAN)
+      {
+        rcode = code = KHE_PRINT_SCREEN;
+        key_internal_state &= ~KH_PRSCR_UP_SCAN;
+      } else if (!(key_internal_state & KH_PRSCR_UP_SCAN)) {
+        key_internal_state |= KH_PRSCR_DOWN_SCAN;
+        key_internal_state &= ~KH_EXTENDED_SCAN;
+        return 0;
+      } else {
+        rcode = code = KHE_UNDEFINED;
+      }
+      break;
+    case 0x35:
+      /* NP / */
+      rcode = code = '/';
+      res |= KH_RESULT_NUMPAD << KH_RMODS_SHIFT;
+      break;
+    case 0x37:
+      /* Stage 1 of PRINT SCREEN MAKE and Stage 0 of PRINT SCREEN BREAK */
+      if(key_internal_state & KH_PRSCR_DOWN_SCAN)
+      {
+        rcode = code = KHE_PRINT_SCREEN;
+        key_internal_state &= ~KH_PRSCR_DOWN_SCAN;
+      } else if (!(key_internal_state & KH_PRSCR_DOWN_SCAN)) {
+        key_internal_state |= KH_PRSCR_UP_SCAN;
+        key_internal_state &= ~KH_EXTENDED_SCAN;
+        return 0;
+      } else {
+        rcode = code = KHE_UNDEFINED;
+      }
+      break;
+    case 0x38:
+      /* Right alt key */
+      rcode = KHE_RALT;
+      if(pressed)
+        key_state |= KH_RALT_KEY;
+      else
+        key_state &= ~KH_RALT_KEY;
+      break;
+    case 0x48:
+      /* UP */
+      rcode = code=KHE_ARROW_UP;
+      break;
+    case 0x4b:
+      /* LEFT */
+      rcode = code=KHE_ARROW_LEFT;
+      break;
+    case 0x4d:
+      /* RIGHT */
+      rcode = code=KHE_ARROW_RIGHT;
+      break;
+    case 0x50:
+      /* DOWN */
+      rcode = code = KHE_ARROW_DOWN;
+      break;
+    case 0x53:
+      /* DEL */
+      rcode = code = 0x7F;
+      break;
+    default:
+      rcode = code = KHE_UNDEFINED;
+      break;
+  }
+
+  key_internal_state &= ~KH_EXTENDED_SCAN;
+
+  if ( rcode != KHE_UNDEFINED && code != KHE_UNDEFINED )
+    res |= (KH_RESULT_HASDATA << KH_RMODS_SHIFT);
+  else
+    code = 0x00;
+
+  return res | (code << KH_CHAR_SHIFT)
+            | (rcode << KH_RAWCHAR_SHIFT)
+            | (KH_RESULT_HASRAW << KH_RMODS_SHIFT);
+}
+
+  /** The entrypoint to the keyboard processing library.
+   *
+   * @param keypress A raw scancode as returned by the keyboard hardware.
+   * @return A kh_type indicating the keyboard modifier key states, result
+   *         modifier bits, and potentially ASCII/410 Upper Code Plane
+   *         translations.
+   */
+kh_type process_scancode(int keypress) {
+  kh_type res;
+  int pressed = !(keypress & 0x80);
+  int keycode = keypress & 0x7F;
+  
+  if (key_internal_state & KH_EXTENDED_SCAN)
+    res = process_extended_scan(keycode, pressed);
+  else
+  {
+    switch(keypress & 0xFF)
+    {
+      case 0x9D:
+        if ((key_internal_state & KH_PAUSE_SCAN) && (key_sequence == 3))
+        {
+          key_sequence++;
+          return 0;
+        } else {
+          key_internal_state &= ~KH_PAUSE_SCAN;
+          key_sequence = 0;
+        }
+        goto deflt;
+      case 0xC5:
+        if ((key_internal_state & KH_PAUSE_SCAN) && (key_sequence == 4))
+        {
+          key_internal_state &= ~KH_PAUSE_SCAN;
+          /* Pause sequence completed */
+          res = (KHE_PAUSE << KH_CHAR_SHIFT)
+                | (KHE_PAUSE << KH_RAWCHAR_SHIFT)
+                | (KH_RESULT_HASDATA << KH_RMODS_SHIFT);
+          break;
+        }
+        key_internal_state &= ~KH_PAUSE_SCAN;
+        key_sequence = 0;
+        goto deflt;
+      case 0xE0:
+        key_internal_state |= KH_EXTENDED_SCAN;
+        /* Return no result for this intermediate state */
+        return key_state << KH_STATE_SHIFT;
+      default:
+deflt:
+        key_internal_state &= ~(KH_PRSCR_UP_SCAN | KH_PRSCR_DOWN_SCAN);
+        res = process_simple_scan(keycode, pressed);
+    }
+  }
+
+  if(pressed)
+    res |= KH_RESULT_MAKE << KH_RMODS_SHIFT;
+
+  res |= (key_state & KH_STATE_SMASK) << KH_STATE_SHIFT;
+
+  return res;
+}
+
+/*@}*/
diff --git a/cs410/keyhelp.h b/cs410/keyhelp.h
new file mode 100644 (file)
index 0000000..4644b86
--- /dev/null
@@ -0,0 +1,210 @@
+#ifndef KEYHELP_H
+#define KEYHELP_H
+
+#define KEY_IDT_ENTRY 0x21
+#define KEYBOARD_PORT 0x60
+
+/** Return type of process_scancode.  Four bytes wide, which are broken down as
+ * follows:
+ *
+ * - The top two (most significant) bytes are a state field composed of the
+ *   KH_*_KEY, KH_*_LOCK, and KH_RESULT_* values below.
+ * - The third byte is defined as the "raw" result and gives a cannonical,
+ *   unshifted name for the key pressed, if KH_HASDATA() gives true
+ *   [KH_RESULT_HASDATA on].
+ * - The fourth (least significant byte) gives a "common" value of the result.
+ *   This is the representation subject to all modifier keys.
+ */
+typedef int kh_type;
+
+  /**@{ kh_type bitfield breakdown definitions */
+#define KH_STATE_SHIFT 16
+#define KH_STATE_SMASK 0x0FF00
+#define KH_RMODS_SHIFT 16
+#define KH_RMODS_SMASK 0x000F
+  /* Note that there are bits in neither of these MASKs; these are reserved for
+   * future expanson; see commentary below.
+   */
+#define KH_RAWCHAR_SHIFT 8
+#define KH_RAWCHAR_SMASK 0x0FF
+#define KH_CHAR_SHIFT 0
+#define KH_CHAR_SMASK 0x0FF
+  /**@}*/
+
+  /**@{ Utility macros for parsing the return of process_scancode() */
+  /** Extract STATE fields from return type */
+#define KH_STATE(k) ((k >> KH_STATE_SHIFT) & KH_STATE_SMASK)
+  /** Extract RMODS fields from return type */
+#define KH_RMODS(k) ((k >> KH_RMODS_SHIFT) & KH_RMODS_SMASK)
+  /** Extract RAWCHAR field from return type */
+#define KH_GETRAW(k) ((k >> KH_RAWCHAR_SHIFT) & KH_RAWCHAR_SMASK)
+  /** Extract CHARACTER field from return type */
+#define KH_GETCHAR(k) ((k >> KH_CHAR_SHIFT) & KH_CHAR_SMASK)
+
+  /** Return nonzero if the CapsLock is on in the status word k */
+#define KH_CAPSLOCK(k) (!!((k>>KH_STATE_SHIFT)&KH_CAPS_LOCK))
+  /** Return nonzero if either shift is down in the status word k */
+#define KH_SHIFT(k) (!!((k>>KH_STATE_SHIFT)&(KH_LSHIFT_KEY|KH_RSHIFT_KEY)))
+  /** Return nonzero if either ctl is down in the status word k */
+#define KH_CTL(k) (!!((k>>KH_STATE_SHIFT)&(KH_LCONTROL_KEY|KH_RCONTROL_KEY)))
+  /** Return nonzero if either alt is down in the status word k */
+#define KH_ALT(k) (!!((k>>KH_STATE_SHIFT)&(KH_LALT_KEY|KH_RALT_KEY)))
+
+  /** Return nonzero if the status word k contains a raw character value */
+#define KH_HASRAW(k) (!!((k>>KH_RMODS_SHIFT)&KH_RESULT_HASRAW))
+  /** Return nonzero if the status word k contains a character value */
+#define KH_HASDATA(k) (!!((k>>KH_RMODS_SHIFT)&KH_RESULT_HASDATA))
+  /** Return nonzero if the status word k results are from the Numeric Pad.
+   * @pre Valid only if KH_HASDATA(k) is nonzero. */
+#define KH_NUMPAD(k) (!!((k>>KH_RMODS_SHIFT)&KH_RESULT_NUMPAD))
+  /** Return nonzero if the status work k results from a key going down.
+   * @pre Valid only if KH_HASDATA(k) is nonzero. */
+#define KH_ISMAKE(k) (!!((k>>KH_RMODS_SHIFT)&KH_RESULT_MAKE))
+
+  /** Return nonzero if the status word k character is from the
+   * 410 Upper Code Plane.
+   *
+   * @pre Valid only if KH_HASDATA(k) is nonzero. */
+#define KH_ISEXTENDED(k) (!!(KH_GETCHAR(k)&0x80))
+
+  /** Return nonzero if the status word k raw result character is from
+   * the 410 Upper Code Plane.
+   *
+   * @pre Valid only if KH_HASDATA(k) is nonzero. */
+#define KH_ISRAWEXTENDED(k) (!!(KH_GETRAW(k)&0x80))
+  /**@}*/
+
+/**@{ key_state variables */
+  /** Left shift */
+#define KH_LSHIFT_KEY       0x8000
+  /** Right shift */
+#define KH_RSHIFT_KEY       0x4000
+  /** Left control */
+#define KH_LCONTROL_KEY     0x2000
+  /** Right control */
+#define KH_RCONTROL_KEY     0x1000
+  /** Left alt */
+#define KH_LALT_KEY         0x0800
+  /** Right alt */
+#define KH_RALT_KEY         0x0400
+  /** Caps lock */
+#define KH_CAPS_LOCK        0x0200
+  /** Num lock */
+#define KH_NUM_LOCK         0x0100
+/**@}*/
+
+  /* Reserved bits in range 0x00F0; these are currently NOT inside either of the
+   * MASKS above.
+   *
+   * @bug Currently the LGUI and RGUI modifiers are ignored.
+   * @bug Currently ScrollLock is not treated as a modifier.
+   */
+
+/**@{*/
+  /** Result contains a meaningful answer beyond the modifier bits.  If this
+   * bit is OFF in the returned word, the calling implementation SHOULD NOT
+   * make access to either the result or the raw result.
+   *
+   * (As a debugging hint, the current implementation should be returning zeros
+   * in those fields in this case.  If lots of zeros seem to be going to
+   * screen, check one's handling of this case!)
+   */
+#define KH_RESULT_HASRAW            0x08
+
+  /** Result contains a meaningful answer beyond the modifier bits and raw
+   * code.  That is to say that this contains a translated code that you
+   * probably care about.  
+   */
+#define KH_RESULT_HASDATA           0x04
+
+  /** Signals that the result is from the Numeric Pad.  This implementation
+   * will return ASCII values regardless of NumLock status, leaving to callers
+   * to do more meaningful things for the non-ASCII meanings. */
+#define KH_RESULT_NUMPAD           0x02
+
+  /** If KH_RESULT_HASDATA, this bit is asserted for MAKE events and clear for
+   * BREAK events.  Traditional parsing logic probably only wants to emit
+   * chars when KH_RESULT_MAKE is turned on.
+   */
+#define KH_RESULT_MAKE   0x01
+/**@}*/
+
+enum kh_extended_e {
+  /* Some control codes are returned within the ASCII encoding scheme, where
+   * the ASCII definition is sufficiently close to what we're after.
+   */
+  KHE_ESCAPE = 0x1B,
+  KHE_BACKSPACE = '\b',
+  KHE_TAB = '\t',
+  KHE_ENTER = '\n',
+
+  /*
+   * The remainder of ASCII, from 0x20 - 0x7F, is returned as ASCII.  But then
+   * we run out of mappings and, rather than inventing a mapping to the unused
+   * control characters, we invent our own upper code plane, which we'll call
+   * the 410 Upper Code Plane.
+   */
+
+  KHE_UNDEFINED = 0x80, /**< A non-ASCII character for which we don't have an
+                            escape sequence.  Traditional results would have
+                            been to return a '?' but this leaves the behavior
+                            to the implementation */
+
+  KHE_ARROW_UP,
+  KHE_ARROW_LEFT,
+  KHE_ARROW_DOWN,
+  KHE_ARROW_RIGHT,
+
+  /* Modifiers */
+  KHE_LALT,
+  KHE_RALT,
+  KHE_LCTL,
+  KHE_RCTL,
+  KHE_LSHIFT,
+  KHE_RSHIFT,
+  /* KHE_LGUI, */
+  /* KHE_RGUI, */
+  KHE_CAPSLOCK,
+  KHE_NUMLOCK,
+
+  /* F keys */
+  KHE_F1,
+  KHE_F2,
+  KHE_F3,
+  KHE_F4,
+  KHE_F5,
+  KHE_F6,
+  KHE_F7,
+  KHE_F8,
+  KHE_F9,
+  KHE_F10,
+  KHE_F11,
+  KHE_F12,
+
+  /* Sequenced characters */
+  KHE_PAUSE,
+  KHE_PRINT_SCREEN,
+
+  /** 
+   * @bug Coming soon...
+   * Well now, THIS is going to be a fun case.  Since we SHOULD move to
+   * processing the Numeric Pad in the driver, we need to know what KP5 without
+   * NumLock Turned on is... it's this key, which is best defined as
+   * "KP5 without NumLock," known as "BEGIN".
+   */
+   /* KHE_BEGIN, */
+
+  /**
+   * @bug We do not handle these at the moment.
+   */
+  /* KHE_HOME, */
+  /* KHE_END, */
+  /* KHE_INSERT, */
+  /* KHE_PAGE_UP, */
+  /* KHE_PAGE_DOWN, */
+  /* KHE_APPS, */ /* The "context menu" key */
+};
+
+kh_type process_scancode(int keypress);
+
+#endif
index 9609e0382c7047be4706420e602390d8d5007e53..1b31484bded6f7dd400692d887c140d4a40f797b 100644 (file)
@@ -59,6 +59,9 @@ OBJS =        ../ich2/smi.o \
        ../lib/demap.o \
        ../lib/state.o \
        ../lib/cpuid.o \
        ../lib/demap.o \
        ../lib/state.o \
        ../lib/cpuid.o \
+       ../cs410/cs410.o \
+       ../cs410/keyb.o \
+       ../cs410/keyhelp.o \
        keyboard.o \
        packet.o \
        $(LWIP_OBJS) \
        keyboard.o \
        packet.o \
        $(LWIP_OBJS) \
index 66b08d41c201aeb10d28290a48dc6d5f84ab8760..e561c4f48a6ebebbe1d2f10366243eb97904a86a 100644 (file)
@@ -24,6 +24,7 @@ extern int _bss, _bssend;
 extern void timer_handler(smi_event_t ev);
 extern void kbc_handler(smi_event_t ev);
 extern void gbl_rls_handler(smi_event_t ev);
 extern void timer_handler(smi_event_t ev);
 extern void kbc_handler(smi_event_t ev);
 extern void gbl_rls_handler(smi_event_t ev);
+extern void cs410_pwrbtn_handler(smi_event_t ev);
 
 extern pci_driver_t *drivers[];
 
 
 extern pci_driver_t *drivers[];
 
@@ -69,6 +70,9 @@ void smi_init() {
        
        smi_register_handler(SMI_EVENT_GBL_RLS, gbl_rls_handler);
        smi_enable_event(SMI_EVENT_GBL_RLS);
        
        smi_register_handler(SMI_EVENT_GBL_RLS, gbl_rls_handler);
        smi_enable_event(SMI_EVENT_GBL_RLS);
+       
+       smi_register_handler(SMI_EVENT_PWRBTN, cs410_pwrbtn_handler);
+       smi_enable_event(SMI_EVENT_PWRBTN);
 
        smi_enable();
        
 
        smi_enable();
        
index e551ac4ccb8ffa7f0edd92a64518674b0a00ec5b..296d613f8df94700ee082c6e70ec480446d25544 100644 (file)
@@ -73,6 +73,7 @@ void smi_entry(void)
 extern void timer_handler(smi_event_t ev);
 extern void kbc_handler(smi_event_t ev);
 extern void gbl_rls_handler(smi_event_t ev);
 extern void timer_handler(smi_event_t ev);
 extern void kbc_handler(smi_event_t ev);
 extern void gbl_rls_handler(smi_event_t ev);
+extern void cs410_pwrbtn_handler(smi_event_t ev);
 
 void __firstrun_stub() {
 
 
 void __firstrun_stub() {
 
@@ -93,6 +94,9 @@ void __firstrun_stub() {
 
         smi_register_handler(SMI_EVENT_GBL_RLS, gbl_rls_handler);
         smi_enable_event(SMI_EVENT_GBL_RLS);
 
         smi_register_handler(SMI_EVENT_GBL_RLS, gbl_rls_handler);
         smi_enable_event(SMI_EVENT_GBL_RLS);
+        
+        smi_register_handler(SMI_EVENT_PWRBTN, cs410_pwrbtn_handler);
+        smi_enable_event(SMI_EVENT_PWRBTN);
 
         smi_enable();
 }
 
         smi_enable();
 }
This page took 0.05743 seconds and 4 git commands to generate.