| plan 9 kernel history: overview | file list | diff list |
1994/0306/carrera/kbd.c (diff list | history)
| carrera/kbd.c on 1993/0907 | ||
| 1993/0907 | #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #include "devtab.h" enum { | |
| 1994/0306 | /* controller command byte */ Cscs1= (1<<6), /* scan code set 1 */ Cmousedis= (1<<5), /* mouse disable */ Ckbddis= (1<<4), /* kbd disable */ Csf= (1<<2), /* system flag */ Cmouseint= (1<<1), /* mouse interrupt enable */ Ckbdint= (1<<0), /* kbd interrupt enable */ | |
| 1993/0907 | /* * responses from keyboard */ Rok= 0xAA, /* self test OK */ Recho= 0xEE, /* ??? */ Rack= 0xFA, /* command acknowledged */ Rfail= 0xFC, /* self test failed */ Rresend= 0xFE, /* ??? */ Rovfl= 0xFF, /* input overflow */ | |
| 1994/0306 | ||
| 1993/0907 | /* * status bits */ Sobf= 1<<0, /* output buffer full */ Sibf= 1<<1, /* input buffer full */ Ssys= 1<<2, /* set by self-test */ Slast= 1<<3, /* last access was to data */ Senabled= 1<<4, /* keyboard is enabled */ Stxtimeout= 1<<5, /* transmit to kybd has timed out */ Srxtimeout= 1<<6, /* receive from kybd has timed out */ Sparity= 1<<7, /* parity on byte was even */ | |
| 1994/0306 | Spec= 0x80, PF= Spec|0x20, /* num pad function key */ View= Spec|0x00, /* view (shift window up) */ KF= Spec|0x40, /* function key */ Shift= Spec|0x60, Break= Spec|0x61, Ctrl= Spec|0x62, Latin= Spec|0x63, Caps= Spec|0x64, Num= Spec|0x65, Middle= Spec|0x66, No= 0x00, /* peter */ Home= KF|13, Up= KF|14, Pgup= KF|15, Print= KF|16, Left= View, Right= View, End= '\r', Down= View, Pgdown= View, Ins= KF|20, Del= 0x7F, | |
| 1993/0907 | }; #define KBDCTL (*(uchar*)(KeyboardIO+Keyctl)) #define KBDDAT (*(uchar*)(KeyboardIO+Keydat)) #define OUTWAIT while(KBDCTL & Sibf); kdbdly(1) #define INWAIT while(!(KBDCTL & Sobf)); kdbdly(1) #define ACKWAIT INWAIT ; if(KBDDAT != Rack) print("bad response\n"); kdbdly(1) | |
| 1994/0306 | uchar kbtab[] = | |
| 1993/0907 | { | |
| 1994/0306 | [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6', [0x08] '7', '8', '9', '0', '-', '=', '\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, '*', [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5, [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, '7', [0x48] '8', '9', '-', '4', '5', '6', '+', '1', [0x50] '2', '3', '0', '.', No, No, No, KF|11, [0x58] KF|12, No, No, No, No, No, No, No, | |
| 1993/0907 | }; | |
| 1994/0306 | 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, '*', [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5, [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, '7', [0x48] '8', '9', '-', '4', '5', '6', '+', '1', [0x50] '2', '3', '0', '.', No, No, No, KF|11, [0x58] KF|12, No, No, No, No, No, No, No, | |
| 1993/0907 | }; | |
| 1994/0306 | 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, '\n', Ctrl, No, No, [0x20] No, No, No, No, No, No, No, No, [0x28] No, No, Shift, No, No, No, No, No, [0x30] 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, Left, No, Right, No, End, [0x50] Down, Pgdown, Ins, Del, No, No, No, No, [0x58] No, No, No, No, No, No, No, No, | |
| 1993/0907 | }; struct Kbd { Lock; int l; } kbd; | |
| 1994/0306 | static uchar ccc; | |
| 1993/0907 | void kdbdly(int l) { int i; | |
| 1993/0908 | l *= 21; /* experimentally determined */ | |
| 1993/0907 | for(i=0; i<l; i++) ; } /* * wait for a keyboard event (or some max time) */ int kbdwait(void) { int tries; for(tries = 0; tries < 2000; tries++){ | |
| 1993/1001 | if(KBDCTL & Sobf) | |
| 1993/0907 | return 1; kdbdly(1); } return 0; } | |
| 1993/1001 | void mouseintr(void) { | |
| 1993/1003 | uchar c; static int nb; int buttons, dx, dy; static short msg[3]; static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 5, 2, 3, 6, 7 }; | |
| 1993/1001 | kbdwait(); | |
| 1993/1003 | c = KBDDAT; /* * check byte 0 for consistency */ if(nb==0 && (c&0xc8)!=0x08) return; msg[nb] = c; if(++nb == 3){ nb = 0; if(msg[0] & 0x10) msg[1] |= 0xFF00; if(msg[0] & 0x20) msg[2] |= 0xFF00; buttons = b[msg[0]&7]; dx = msg[1]; dy = -msg[2]; mousetrack(buttons, dx, dy); } | |
| 1993/0907 | } | |
| 1994/0306 | void | |
| 1993/0907 | kbdintr(void) { int c, i, nk; | |
| 1994/0306 | static int esc1, esc2; static int caps; static int ctl; static int num; static int lstate; | |
| 1993/0907 | static uchar kc[5]; | |
| 1994/0306 | static int shift; int keyup; | |
| 1993/0907 | kbdwait(); | |
| 1994/0306 | c = KBDDAT; | |
| 1993/0907 | /* | |
| 1994/0306 | * e0's is the first of a 2 character sequence | |
| 1993/0907 | */ | |
| 1994/0306 | if(c == 0xe0){ esc1 = 1; return; } else if(c == 0xe1){ esc2 = 2; return; | |
| 1993/0908 | } | |
| 1994/0306 | keyup = c&0x80; c &= 0x7f; if(c > sizeof kbtab){ print("unknown key %ux\n", c|keyup); return; } | |
| 1993/0908 | ||
| 1994/0306 | if(esc1){ c = kbtabesc1[c]; esc1 = 0; | |
| 1993/0907 | } | |
| 1994/0306 | else if(esc2){ esc2--; return; } else if(shift) c = kbtabshift[c]; else c = kbtab[c]; | |
| 1993/0907 | ||
| 1994/0306 | if(caps && c<='z' && c>='a') c += 'A' - 'a'; | |
| 1993/0907 | /* | |
| 1994/0306 | * keyup only important for shifts | |
| 1993/0907 | */ | |
| 1994/0306 | if(keyup){ switch(c){ case Shift: shift = 0; break; case Ctrl: ctl = 0; break; } return; } | |
| 1993/0907 | /* * normal character */ | |
| 1994/0306 | if(!(c & Spec)){ if(ctl) c &= 0x1f; | |
| 1993/0907 | switch(lstate){ case 1: | |
| 1994/0306 | kc[0] = c; | |
| 1993/0907 | lstate = 2; | |
| 1994/0306 | if(c == 'X') | |
| 1993/0907 | lstate = 3; break; case 2: | |
| 1994/0306 | kc[1] = c; | |
| 1993/0907 | c = latin1(kc); nk = 2; putit: lstate = 0; if(c != -1) kbdputc(kbdq, c); | |
| 1994/0306 | else for(i=0; i<nk; i++) kbdputc(kbdq, kc[i]); | |
| 1993/0907 | break; case 3: case 4: case 5: | |
| 1994/0306 | kc[lstate-2] = c; | |
| 1993/0907 | lstate++; break; case 6: | |
| 1994/0306 | kc[4] = c; | |
| 1993/0907 | c = unicode(kc); nk = 5; goto putit; default: | |
| 1994/0306 | kbdputc(kbdq, c); | |
| 1993/0907 | break; } | |
| 1994/0306 | return; | |
| 1993/0907 | } | |
| 1994/0306 | else { switch(c){ case Caps: caps ^= 1; return; case Num: num ^= 1; return; case Shift: shift = 1; return; case Latin: lstate = 1; return; case Ctrl: ctl = 1; return; } | |
| 1993/0907 | } | |
| 1994/0306 | kbdputc(kbdq, c); | |
| 1993/0907 | } void lights(int l) { | |
| 1994/0306 | USED(l); | |
| 1993/0907 | } static void empty(void) { int i; /* * empty the buffer */ kdbdly(20); while(KBDCTL & Sobf){ i = KBDDAT; USED(i); kdbdly(1); } } | |
| 1993/1003 | /* * send a command to the mouse */ static int mousecmd(int cmd) { int tries; unsigned int c; c = 0; tries = 0; do{ if(tries++ > 2) break; OUTWAIT; KBDCTL = 0xD4; OUTWAIT; KBDDAT = cmd; OUTWAIT; kbdwait(); c = KBDDAT; } while(c == 0xFE || c == 0); if(c != 0xFA){ print("mouse returns %2.2ux to the %2.2ux command\n", c, cmd); return -1; } return 0; } | |
| 1993/0907 | int kbdinit(void) { int i; /* * empty the buffer */ while(KBDCTL & Sobf){ i = KBDDAT; USED(i); } | |
| 1994/0306 | /* wait for a quiescent controller */ | |
| 1993/0907 | OUTWAIT; | |
| 1994/0306 | KBDCTL = 0x20; if(kbdwait() == 0) { print("kbdinit: can't read ccc\n"); ccc = 0; } else ccc = KBDDAT; | |
| 1993/0907 | ||
| 1994/0306 | /* enable kbd xfers and interrupts */ ccc &= ~Ckbddis; ccc |= Csf | Ckbdint | Cscs1 | Cmouseint; | |
| 1993/0907 | OUTWAIT; | |
| 1994/0306 | KBDCTL = 0x60; | |
| 1993/0907 | OUTWAIT; | |
| 1994/0306 | KBDDAT = ccc; | |
| 1993/0907 | OUTWAIT; | |
| 1993/1003 | ||
| 1994/0201 | mousecmd(0xEA); /* streaming */ mousecmd(0xE8); /* set resolution */ mousecmd(3); mousecmd(0xF4); /* enabled */ | |
| 1993/0907 | return 1; } | |