@@ 2,6 2,8 @@
#include "lib.h"
#include "dat.h"
#include "fns.h"
+#include "io.h"
+#include "mem.h"
enum {
Data= 0x60, /* data port */
@@ 16,120 18,366 @@ enum {
Rtimeout= 0x40, /* receive timeout */
Parity= 0x80, /* 0==odd, 1==even */
-
+ Spec= 0x80,
+
+ PF= Spec|0x20, /* num pad function key */
+ View= Spec|0x00, /* view (shift window up) */
+ F= Spec|0x40, /* function key */
+ Shift= Spec|0x60,
+ Break= Spec|0x61,
+ Ctrl= Spec|0x62,
+ Latin= Spec|0x63,
+ Caps= Spec|0x64,
+ Num= Spec|0x65,
+ No= Spec|0x7F, /* no mapping */
+
+ Home= F|13,
+ Up= F|14,
+ Pgup= F|15,
+ Print= F|16,
+ Left= View,
+ Right= View,
+ End= '\r',
+ Down= View,
+ Pgdown= View,
+ Ins= F|20,
+ Del= 0x7F,
};
-char noshift[256] =
+uchar kbtab[] =
{
-[0x00] Nokey, 0x1b, '1', '2', '3', '4', '5', '6',
+[0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
[0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
-[0x10]
-[0x28]
-[0x30]
+[0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+[0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
+[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
+[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, No,
+[0x38] Latin, ' ', Caps, F|1, F|2, F|3, F|4, F|5,
+[0x40] F|6, F|7, F|8, F|9, F|10, Num, F|12, Home,
+[0x48] No, No, No, No, No, No, No, No,
+[0x50] No, No, No, No, No, No, No, F|11,
+[0x58] F|12, No, No, No, No, No, No, No,
+};
+
+uchar kbtabshift[] =
+{
+[0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
+[0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
+[0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
+[0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
+[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
+[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
+[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, No,
+[0x38] Latin, ' ', Caps, F|1, F|2, F|3, F|4, F|5,
+[0x40] F|6, F|7, F|8, F|9, F|10, Num, F|12, Home,
+[0x48] No, No, No, No, No, No, No, No,
+[0x50] No, No, No, No, No, No, No, F|11,
+[0x58] F|12, No, No, No, No, No, No, No,
+};
+
+uchar kbtabesc1[] =
+{
+[0x00] No, No, No, No, No, No, No, No,
+[0x08] No, No, No, No, No, No, No, No,
+[0x10] No, No, No, No, No, No, No, No,
+[0x18] No, No, No, No, No, Ctrl, No, No,
+[0x20] No, No, No, No, No, No, No, No,
+[0x28] No, No, No, No, No, No, No, No,
+[0x30] No, No, No, No, No, No, No, Print,
+[0x38] Latin, No, No, No, No, No, No, No,
+[0x40] No, No, No, No, No, No, Break, Home,
+[0x48] Up, Pgup, No, Down, No, Right, No, End,
+[0x50] Left, Pgdown, Ins, Del, No, No, No, No,
+[0x58] No, No, No, No, No, No, No, No,
+};
+
+struct latin
+{
+ uchar l;
+ char c[2];
+}latintab[] = {
+ '', "!!", /* spanish initial ! */
+ '', "c|", /* cent */
+ '', "c$", /* cent */
+ '', "l$", /* pound sterling */
+ '', "g$", /* general currency */
+ '', "y$", /* yen */
+ '', "j$", /* yen */
+ '', "||", /* broken vertical bar */
+ '', "SS", /* section symbol */
+ '', "\"\"", /* dieresis */
+ '', "cr", /* copyright */
+ '', "cO", /* copyright */
+ '', "sa", /* super a, feminine ordinal */
+ '', "<<", /* left angle quotation */
+ '', "no", /* not sign, hooked overbar */
+ '', "--", /* soft hyphen */
+ '', "rg", /* registered trademark */
+ '', "__", /* macron */
+ '', "s0", /* degree (sup o) */
+ '', "+-", /* plus-minus */
+ '', "s2", /* sup 2 */
+ '', "s3", /* sup 3 */
+ '', "''", /* grave accent */
+ '', "mu", /* mu */
+ '', "pg", /* paragraph (pilcrow) */
+ '', "..", /* centered . */
+ '', ",,", /* cedilla */
+ '', "s1", /* sup 1 */
+ '', "so", /* sup o */
+ '', ">>", /* right angle quotation */
+ '', "14", /* 1/4 */
+ '', "12", /* 1/2 */
+ '', "34", /* 3/4 */
+ '', "??", /* spanish initial ? */
+ '', "A`", /* A grave */
+ '', "A'", /* A acute */
+ '', "A^", /* A circumflex */
+ '', "A~", /* A tilde */
+ '', "A\"", /* A dieresis */
+ '', "A:", /* A dieresis */
+ '', "Ao", /* A circle */
+ '', "AO", /* A circle */
+ '', "Ae", /* AE ligature */
+ '', "AE", /* AE ligature */
+ '', "C,", /* C cedilla */
+ '', "E`", /* E grave */
+ '', "E'", /* E acute */
+ '', "E^", /* E circumflex */
+ '', "E\"", /* E dieresis */
+ '', "E:", /* E dieresis */
+ '', "I`", /* I grave */
+ '', "I'", /* I acute */
+ '', "I^", /* I circumflex */
+ '', "I\"", /* I dieresis */
+ '', "I:", /* I dieresis */
+ '', "D-", /* Eth */
+ '', "N~", /* N tilde */
+ '', "O`", /* O grave */
+ '', "O'", /* O acute */
+ '', "O^", /* O circumflex */
+ '', "O~", /* O tilde */
+ '', "O\"", /* O dieresis */
+ '', "O:", /* O dieresis */
+ '', "OE", /* O dieresis */
+ '', "Oe", /* O dieresis */
+ '', "xx", /* times sign */
+ '', "O/", /* O slash */
+ '', "U`", /* U grave */
+ '', "U'", /* U acute */
+ '', "U^", /* U circumflex */
+ '', "U\"", /* U dieresis */
+ '', "U:", /* U dieresis */
+ '', "UE", /* U dieresis */
+ '', "Ue", /* U dieresis */
+ '', "Y'", /* Y acute */
+ '', "P|", /* Thorn */
+ '', "Th", /* Thorn */
+ '', "TH", /* Thorn */
+ '', "ss", /* sharp s */
+ '', "a`", /* a grave */
+ '', "a'", /* a acute */
+ '', "a^", /* a circumflex */
+ '', "a~", /* a tilde */
+ '', "a\"", /* a dieresis */
+ '', "a:", /* a dieresis */
+ '', "ao", /* a circle */
+ '', "ae", /* ae ligature */
+ '', "c,", /* c cedilla */
+ '', "e`", /* e grave */
+ '', "e'", /* e acute */
+ '', "e^", /* e circumflex */
+ '', "e\"", /* e dieresis */
+ '', "e:", /* e dieresis */
+ '', "i`", /* i grave */
+ '', "i'", /* i acute */
+ '', "i^", /* i circumflex */
+ '', "i\"", /* i dieresis */
+ '', "i:", /* i dieresis */
+ '', "d-", /* eth */
+ '', "n~", /* n tilde */
+ '', "o`", /* o grave */
+ '', "o'", /* o acute */
+ '', "o^", /* o circumflex */
+ '', "o~", /* o tilde */
+ '', "o\"", /* o dieresis */
+ '', "o:", /* o dieresis */
+ '', "oe", /* o dieresis */
+ '', "-:", /* divide sign */
+ '', "o/", /* o slash */
+ '', "u`", /* u grave */
+ '', "u'", /* u acute */
+ '', "u^", /* u circumflex */
+ '', "u\"", /* u dieresis */
+ '', "u:", /* u dieresis */
+ '', "ue", /* u dieresis */
+ '', "y'", /* y acute */
+ '', "th", /* thorn */
+ '', "p|", /* thorn */
+ '', "y\"", /* y dieresis */
+ '', "y:", /* y dieresis */
+ 0, 0,
};
+KIOQ kbdq;
+
+int
+latin1(int k1, int k2)
+{
+ int i;
+ struct latin *l;
+
+ for(l=latintab; l->l; l++)
+ if(k1==l->c[0] && k2==l->c[1])
+ return l->l;
+ return 0;
+}
+
+void
+kbdinit(void)
+{
+ initq(&kbdq);
+ setvec(Kbdvec, kbdintr, SEGIG);
+}
+
/*
* get a byte from the keyboard
*/
int
kbdc(void)
{
- while((inb(Status)&Inready)==0)
- ;
- return inb(Data);
+ int c;
+
+ for(;;){
+ while((inb(Status)&Inready)==0)
+ ;
+ kbdintr(&c);
+ c = getc(&kbdq);
+ if(c != -1)
+ return c;
+ }
}
-1 0x1b,
-3b F1,
-3c F2,
-3d F3,
-3e F4,
-3f F5,
-40 f6,
-41 F7,
-42 F8,
-43 F9,
-44 F10,
-57 F11,
-58 F12,
-e0 52 INS,
-e0 53 DEL,
-2 '1',
-3 '2',
-4 '3',
-5 '4',
-6 '5',
-7 '6',
-8 '7',
-9 '8',
-A '9',
-B '0',
-C '-',
-D '=',
-E '\b',
-E0 47 Home,
-F '\t',
-10 'q',
-11 'w',
-12 'e',
-13 'r',
-14 't',
-15 'y',
-16 'u',
-17 'i',
-18 'o',
-19 'p',
-1a '[',
-1b ']',
-2b '\\',
-e0 49 Pageup,
-3a Capslock,
-1e 'a'
-1f 's'
-20 'd'
-21 'f'
-22 'g'
-23 'h'
-24 'j'
-25 'k'
-26 'l'
-27 ';'
-28 '\''
-1c '\r'
-2a Lshift,
-2c 'z'
-2d 'x'
-2e 'c'
-2f 'v'
-30 'b'
-31 'n'
-32 'm'
-33 ','
-34 '.'
-35 '/'
-36 Rshift,
-e0 51 Pagedown,
-e0 4f End,
-e0 48 Uparrow,
-e0 50 Downarrow,
-e0 4b Leftarrow,
-e0 4d Rightarrow,
-e0 1d Rctl,
-e0 38 Ralt,
-39 Space,
-38 Lalt,
-1d Lctl,
-29 '`',
-1d 38 1 81 b8 9d F1
-1d 38 21 a1 b8 9d F2
- 2e ae F3
- 19 99 F4
- 26 F5
- 2F F6
-
-e1 1d 45 e1 9d cf F7
-e0 46 e0 c6 f8
-e0 2a e0 37 e0 b7 e0 aa f9
-54 f10
-45 f11
-46 f12
+int
+kbdputc(IOQ* q, int c)
+{
+ screenputc(c);
+ putc(q, c);
+}
+
+/*
+ * keyboard interrupt
+ */
+void
+kbdintr(void *a)
+{
+ int c, nc;
+ static int esc1, esc2;
+ static int shift;
+ static int caps;
+ static int ctl;
+ static int num;
+ static int lstate, k1, k2;
+ int keyup;
+
+ /*
+ * get a character to be there
+ */
+ c = inb(Data);
+
+ keyup = c&0x80;
+ c &= 0x7f;
+ if(c > sizeof kbtab){
+ print("unknown key %ux\n", c|keyup);
+ kbdputc(&kbdq, k1);
+ goto out;
+ }
+
+ /*
+ * e0's is the first of a 2 character sequence
+ */
+ if(c == 0xe0){
+ esc1 = 1;
+ goto out;
+ } else if(c == 0xe1){
+ esc2 = 2;
+ goto out;
+ }
+
+ if(esc1){
+ c = kbtabesc1[c];
+ esc1 = 0;
+ } else if(esc2){
+ esc2--;
+ goto out;
+ } else if(shift)
+ c = kbtabshift[c];
+ else
+ c = kbtab[c];
+
+ if(caps && c<='z' && c>='a')
+ c += 'A' - 'a';
+
+ /*
+ * keyup only important for shifts
+ */
+ if(keyup){
+ switch(c){
+ case Shift:
+ shift = 0;
+ break;
+ case Ctrl:
+ ctl = 0;
+ break;
+ }
+ goto out;
+ }
+
+ /*
+ * normal character
+ */
+ if(!(c & Spec)){
+ if(ctl)
+ c &= 0x1f;
+ switch(lstate){
+ case 1:
+ k1 = c;
+ lstate = 2;
+ return;
+ case 2:
+ k2 = c;
+ lstate = 0;
+ c = latin1(k1, k2);
+ if(c == 0){
+ kbdputc(&kbdq, k1);
+ c = k2;
+ }
+ /* fall through */
+ default:
+ break;
+ }
+ } else {
+ switch(c){
+ case Caps:
+ caps ^= 1;
+ goto out;
+ case Num:
+ num ^= 1;
+ goto out;
+ case Shift:
+ shift = 1;
+ goto out;
+ case Latin:
+ lstate = 1;
+ goto out;
+ case Ctrl:
+ ctl = 1;
+ goto out;
+ }
+ }
+ kbdputc(&kbdq, c);
+out:
+ INTENABLE; /* reenable interrupt */
+ return;
+}
@@ 4,76 4,96 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
-
-void ediv(void);
-void edebug(void);
-void enmi(void);
-void ebp(void);
-void eover(void);
-void ebound(void);
-void ebadop(void);
-void enoco(void);
-void edfault(void);
-void enoway(void);
-void etss(void);
-void enoseg(void);
-void estack(void);
-void eprot(void);
-void efault(void);
-
-/*
- * exception types
- */
-enum {
- Ediv= 0, /* divide error */
- Edebug= 1, /* debug exceptions */
- Enmi= 2, /* non-maskable interrupt */
- Ebp= 3, /* INT 3 */
- Eover= 4, /* overflow */
- Ebound= 5, /* bounds check */
- Ebadop= 6, /* invalid opcode */
- Enoco= 7, /* coprocessor not available */
- Edfault=8, /* double fault */
- Etss= 10, /* invalid tss */
- Enoseg= 11, /* segment not present */
- Estack= 12, /* stack exception */
- Eprot= 13, /* general protection */
- Efault= 14, /* page fault */
- Eco= 16, /* coprocessor error */
-};
+#include "ureg.h"
/*
* trap/interrupt gates
*/
-Segdesc ilt[256] =
+Segdesc ilt[256];
+void (*ivec[256])(void*);
+
+void
+sethvec(int v, void (*r)(void), int type)
+{
+ ilt[v].d0 = ((ulong)r)&0xFFFF|(KESEL<<16);
+ ilt[v].d1 = ((ulong)r)&0xFFFF0000|SEGP|SEGPL(3)|type;
+}
+
+void
+setvec(int v, void (*r)(void*), int type)
{
-[Ediv] TRAPGATE(KESEL, ediv, 3),
-[Edebug] TRAPGATE(KESEL, edebug, 3),
-[Enmi] INTRGATE(KESEL, enmi, 3),
-[Ebp] TRAPGATE(KESEL, ebp, 3),
-[Eover] TRAPGATE(KESEL, eover, 3),
-[Ebound] TRAPGATE(KESEL, ebound, 3),
-[Ebadop] TRAPGATE(KESEL, ebadop, 3),
-[Enoco] TRAPGATE(KESEL, enoco, 3),
-[Edfault] TRAPGATE(KESEL, edfault, 3),
-[Etss] TRAPGATE(KESEL, etss, 3),
-[Enoseg] TRAPGATE(KESEL, enoseg, 3),
-[Estack] TRAPGATE(KESEL, estack, 3),
-[Eprot] TRAPGATE(KESEL, eprot, 3),
-[Efault] TRAPGATE(KESEL, efault, 3),
-[Eco] TRAPGATE(KESEL, eco, 3),
-};
+ ilt[v].d1 &= ~SEGTYPE;
+ ilt[v].d1 |= type;
+ ivec[v] = r;
+}
/*
- * trap table
+ * set up the interrupt/trap gates
*/
-uchar traptab[4096];
+void
+trapinit(void)
+{
+ int i;
+
+ /*
+ * set the standard traps
+ */
+ sethvec(0, intr0, SEGTG);
+ sethvec(1, intr1, SEGTG);
+ sethvec(2, intr2, SEGTG);
+ sethvec(3, intr3, SEGTG);
+ sethvec(4, intr4, SEGTG);
+ sethvec(5, intr5, SEGTG);
+ sethvec(6, intr6, SEGTG);
+ sethvec(7, intr7, SEGTG);
+ sethvec(8, intr8, SEGTG);
+ sethvec(9, intr9, SEGTG);
+ sethvec(10, intr10, SEGTG);
+ sethvec(11, intr11, SEGTG);
+ sethvec(12, intr12, SEGTG);
+ sethvec(13, intr13, SEGTG);
+ sethvec(14, intr14, SEGTG);
+ sethvec(15, intr15, SEGTG);
+ sethvec(16, intr16, SEGTG);
+
+ /*
+ * set all others to unknown
+ */
+ for(i = 17; i < 256; i++)
+ sethvec(i, intrbad, SEGIG);
+
+ /*
+ * tell the hardware where the table is (and how long)
+ */
+ lidt(ilt, sizeof(ilt));
+}
+
/*
- * j-random uncaught trap or interrupt
+ * All traps
*/
-void
-trap(void)
+trap(Ureg *ur)
{
- panic("unknown trap");
+ print("trap %lux\n", ur->trap);
+ print(" edi %lux\n", ur->edi);
+ print(" esi %lux\n", ur->esi);
+ print(" ebp %lux\n", ur->ebp);
+ print(" esp %lux\n", ur->esp);
+ print(" ebx %lux\n", ur->ebx);
+ print(" edx %lux\n", ur->edx);
+ print(" ecx %lux\n", ur->ecx);
+ print(" eax %lux\n", ur->eax);
+ print(" ds %lux\n", ur->ds);
+ print(" trap %lux\n", ur->trap);
+ print(" ecode %lux\n", ur->ecode);
+ print(" eip %lux\n", ur->eip);
+ print(" cs %lux\n", ur->cs);
+ print(" eflags %lux\n", ur->eflags);
+ print(" oesp %lux\n", ur->oesp);
+ print(" ss %lux\n", ur->ss);
+ delay(500);
+ if(ur->trap>=256 || ivec[ur->trap] == 0)
+ panic("bad trap type %d\n", ur->trap);
+
+ (*ivec[ur->trap])(ur);
}