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