|
|
1.1 root 1: #include "u.h"
2: #include "lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "io.h"
7:
8: #include <libg.h>
9:
10: enum {
11: Data= 0x60, /* data port */
12:
13: Status= 0x64, /* status port */
14: Inready= 0x01, /* input character ready */
15: Outbusy= 0x02, /* output busy */
16: Sysflag= 0x04, /* system flag */
17: Cmddata= 0x08, /* cmd==0, data==1 */
18: Inhibit= 0x10, /* keyboard/mouse inhibited */
19: Minready= 0x20, /* mouse character ready */
20: Rtimeout= 0x40, /* general timeout */
21: Parity= 0x80,
22:
23: Cmd= 0x64, /* command port (write only) */
24:
25: Spec= 0x80,
26:
27: PF= Spec|0x20, /* num pad function key */
28: View= Spec|0x00, /* view (shift window up) */
29: KF= Spec|0x40, /* function key */
30: Shift= Spec|0x60,
31: Break= Spec|0x61,
32: Ctrl= Spec|0x62,
33: Latin= Spec|0x63,
34: Caps= Spec|0x64,
35: Num= Spec|0x65,
36: No= Spec|0x7F, /* no mapping */
37:
38: Home= KF|13,
39: Up= KF|14,
40: Pgup= KF|15,
41: Print= KF|16,
42: Left= View,
43: Right= View,
44: End= '\r',
45: Down= View,
46: Pgdown= View,
47: Ins= KF|20,
48: Del= 0x7F,
49: };
50:
51: uchar kbtab[] =
52: {
53: [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
54: [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
55: [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
56: [0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
57: [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
58: [0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
59: [0x30] 'b', 'n', 'm', ',', '.', '/', Shift, No,
60: [0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
61: [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
62: [0x48] No, No, No, No, No, No, No, No,
63: [0x50] No, No, No, No, No, No, No, KF|11,
64: [0x58] KF|12, No, No, No, No, No, No, No,
65: };
66:
67: uchar kbtabshift[] =
68: {
69: [0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
70: [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
71: [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
72: [0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
73: [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
74: [0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
75: [0x30] 'B', 'N', 'M', '<', '>', '?', Shift, No,
76: [0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
77: [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
78: [0x48] No, No, No, No, No, No, No, No,
79: [0x50] No, No, No, No, No, No, No, KF|11,
80: [0x58] KF|12, No, No, No, No, No, No, No,
81: };
82:
83: uchar kbtabesc1[] =
84: {
85: [0x00] No, No, No, No, No, No, No, No,
86: [0x08] No, No, No, No, No, No, No, No,
87: [0x10] No, No, No, No, No, No, No, No,
88: [0x18] No, No, No, No, No, Ctrl, No, No,
89: [0x20] No, No, No, No, No, No, No, No,
90: [0x28] No, No, No, No, No, No, No, No,
91: [0x30] No, No, No, No, No, No, No, Print,
92: [0x38] Latin, No, No, No, No, No, No, No,
93: [0x40] No, No, No, No, No, No, Break, Home,
94: [0x48] Up, Pgup, No, Down, No, Right, No, End,
95: [0x50] Left, Pgdown, Ins, Del, No, No, No, No,
96: [0x58] No, No, No, No, No, No, No, No,
97: };
98:
99: struct latin
100: {
101: uchar l;
102: char c[2];
103: }latintab[] = {
104: '¡', "!!", /* spanish initial ! */
105: '¢', "c|", /* cent */
106: '¢', "c$", /* cent */
107: '£', "l$", /* pound sterling */
108: '¤', "g$", /* general currency */
109: '¥', "y$", /* yen */
110: '¥', "j$", /* yen */
111: '¦', "||", /* broken vertical bar */
112: '§', "SS", /* section symbol */
113: '¨', "\"\"", /* dieresis */
114: '©', "cr", /* copyright */
115: '©', "cO", /* copyright */
116: 'ª', "sa", /* super a, feminine ordinal */
117: '«', "<<", /* left angle quotation */
118: '¬', "no", /* not sign, hooked overbar */
119: '', "--", /* soft hyphen */
120: '®', "rg", /* registered trademark */
121: '¯', "__", /* macron */
122: '°', "s0", /* degree (sup o) */
123: '±', "+-", /* plus-minus */
124: '²', "s2", /* sup 2 */
125: '³', "s3", /* sup 3 */
126: '´', "''", /* grave accent */
127: 'µ', "mu", /* mu */
128: '¶', "pg", /* paragraph (pilcrow) */
129: '·', "..", /* centered . */
130: '¸', ",,", /* cedilla */
131: '¹', "s1", /* sup 1 */
132: 'º', "so", /* sup o */
133: '»', ">>", /* right angle quotation */
134: '¼', "14", /* 1/4 */
135: '½', "12", /* 1/2 */
136: '¾', "34", /* 3/4 */
137: '¿', "??", /* spanish initial ? */
138: 'À', "A`", /* A grave */
139: 'Á', "A'", /* A acute */
140: 'Â', "A^", /* A circumflex */
141: 'Ã', "A~", /* A tilde */
142: 'Ä', "A\"", /* A dieresis */
143: 'Ä', "A:", /* A dieresis */
144: 'Å', "Ao", /* A circle */
145: 'Å', "AO", /* A circle */
146: 'Æ', "Ae", /* AE ligature */
147: 'Æ', "AE", /* AE ligature */
148: 'Ç', "C,", /* C cedilla */
149: 'È', "E`", /* E grave */
150: 'É', "E'", /* E acute */
151: 'Ê', "E^", /* E circumflex */
152: 'Ë', "E\"", /* E dieresis */
153: 'Ë', "E:", /* E dieresis */
154: 'Ì', "I`", /* I grave */
155: 'Í', "I'", /* I acute */
156: 'Î', "I^", /* I circumflex */
157: 'Ï', "I\"", /* I dieresis */
158: 'Ï', "I:", /* I dieresis */
159: 'Ð', "D-", /* Eth */
160: 'Ñ', "N~", /* N tilde */
161: 'Ò', "O`", /* O grave */
162: 'Ó', "O'", /* O acute */
163: 'Ô', "O^", /* O circumflex */
164: 'Õ', "O~", /* O tilde */
165: 'Ö', "O\"", /* O dieresis */
166: 'Ö', "O:", /* O dieresis */
167: 'Ö', "OE", /* O dieresis */
168: 'Ö', "Oe", /* O dieresis */
169: '×', "xx", /* times sign */
170: 'Ø', "O/", /* O slash */
171: 'Ù', "U`", /* U grave */
172: 'Ú', "U'", /* U acute */
173: 'Û', "U^", /* U circumflex */
174: 'Ü', "U\"", /* U dieresis */
175: 'Ü', "U:", /* U dieresis */
176: 'Ü', "UE", /* U dieresis */
177: 'Ü', "Ue", /* U dieresis */
178: 'Ý', "Y'", /* Y acute */
179: 'Þ', "P|", /* Thorn */
180: 'Þ', "Th", /* Thorn */
181: 'Þ', "TH", /* Thorn */
182: 'ß', "ss", /* sharp s */
183: 'à', "a`", /* a grave */
184: 'á', "a'", /* a acute */
185: 'â', "a^", /* a circumflex */
186: 'ã', "a~", /* a tilde */
187: 'ä', "a\"", /* a dieresis */
188: 'ä', "a:", /* a dieresis */
189: 'å', "ao", /* a circle */
190: 'æ', "ae", /* ae ligature */
191: 'ç', "c,", /* c cedilla */
192: 'è', "e`", /* e grave */
193: 'é', "e'", /* e acute */
194: 'ê', "e^", /* e circumflex */
195: 'ë', "e\"", /* e dieresis */
196: 'ë', "e:", /* e dieresis */
197: 'ì', "i`", /* i grave */
198: 'í', "i'", /* i acute */
199: 'î', "i^", /* i circumflex */
200: 'ï', "i\"", /* i dieresis */
201: 'ï', "i:", /* i dieresis */
202: 'ð', "d-", /* eth */
203: 'ñ', "n~", /* n tilde */
204: 'ò', "o`", /* o grave */
205: 'ó', "o'", /* o acute */
206: 'ô', "o^", /* o circumflex */
207: 'õ', "o~", /* o tilde */
208: 'ö', "o\"", /* o dieresis */
209: 'ö', "o:", /* o dieresis */
210: 'ö', "oe", /* o dieresis */
211: '÷', "-:", /* divide sign */
212: 'ø', "o/", /* o slash */
213: 'ù', "u`", /* u grave */
214: 'ú', "u'", /* u acute */
215: 'û', "u^", /* u circumflex */
216: 'ü', "u\"", /* u dieresis */
217: 'ü', "u:", /* u dieresis */
218: 'ü', "ue", /* u dieresis */
219: 'ý', "y'", /* y acute */
220: 'þ', "th", /* thorn */
221: 'þ', "p|", /* thorn */
222: 'ÿ', "y\"", /* y dieresis */
223: 'ÿ', "y:", /* y dieresis */
224: 0, 0,
225: };
226:
227: enum
228: {
229: /* controller command byte */
230: Cscs1= (1<<6), /* scan code set 1 */
231: Cmousedis= (1<<5), /* mouse disable */
232: Ckbddis= (1<<4), /* kbd disable */
233: Csf= (1<<2), /* system flag */
234: Cmouseint= (1<<1), /* mouse interrupt enable */
235: Ckbdint= (1<<0), /* kbd interrupt enable */
236: };
237:
238: static uchar ccc;
239:
240: int
241: latin1(int k1, int k2)
242: {
243: struct latin *l;
244:
245: for(l=latintab; l->l; l++)
246: if(k1==l->c[0] && k2==l->c[1])
247: return l->l;
248: return 0;
249: }
250:
251: /*
252: * wait for output no longer busy
253: */
254: static int
255: outready(void)
256: {
257: int tries;
258:
259: for(tries = 0; (inb(Status) & Outbusy); tries++){
260: if(tries > 500)
261: return -1;
262: delay(2);
263: }
264: return 0;
265: }
266:
267: /*
268: * wait for input
269: */
270: static int
271: inready(void)
272: {
273: int tries;
274:
275: for(tries = 0; !(inb(Status) & Inready); tries++){
276: if(tries > 500)
277: return -1;
278: delay(2);
279: }
280: return 0;
281: }
282:
283: /*
284: * ask 8042 to enable the use of address bit 20
285: */
286: void
287: i8042a20(void)
288: {
289: outready();
290: outb(Cmd, 0xD1);
291: outready();
292: outb(Data, 0xDF);
293: outready();
294: }
295:
296: /*
297: * ask 8042 to reset the machine
298: */
299: void
300: i8042reset(void)
301: {
302: ushort *s = (ushort*)(KZERO|0x472);
303: int i, x;
304:
305: *s = 0x1234; /* BIOS warm-boot flag */
306:
307: outready();
308: outb(Cmd, 0xFE); /* pulse reset line (means resend on AT&T machines) */
309: outready();
310:
311: /*
312: * Pulse it by hand (old somewhat reliable)
313: */
314: x = 0xDF;
315: for(i = 0; i < 5; i++){
316: x ^= 1;
317: outready();
318: outb(Cmd, 0xD1);
319: outready();
320: outb(Data, x); /* toggle reset */
321: delay(100);
322: }
323: }
324:
325: /*
326: * keyboard interrupt
327: */
328: int
329: kbdintr0(void)
330: {
331: int s, c;
332: static int esc1, esc2;
333: static int shift;
334: static int caps;
335: static int ctl;
336: static int num;
337: static int lstate, k1, k2;
338: int keyup;
339:
340: /*
341: * get status
342: */
343: s = inb(Status);
344: if(!(s&Inready))
345: return -1;
346:
347: /*
348: * get the character
349: */
350: c = inb(Data);
351:
352: /*
353: * e0's is the first of a 2 character sequence
354: */
355: if(c == 0xe0){
356: esc1 = 1;
357: return 0;
358: } else if(c == 0xe1){
359: esc2 = 2;
360: return 0;
361: }
362:
363: keyup = c&0x80;
364: c &= 0x7f;
365: if(c > sizeof kbtab){
366: print("unknown key %ux\n", c|keyup);
367: kbdchar(k1);
368: return 0;
369: }
370:
371: if(esc1){
372: c = kbtabesc1[c];
373: esc1 = 0;
374: kbdchar(c);
375: return 0;
376: } else if(esc2){
377: esc2--;
378: return 0;
379: } else if(shift)
380: c = kbtabshift[c];
381: else
382: c = kbtab[c];
383:
384: if(caps && c<='z' && c>='a')
385: c += 'A' - 'a';
386:
387: /*
388: * keyup only important for shifts
389: */
390: if(keyup){
391: switch(c){
392: case Shift:
393: shift = 0;
394: break;
395: case Ctrl:
396: ctl = 0;
397: break;
398: }
399: return 0;
400: }
401:
402: /*
403: * normal character
404: */
405: if(!(c & Spec)){
406: if(ctl)
407: c &= 0x1f;
408: switch(lstate){
409: case 1:
410: k1 = c;
411: lstate = 2;
412: return 0;
413: case 2:
414: k2 = c;
415: lstate = 0;
416: c = latin1(k1, k2);
417: if(c == 0){
418: kbdchar(k1);
419: c = k2;
420: }
421: /* fall through */
422: default:
423: break;
424: }
425: } else {
426: switch(c){
427: case Caps:
428: caps ^= 1;
429: return 0;
430: case Num:
431: num ^= 1;
432: return 0;
433: case Shift:
434: shift = 1;
435: return 0;
436: case Latin:
437: lstate = 1;
438: return 0;
439: case Ctrl:
440: ctl = 1;
441: return 0;
442: }
443: }
444: kbdchar(c);
445: return 0;
446: }
447:
448: static void
449: kbdintr(Ureg*, void*)
450: {
451: while(kbdintr0() == 0)
452: ;
453: }
454:
455: void
456: kbdinit(void)
457: {
458: int c;
459:
460: /* wait for a quiescent controller */
461: while((c = inb(Status)) & (Outbusy | Inready))
462: if(c & Inready)
463: inb(Data);
464:
465: /* get current controller command byte */
466: outb(Cmd, 0x20);
467: if(inready() < 0){
468: print("kbdinit: can't read ccc\n");
469: ccc = 0;
470: } else
471: ccc = inb(Data);
472:
473: /* enable kbd xfers and interrupts */
474: ccc &= ~Ckbddis;
475: ccc |= Csf | Ckbdint | Cscs1;
476: if(outready() < 0)
477: print("kbd init failed\n");
478: outb(Cmd, 0x60);
479: if(outready() < 0)
480: print("kbd init failed\n");
481: outb(Data, ccc);
482: if(outready() < 0)
483: print("kbd init failed\n");
484:
485: setvec(Kbdvec, kbdintr, 0);
486: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.