|
|
1.1 root 1: /*
2: * io.386/kb_d.c
3: *
4: * Keyboard driver, no virtual consoles, no loadable tables, German.
5: *
6: * Revised: Fri Jul 16 08:39:12 1993 CDT
7: */
8:
9: #include <sys/coherent.h>
10: #include <sys/reg.h>
11: #include <sys/con.h>
12: #include <sys/devices.h>
13: #include <sys/errno.h>
14: #include <sys/stat.h>
15: #include <sys/tty.h>
16: #include <signal.h>
17: #include <sys/sched.h>
18: #include <sys/silo.h>
19:
20: #define SPC 0376 /* Special encoding */
21: #define XXX 0377 /* Non-character */
22: #define KBDATA 0x60 /* Keyboard data */
23: #define KBCTRL 0x61 /* Keyboard control */
24: #define KBFLAG 0x80 /* Keyboard reset flag */
25: #define LEDCMD 0xED /* status indicator command */
26: #define KBACK 0xFA /* status indicator acknowledge */
27: #define EXTENDED0 0xE0 /* extended key seq initiator */
28: #define EXTENDED1 0xE1 /* extended key seq initiator */
29:
30: #define KEYUP 0x80 /* Key up change */
31: #define KEYSC 0x7F /* Key scan code mask */
32: #define LSHIFT 0x2A-1 /* Left shift key */
33: #define LSHIFTA 0x2B-1 /* Alternate left-shift key */
34: #define RSHIFT 0x36-1 /* Right shift key */
35: #define CTRL 0x1D-1 /* Control key */
36: /*-- #define CAPLOCK 0x1D-1 --*/ /* Control key */
37: #define ALT 0x38-1 /* Alt key or ALT GR */
38: #define CAPLOCK 0x3A-1 /* Caps lock key */
39: /*-- #define CTRL 0x3A-1 --*/ /* Caps lock key */
40: #define NUMLOCK 0x45-1 /* Numeric lock key */
41: #define DELETE 0x53-1 /* Del, as in CTRL-ALT-DEL */
42: #define BACKSP 0x0E-1 /* Back space */
43: #define SCRLOCK 0x46-1 /* Scroll lock */
44:
45: /* Shift flags */
46: #define SRS 0x01 /* Right shift key on */
47: #define SLS 0x02 /* Left shift key on */
48: #define CTS 0x04 /* Ctrl key on */
49: #define ALS 0x08 /* Alt key on */
50: #define CPLS 0x10 /* Caps lock on */
51: #define NMLS 0x20 /* Num lock on */
52: #define AKPS 0x40 /* Alternate keypad shift */
53: #define SHFT 0x80 /* Shift key flag */
54: #define AGS 0x100 /* Alt Graphics on */
55:
56: /* Function key information */
57: #define NFKEY 50 /* Number of settable functions */
58: #define NFCHAR 150 /* Number of characters settable */
59: #define NFBUF (NFKEY*2+NFCHAR+1) /* Size of buffer */
60:
61: #define ESCAPE_CHAR '\x1B'
62: #define ESCAPE_STRING "\x1B"
63: #define HEXFF_STRING "\xFF"
64: #define DELETE_STRING "\x7F"
65:
66: /*
67: * Functions.
68: */
69: int isrint();
70: int istime();
71: void isbatch();
72: int mmstart();
73: int isopen();
74: int isclose();
75: int isread();
76: int mmwrite();
77: int isioctl();
78: void mmwatch();
79: int isload();
80: int isuload();
81: int ispoll();
82: int nulldev();
83: int nonedev();
84:
85: /*
86: * Configuration table.
87: */
88: CON iscon ={
89: DFCHR|DFPOL, /* Flags */
90: KB_MAJOR, /* Major index */
91: isopen, /* Open */
92: isclose, /* Close */
93: nulldev, /* Block */
94: isread, /* Read */
95: mmwrite, /* Write */
96: isioctl, /* Ioctl */
97: nulldev, /* Powerfail */
98: mmwatch, /* Timeout */
99: isload, /* Load */
100: isuload, /* Unload */
101: ispoll /* Poll */
102: };
103:
104: /*
105: * Flag indicating turbo machine.
106: */
107: int isturbo = 0;
108:
109: /*
110: * Terminal structure.
111: */
112: TTY istty = {
113: {0}, {0}, 0, mmstart, NULL, 0, 0
114: };
115:
116: static silo_t in_silo;
117:
118: /*
119: * State variables.
120: */
121: int islock; /* Keyboard locked flag */
122: int isbusy; /* Raw input conversion busy */
123: static short shift; /* Overall shift state */
124: static char scroll; /* Scroll lock state */
125: static char lshift = LSHIFT; /* Left shift alternate state */
126: static char isfbuf[NFBUF]; /* Function key values */
127: static char *isfval[NFKEY]; /* Function key string pointers */
128: static int ledcmd; /* LED update command flag */
129: static int extended; /* extended key scan count */
130: static char extmode; /* use extended mode for this key */
131: static char ext0seen; /* 0xE0 prefix seen */
132: static int xlate = 1; /* scan code translation flag */
133:
134: /*
135: * Tables for converting key code to ASCII.
136: * lmaptab specifies unshifted conversion,
137: * umaptab specifies shifted conversion,
138: * smaptab specifies the shift states which are active.
139: * An entry of XXX says the key is dead.
140: * An entry of SPC requires further processing.
141: *
142: * Key codes:
143: * ESC .. <- == 1 .. 14
144: * -> .. \n == 15 .. 28
145: * CTRL .. ` == 29 .. 41
146: * ^Shift .. PrtSc == 42 .. 55
147: * ALT .. CapsLock == 56 .. 58
148: * F1 .. F10 == 59 .. 68
149: * NumLock .. Del == 69 .. 83
150: * ISO, F11, F12 == 86 .. 88
151: */
152: unsigned char agmaptab[] ={ /* Alt Gr */
153: XXX, XXX,'\375','\374',XXX, XXX, XXX, /* 1 - 7 */
154: '{', '[', ']', '}', '\\', XXX, XXX, XXX, /* 8 - 15 */
155: '@', XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 16 - 23 */
156: XXX, XXX, XXX, '~', XXX, XXX, XXX, XXX, /* 24 - 31 */
157: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 32 - 39 */
158: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 40 - 47 */
159: XXX, XXX,'\346', XXX, XXX, XXX, XXX, XXX, /* 48 - 55 */
160: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 56 - 63 */
161: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 64 - 71 */
162: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 72 - 79 */
163: XXX, XXX, XXX, XXX, XXX, XXX, '|', XXX, /* 80 - 87 */
164: XXX /* 88 */
165: };
166:
167: static unsigned char lmaptab[] ={
168: ESCAPE_CHAR, '1', '2', '3', '4', '5', '6', /* 1 - 7 */
169: '7', '8', '9', '0','\341','\'', '\b', '\t', /* 8 - 15 */
170: 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* 16 - 23 */
171: 'o', 'p','\201', '+', '\r', XXX, 'a', 's', /* 24 - 31 */
172: 'd', 'f', 'g', 'h', 'j', 'k', 'l','\224', /* 32 - 39 */
173: '\204','^', XXX, '#', 'y', 'x', 'c', 'v', /* 40 - 47 */
174: 'b', 'n', 'm', ',', '.', SPC, XXX, SPC, /* 48 - 55 */
175: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */
176: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */
177: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */
178: SPC, SPC, SPC, SPC, XXX, XXX, '<', XXX, /* 80 - 87 */
179: XXX /* 88 */
180: };
181:
182: static unsigned char umaptab[] ={
183: ESCAPE_CHAR, '!', '"','\025', '$', '%', '&', /* 1 - 7 */
184: '/', '(', ')', '=', '?', '`', '\b', SPC, /* 8 - 15 */
185: 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', /* 16 - 23 */
186: 'O', 'P','\232', '*', '\r', XXX, 'A', 'S', /* 24 - 31 */
187: 'D', 'F', 'G', 'H', 'J', 'K', 'L','\231', /* 32 - 39 */
188: '\216','\370',XXX,'\'', 'Y', 'X', 'C', 'V', /* 40 - 47 */
189: 'B', 'N', 'M', ';', ':', SPC, XXX, SPC, /* 48 - 55 */
190: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */
191: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */
192: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */
193: SPC, SPC, SPC, SPC, XXX, XXX, '>', XXX, /* 80 - 87 */
194: XXX /* 88 */
195: };
196:
197: #define SS0 0 /* No shift */
198: #define SS1 (SLS|SRS|CTS) /* Shift, Ctrl */
199: #define SES (SLS|SRS) /* Shift */
200: #define LET (SLS|SRS|CPLS|CTS) /* Shift, Caps, Ctrl */
201: #define KEY (SLS|SRS|NMLS|AKPS) /* Shift, Num, Alt keypad */
202:
203: static unsigned char smaptab[] ={
204: SS0, SES, SS1, SES, SES, SES, SS1, /* 1 - 7 */
205: SES, SES, SES, SES, SS1, SES, CTS, SES, /* 8 - 15 */
206: LET, LET, LET, LET, LET, LET, LET, LET, /* 16 - 23 */
207: LET, LET, SS1, SS1, CTS, SHFT, LET, LET, /* 24 - 31 */
208: LET, LET, LET, LET, LET, LET, LET, SES, /* 32 - 39 */
209: SES, SS1, SHFT, SS1, LET, LET, LET, LET, /* 40 - 47 */
210: LET, LET, LET, SES, SES, SES, SHFT, SES, /* 48 - 55 */
211: SHFT, SS1, SHFT, SS1, SS1, SS1, SS1, SS1, /* 56 - 63 */
212: SS1, SS1, SS1, SS1, SS1, SHFT, KEY, KEY, /* 64 - 71 */
213: KEY, KEY, SS0, KEY, KEY, KEY, SS0, KEY, /* 72 - 79 */
214: KEY, KEY, KEY, KEY, SS0, SS0, SES, SS0, /* 80 - 87 */
215: SS0
216: };
217:
218: /*
219: * Load entry point.
220: * Do reset the keyboard because it gets terribly munged
221: * if you type during the boot.
222: */
223: isload()
224: {
225: register short i;/* was: int i .. the loop below is hardly portable */
226:
227: /*
228: * Reset keyboard if NOT an XT turbo.
229: */
230: if ( ! isturbo ) {
231: outb(KBCTRL, 0x0C); /* Clock low */
232: for (i = 10582; --i >= 0; ); /* For 20ms */
233: outb(KBCTRL, 0xCC); /* Clock high */
234: for (i = 0; --i != 0; )
235: ;
236: i = inb(KBDATA);
237: outb(KBCTRL, 0xCC); /* Clear keyboard */
238: outb(KBCTRL, 0x4D); /* Enable keyboard */
239: }
240:
241: /*
242: * Enable mmwatch() invocation every second.
243: */
244: drvl[KB_MAJOR].d_time = 1;
245:
246: /*
247: * Seize keyboard interrupt.
248: */
249: setivec(1, isrint);
250:
251: /*
252: * Initialize video display.
253: */
254: mmstart( &istty );
255: }
256:
257: /*
258: * Unload entry point.
259: */
260: isuload()
261: {
262: clrivec(1);
263: }
264:
265: /*
266: * Default function key strings (terminated by -1 [\377])
267: */
268: static char *deffuncs[] = {
269: /* Normal keypresses */
270: ESCAPE_STRING "[M" HEXFF_STRING, /* F1 */
271: ESCAPE_STRING "[N" HEXFF_STRING, /* F2 */
272: ESCAPE_STRING "[O" HEXFF_STRING, /* F3 */
273: ESCAPE_STRING "[P" HEXFF_STRING, /* F4 */
274: ESCAPE_STRING "[Q" HEXFF_STRING, /* F5 */
275: ESCAPE_STRING "[R" HEXFF_STRING, /* F6 */
276: ESCAPE_STRING "[S" HEXFF_STRING, /* F7 */
277: ESCAPE_STRING "[T" HEXFF_STRING, /* F8 */
278: ESCAPE_STRING "[U" HEXFF_STRING, /* F9 */
279: ESCAPE_STRING "[V" HEXFF_STRING, /* F10 - historical value */
280:
281: /* Shifted keypresses */
282: ESCAPE_STRING "[Y" HEXFF_STRING, /* sF1 */
283: ESCAPE_STRING "[Z" HEXFF_STRING, /* sF2 */
284: ESCAPE_STRING "[a" HEXFF_STRING, /* sF3 */
285: ESCAPE_STRING "[b" HEXFF_STRING, /* sF4 */
286: ESCAPE_STRING "[c" HEXFF_STRING, /* sF5 */
287: ESCAPE_STRING "[d" HEXFF_STRING, /* sF6 */
288: ESCAPE_STRING "[e" HEXFF_STRING, /* sF7 */
289: ESCAPE_STRING "[f" HEXFF_STRING, /* sF8 */
290: ESCAPE_STRING "[g" HEXFF_STRING, /* sF9 */
291: ESCAPE_STRING "[h" HEXFF_STRING, /* sF10 */
292:
293: /* Ctrl-ed keypresses */
294: ESCAPE_STRING "[k" HEXFF_STRING, /* cF1 */
295: ESCAPE_STRING "[l" HEXFF_STRING, /* cF2 */
296: ESCAPE_STRING "[m" HEXFF_STRING, /* cF3 */
297: ESCAPE_STRING "[n" HEXFF_STRING, /* cF4 */
298: ESCAPE_STRING "[o" HEXFF_STRING, /* cF5 */
299: ESCAPE_STRING "[p" HEXFF_STRING, /* cF6 */
300: ESCAPE_STRING "[q" HEXFF_STRING, /* cF7 */
301: ESCAPE_STRING "[r" HEXFF_STRING, /* cF8 */
302: ESCAPE_STRING "[s" HEXFF_STRING, /* cF9 */
303: ESCAPE_STRING "[t" HEXFF_STRING, /* cF10 */
304:
305: /* Ctrl-Shift-ed Keypresses ;) */
306: ESCAPE_STRING "[w" HEXFF_STRING, /* csF1 */
307: ESCAPE_STRING "[x" HEXFF_STRING, /* csF2 */
308: ESCAPE_STRING "[y" HEXFF_STRING, /* csF3 */
309: ESCAPE_STRING "[z" HEXFF_STRING, /* csF4 */
310: ESCAPE_STRING "[@" HEXFF_STRING, /* csF5 */
311: ESCAPE_STRING "[[" HEXFF_STRING, /* csF6 */
312: ESCAPE_STRING "[\\" HEXFF_STRING, /* csF7 */
313: ESCAPE_STRING "[]" HEXFF_STRING, /* csF8 */
314: ESCAPE_STRING "[^" HEXFF_STRING, /* csF9 */
315: ESCAPE_STRING "[_" HEXFF_STRING, /* csF10 */
316:
317: /* Alt keys -- use original 83 key settings since these
318: are not defined with a default for virtual terminals */
319: ESCAPE_STRING "[1y" HEXFF_STRING, /* aF1 */
320: ESCAPE_STRING "[2y" HEXFF_STRING, /* aF2 */
321: ESCAPE_STRING "[3y" HEXFF_STRING, /* aF3 */
322: ESCAPE_STRING "[4y" HEXFF_STRING, /* aF4 */
323: ESCAPE_STRING "[5y" HEXFF_STRING, /* aF5 */
324: ESCAPE_STRING "[6y" HEXFF_STRING, /* aF6 */
325: ESCAPE_STRING "[7y" HEXFF_STRING, /* aF7 */
326: ESCAPE_STRING "[8y" HEXFF_STRING, /* aF8 */
327: ESCAPE_STRING "[9y" HEXFF_STRING, /* aF9 */
328: ESCAPE_STRING "[0y" HEXFF_STRING /* aF10 */
329: };
330:
331: /*
332: * Open routine.
333: */
334: isopen(dev, mode)
335: dev_t dev;
336: unsigned int mode;
337: {
338: register int s;
339:
340: if (minor(dev) != 0) {
341: u.u_error = ENXIO;
342: return;
343: }
344: if ((istty.t_flags&T_EXCL)!=0 && super()==0) {
345: u.u_error = ENODEV;
346: return;
347: }
348: ttsetgrp(&istty, dev, mode);
349:
350: s = sphi();
351: if (istty.t_open++ == 0)
352: { initkeys(); /* init function keys */
353: istty.t_flags = T_CARR; /* indicate "carrier" */
354: ttopen(&istty);
355: }
356: spl(s);
357: updleds(); /* update keyboard status LEDS */
358: }
359:
360: /* Init function keys */
361: initkeys()
362: { register int i;
363: register char *cp1, *cp2;
364:
365: for (i=0; i<NFKEY; i++)
366: isfval[i] = 0; /* clear function key buffer */
367: cp2 = isfbuf; /* pointer to key buffer */
368: for (i=0; i<NFKEY; i++)
369: { isfval[i] = cp2; /* save pointer to key string */
370: cp1 = deffuncs[i]; /* get init string pointer */
371: while ((*cp2++ = *cp1++) != -1) /* copy key data */
372: if (cp2 >= &isfbuf[NFBUF-3]) /* overflow? */
373: return;
374: }
375: }
376:
377: /*
378: * Close a tty.
379: */
380: isclose(dev)
381: {
382: register int s;
383:
384: s = sphi();
385: if (--istty.t_open == 0)
386: { s = sphi();
387: ttclose(&istty);
388: spl(s);
389: }
390: }
391:
392: /*
393: * Read routine.
394: */
395: isread(dev, iop)
396: dev_t dev;
397: IO *iop;
398: {
399: ttread(&istty, iop, 0);
400: if (istty.t_oq.cq_cc)
401: mmtime(&istty);
402: }
403:
404: /*
405: * Ioctl routine.
406: */
407: /*
408: * special struct for the KDMAPDISP call
409: */
410:
411: #define KDMAPDISP (('K' << 8) | 2) /* map display into user space */
412: #define KDSKBMODE (('K' << 8) | 6) /* turn scan code xlate on/off */
413: #define KDMEMDISP (('K' << 8) | 7) /* dump byte of virt/phys mem */
414: #define KDENABIO (('K' << 8) | 60) /* enable IO */
415: #define KIOCSOUND (('K' << 8) | 63) /* start sound generation */
416: #define KDSETLED (('K' << 8) | 66) /* set leds */
417:
418: #define TIMER_CTL 0x43 /* Timer control */
419: #define TIMER_CNT 0x42 /* Timer counter */
420: #define SPEAKER_CTL 0x61 /* Speaker control */
421:
422: struct kd_memloc {
423: char *vaddr; /* virtual address to map to */
424: char *physaddr; /* physical address to map to */
425: long length; /* size in bytes to map */
426: long ioflg; /* enable I/O addresses if non-zero */
427: };
428:
429: static TIM tp;
430: int
431: kbstate(action)
432: int action;
433: {
434: int i;
435: if (action == 1) {
436: timeout(&tp,20,kbstate,2);
437: outb(KBCTRL, 0xCC); /* Clock high */
438: }
439: if (action == 2) {
440: i = inb(KBDATA);
441: outb(KBCTRL, 0xCC); /* Clear keyboard */
442: outb(KBCTRL, 0x4D); /* Enable keyboard */
443: }
444: }
445:
446: static int X11led;
447:
448: isioctl(dev, com, vec)
449: dev_t dev;
450: struct sgttyb *vec;
451: {
452: register int s;
453:
454: switch(com) {
455: #define KDDEBUG 0
456: #if KDDEBUG
457: case KDMEMDISP:
458: {
459: struct kd_memloc* mem;
460: unsigned char ub, pb;
461: mem = vec;
462: pxcopy( mem->physaddr, &pb, 1, SEG_386_KD );
463: ub = getubd( mem->vaddr );
464: printf( "User's byte %x(%x), Physical byte %x, Addresses %x %x\n",
465: mem->ioflg, ub, pb, mem->vaddr, mem->physaddr );
466: goto ioc_done;;
467: }
468: #endif
469: case KDMAPDISP:
470: {
471: struct kd_memloc* mem;
472: mem = vec;
473: #if KDDEBUG
474: printf( "mapPhysUser(%x, %x, %x) = %d\n",
475: mem->vaddr, mem->physaddr, mem->length,
476: #endif
477: mapPhysUser(mem->vaddr, mem->physaddr, mem->length)
478: #if KDDEBUG
479: )
480: #endif
481: ;
482: }
483: case KDENABIO:
484: {
485: int i;
486: for (i = 0 ; i < 64 ; i++ )
487: iomapAnd(0,i);
488: goto ioc_done;;
489: }
490: case KIOCSOUND:
491: {
492: if (vec) {
493: outb(TIMER_CTL, 0xB6);
494: outb(TIMER_CNT, (int)vec&0xFF);
495: outb(TIMER_CNT, (int)vec>>8);
496: outb(SPEAKER_CTL, inb(SPEAKER_CTL) | 03); /* Turn speaker on */
497: }
498: else
499: outb(SPEAKER_CTL, inb(SPEAKER_CTL) & ~03 ); /* speaker off */
500: goto ioc_done;;
501: }
502: case KDSKBMODE:
503: {
504: outb(KBCTRL, 0x0C); /* Clock low */
505: timeout(&tp,3,kbstate,1); /* wait about 20-30ms */
506: xlate = (int)vec;
507: goto ioc_done;;
508: }
509: case KDSETLED:
510: {
511: X11led = (int)vec;
512: updleds();
513: goto ioc_done;;
514: }
515:
516: case TIOCSETF:
517: case TIOCGETF:
518: isfunction(com, (char *)vec);
519: goto ioc_done;;
520: case TIOCSHIFT: /* switch left-SHIFT and "\" */
521: lshift = LSHIFTA; /* alternate values */
522: lmaptab[41] = '\\';
523: lmaptab[42] = XXX;
524: umaptab[41] = '|';
525: umaptab[42] = XXX;
526: smaptab[41] = SS1;
527: smaptab[42] = SHFT;
528: goto ioc_done;;
529: case TIOCCSHIFT: /* normal (default) left-SHIFT and "\" */
530: lshift = LSHIFT; /* normal values */
531: lmaptab[41] = XXX;
532: lmaptab[42] = '\\';
533: umaptab[41] = XXX;
534: umaptab[42] = '|';
535: smaptab[41] = SHFT;
536: smaptab[42] = SS1;
537: goto ioc_done;;
538: }
539: s = sphi();
540: ttioctl(&istty, com, vec);
541: spl(s);
542:
543: ioc_done:
544: return;
545: }
546:
547: /*
548: * Set and receive the function keys.
549: */
550: isfunction(c, v)
551: int c;
552: char *v;
553: {
554: register char *cp;
555: register int i;
556:
557: if (c == TIOCGETF) {
558: for (cp = isfbuf; cp < &isfbuf[NFBUF]; cp++)
559: putubd(v++, *cp);
560: } else {
561: for (i=0; i<NFKEY; i++) /* zap current settings */
562: isfval[i] = 0;
563: cp = isfbuf; /* pointer to key buffer */
564: for (i=0; i<NFKEY; i++) {
565: isfval[i] = cp; /* save pointer to key string */
566: while ((*cp++ = getubd(v++)) != -1) /* copy key data */
567: if (cp >= &isfbuf[NFBUF-3]) /* overflow? */
568: return;
569: }
570: }
571: }
572:
573:
574: /*
575: * Poll routine.
576: */
577: ispoll( dev, ev, msec )
578: dev_t dev;
579: int ev;
580: int msec;
581: {
582: return ttpoll(&istty, ev, msec);
583: }
584:
585: /*
586: * Receive interrupt.
587: */
588: isrint()
589: {
590: register int c;
591: register int s;
592: register int r;
593: int savests;
594: int update_leds = 0;
595:
596: /*
597: * Schedule raw input handler if not already active.
598: */
599: if ( isbusy == 0 ) {
600: isbusy = 1;
601: defer( isbatch, &istty );
602: }
603:
604: /*
605: * Pull character from the data
606: * port. Pulse the KBFLAG in the control
607: * port to reset the data buffer.
608: */
609: r = inb(KBDATA) & 0xFF;
610: c = inb(KBCTRL);
611: outb(KBCTRL, c|KBFLAG);
612: outb(KBCTRL, c);
613: if (!xlate) {
614: if (ledcmd) {
615: ledcmd = 0;
616: if (r == KBACK) { /* output to status LEDS */
617: outb(KBDATA, X11led);
618: return;
619: }
620: }
621: isin(r);
622: return;
623: }
624:
625: #if KBDEBUG
626: printf("kbd: 0x%x ", r); /* print scan code/direction */
627: #endif
628: if (ledcmd) {
629: ledcmd = 0;
630: if (r == KBACK) { /* output to status LEDS */
631: c = scroll & 1;
632: if (shift & NMLS)
633: c |= 2;
634: if (shift & CPLS)
635: c |= 4;
636: outb(KBDATA, c);
637: }
638: return;
639: }
640: if (extended > 0) { /* if multi-character seq, */
641: --extended; /* ... ignore this char */
642: return;
643: }
644: switch (r) {
645: case EXTENDED0: /* 0xE0 prefix found */
646: ext0seen = 1;
647: return;
648: case EXTENDED1: /* ignore extended sequences */
649: extended = 5;
650: return;
651: case 0xFF: /* Overrun */
652: return;
653: }
654:
655: if (ext0seen) {
656: ext0seen = 0;
657: extmode = 1;
658: } else
659: extmode = 0;
660:
661: c = (r & KEYSC) - 1;
662: /*
663: * Check for reset.
664: */
665: if ((r&KEYUP) == 0 && c == DELETE && (shift&(CTS|ALS)) == (CTS|ALS))
666: boot();
667:
668: /*
669: * Track "shift" keys.
670: */
671: s = smaptab[c];
672: if (s&SHFT) {
673: if (r&KEYUP) { /* "shift" released */
674: if (c == RSHIFT)
675: shift &= ~SRS;
676: else if (c == lshift)
677: shift &= ~SLS;
678: else if (c == CTRL)
679: shift &= ~CTS;
680: else if (c == ALT)
681: shift &= extmode ? ~AGS : ~ALS;
682: } else { /* "shift" pressed */
683: if (c == lshift)
684: shift |= SLS;
685: else if (c == RSHIFT)
686: shift |= SRS;
687: else if (c == CTRL)
688: shift |= CTS;
689: else if (c == ALT)
690: shift |= extmode ? AGS : ALS;
691: else if (c == CAPLOCK) {
692: shift ^= CPLS; /* toggle cap lock */
693: updleds();
694: } else if (c == NUMLOCK) {
695: shift ^= NMLS; /* toggle num lock */
696: updleds();
697: }
698: }
699: return;
700: }
701:
702: /*
703: * No other key up codes of interest.
704: */
705: if (r&KEYUP)
706: return;
707:
708: /*
709: * If the tty is not open the character is
710: * just tossed away.
711: */
712: if (istty.t_open == 0)
713: return;
714:
715: /*
716: * Map character, based on the
717: * current state of the shift, control, alt graphics,
718: * meta (ALT) and lock flags.
719: */
720: if (shift & AGS) /* Alt Graphics ? */
721: c = agmaptab[c];
722: else if (shift & CTS) {
723: if (s == CTS) /* Map Ctrl (BS | NL) */
724: c = (c == BACKSP) ? 0x7F : 0x0A;
725: else if (s==SS1 || s==LET) { /* Normal Ctrl map */
726: if((c = umaptab[c]) != SPC)
727: c &= 0x1F; /* Clear bits 5-6 */
728: } else
729: return; /* Ignore this char */
730: } else if (s &= shift) {
731: if (shift & SES) { /* if shift on */
732: if (s & (CPLS|NMLS)) /* if caps/num lock */
733: c = lmaptab[c]; /* use unshifted */
734: else
735: c = umaptab[c]; /* use shifted */
736: } else { /* if shift not on */
737: if (s & (CPLS|NMLS)) /* if caps/num lock */
738: c = umaptab[c]; /* use shifted */
739: else
740: c = lmaptab[c]; /* use unshifted */
741: }
742: } else
743: c = lmaptab[c]; /* use unshifted */
744:
745: /*
746: * Act on character.
747: */
748: if (c == XXX)
749: return; /* char to ignore */
750:
751: if (c != SPC) { /* not special char? */
752: if (shift & ALS) /* ALT (meta bit)? */
753: c |= 0x80; /* set meta */
754: isin(c); /* send the char */
755: } else
756: update_leds += isspecial(r); /* special chars */
757: if (update_leds) {
758: savests = sphi();
759: outb(KBDATA, LEDCMD);
760: ledcmd = 1;
761: spl(savests);
762: }
763: }
764:
765: /*
766: * Handle special input sequences.
767: * The character passed is the key number.
768: *
769: * The keypad is translated by the following table,
770: * the first entry is the normal sequence, the second the shifted,
771: * and the third the alternate keypad sequence.
772: */
773: static char *keypad[][3] = {
774: { ESCAPE_STRING "[H", "7", ESCAPE_STRING "?w" }, /* 71 */
775: { ESCAPE_STRING "[A", "8", ESCAPE_STRING "?x" }, /* 72 */
776: { ESCAPE_STRING "[I", "9", ESCAPE_STRING "?y" }, /* 73 */
777: { ESCAPE_STRING "[D", "4", ESCAPE_STRING "?t" }, /* 75 */
778: { ESCAPE_STRING "7", "5", ESCAPE_STRING "?u" }, /* 76 */
779: { ESCAPE_STRING "[C", "6", ESCAPE_STRING "?v" }, /* 77 */
780: { ESCAPE_STRING "[F", "1", ESCAPE_STRING "?q" }, /* 79 */
781: { ESCAPE_STRING "[B", "2", ESCAPE_STRING "?r" }, /* 80 */
782: { ESCAPE_STRING "[G", "3", ESCAPE_STRING "?s" }, /* 81 */
783: { ESCAPE_STRING "[L", "0", ESCAPE_STRING "?p" }, /* 82 */
784: { DELETE_STRING , ".", ESCAPE_STRING "?n" } /* 83 */
785: };
786:
787: isspecial(c)
788: int c;
789: {
790: register char *cp;
791: register int s;
792: int update_leds = 0;
793:
794: cp = 0;
795:
796: switch (c) {
797: case 15: /* cursor back tab */
798: cp = ESCAPE_STRING "[Z";
799: break;
800: case 53:
801: if (extmode)
802: cp = "/";
803: else if (shift & SES)
804: cp = "_";
805: else
806: cp = "-";
807: break;
808: case 55: /* ignore PrtScr */
809: if (!extmode)
810: cp = "*";
811: break;
812: case 59: case 60: case 61: case 62: case 63: /* Function keys */
813: case 64: case 65: case 66: case 67: case 68:
814: /* offset to function string */
815: if (shift & ALS)
816: cp = isfval[c-19]; /* alt-Fx */
817: else { if ((shift & (SES)) && (shift & CTS)) /* CTRL-Shift-Fx */
818: cp = isfval[c-29];
819: else { if (shift & CTS) /* CTRL-Fx */
820: cp = isfval[c-39];
821: else { if(shift & (SES)) /* Shift-Fx */
822: cp = isfval[c-49];
823: else cp = isfval[c-59]; /* Plain Fx */
824: }
825: }
826: }
827: break;
828:
829: case 70: /* Scroll Lock -- stop/start output */
830: {
831: static char cbuf[2];
832:
833: cp = &cbuf[0]; /* working buffer */
834: if (!(istty.t_sgttyb.sg_flags&RAWIN)) { /* not if in RAW mode */
835: ++update_leds;
836: if (istty.t_flags & T_STOP) { /* output stopped? */
837: cbuf[0] = istty.t_tchars.t_startc; /* start it */
838: scroll = 0;
839: } else {
840: cbuf[0] = istty.t_tchars.t_stopc; /* stop output */
841: scroll = 1;
842: }
843: }
844: break;
845: }
846:
847: case 79: /* 1/End */
848: case 80: /* 2/DOWN */
849: case 81: /* 3/PgDn */
850: case 82: /* 0/Ins */
851: case 83: /* ./Del */
852: --c; /* adjust code */
853: case 75: /* 4/LEFT */
854: case 76: /* 5 */
855: case 77: /* 6/RIGHT */
856: --c; /* adjust code */
857: case 71: /* 7/Home/Clear */
858: case 72: /* 8/UP */
859: case 73: /* 9/PgUp */
860: s = 0; /* start off with normal keypad */
861: if (shift & NMLS) /* num lock? */
862: s = 1; /* set shift pad */
863: if (shift & SES) /* shift? */
864: s ^= 1; /* toggle shift pad */
865: if (shift & AKPS) /* alternate pad? */
866: s = 2; /* set alternate pad */
867: if (extmode) /* not from keypad? */
868: s = 0; /* force normal sequence */
869: cp = keypad[c-71][s]; /* get keypad value */
870: break;
871: }
872: if (cp) /* send string */
873: while ((*cp != 0) && (*cp != -1))
874: isin( *cp++ & 0377 );
875: return update_leds;
876: }
877:
878: /**
879: *
880: * void
881: * ismmfunc( c ) -- process keyboard related output escape sequences
882: * char c;
883: */
884: void
885: ismmfunc(c)
886: register int c;
887: {
888: switch (c) {
889: case 't': /* Enter numlock */
890: shift |= NMLS;
891: updleds(); /* update LED status */
892: break;
893: case 'u': /* Leave numlock */
894: shift &= ~NMLS;
895: updleds(); /* update LED status */
896: break;
897: case '=': /* Enter alternate keypad */
898: shift |= AKPS;
899: break;
900: case '>': /* Exit alternate keypad */
901: shift &= ~AKPS;
902: break;
903: case 'c': /* Reset terminal */
904: islock = 0;
905: shift = 0;
906: initkeys();
907: updleds(); /* update LED status */
908: break;
909: }
910: }
911:
912: /**
913: *
914: * void
915: * isin( c ) -- append character to raw input silo
916: * char c;
917: */
918: static
919: isin( c )
920: register int c;
921: {
922: int cache_it = 1;
923: TTY * tp = &istty;
924:
925: /*
926: * If using software incoming flow control, process and
927: * discard t_stopc and t_startc.
928: */
929: if (_IS_IXON_MODE (tp)) {
930: #if _I386
931: if (_IS_START_CHAR (tp, c) ||
932: (_IS_IXANY_MODE (tp) && (tp->t_flags & T_STOP) != 0)) {
933: tp->t_flags &= ~(T_STOP | T_XSTOP);
934: ttstart(tp);
935: cache_it = 0;
936: } else if (_IS_STOP_CHAR (tp, c)) {
937: if ((tp->t_flags&T_STOP) == 0)
938: tp->t_flags |= (T_STOP | T_XSTOP);
939: cache_it = 0;
940: }
941: #else
942: if (_IS_STOP_CHAR (tp, c)) {
943: if ((tp->t_flags&T_STOP) == 0)
944: tp->t_flags |= T_STOP;
945: cache_it = 0;
946: }
947: if (_IS_START_CHAR (tp, c)) {
948: tp->t_flags &= ~T_STOP;
949: ttstart (tp);
950: cache_it = 0;
951: }
952: #endif
953: }
954:
955: /*
956: * Cache received character.
957: */
958: if (cache_it) {
959: in_silo.si_buf[ in_silo.si_ix ] = c;
960:
961: if ( ++in_silo.si_ix >= sizeof(in_silo.si_buf) )
962: in_silo.si_ix = 0;
963: }
964: }
965:
966: /**
967: *
968: * void
969: * isbatch() -- raw input conversion routine
970: *
971: * Action: Enable the video display.
972: * Canonize the raw input silo.
973: *
974: * Notes: isbatch() was scheduled as a deferred process by isrint().
975: */
976: static void
977: isbatch( tp )
978: register TTY * tp;
979: {
980: register int c;
981: static int lastc;
982:
983: /*
984: * Ensure video display is enabled.
985: */
986: mm_von();
987:
988: isbusy = 0;
989:
990: /*
991: * Process all cached characters.
992: */
993: while ( in_silo.si_ix != in_silo.si_ox ) {
994:
995: /*
996: * Get next cached char.
997: */
998: c = in_silo.si_buf[ in_silo.si_ox ];
999:
1000: if ( in_silo.si_ox >= sizeof(in_silo.si_buf) - 1 )
1001: in_silo.si_ox = 0;
1002: else
1003: in_silo.si_ox++;
1004:
1005: if (islock == 0 || _IS_INTERRUPT_CHAR (tp, c) ||
1006: _IS_QUIT_CHAR (tp, c)) {
1007: ttin (tp, c);
1008: } else if (c == 'b' && lastc == ESCAPE_CHAR) {
1009: islock = 0;
1010: ttin (tp, lastc);
1011: ttin (tp, c);
1012: } else if (c == 'c' && lastc == ESCAPE_CHAR) {
1013: ttin (tp, lastc);
1014: ttin (tp, c);
1015: } else
1016: putchar ('\a');
1017:
1018: lastc = c;
1019: }
1020: }
1021:
1022: /*
1023: * update the keyboard status LEDS
1024: */
1025: updleds()
1026: {
1027: int s;
1028:
1029: s = sphi();
1030: outb(KBDATA, LEDCMD);
1031: ledcmd = 1;
1032: spl(s);
1033: }
1034:
1035: /*
1036: * unlock the scroll in case an interrupt character is received
1037: */
1038: kbunscroll()
1039: {
1040: scroll = 0;
1041: updleds();
1042: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.