|
|
1.1 root 1: /*
2: * io.386/vtkb.c
3: *
4: * virtual console, nonloadable keyboard driver
5: *
6: * Revised: Fri Aug 6 15:21:14 1993 CDT
7: */
8:
9: /*
10: * Functions in this module:
11: * isload() isuload() isopen() initkeys()
12: * isclose() isread() kbstate() isioctl()
13: * isfunction() ispoll() ismmfunc() isin()
14: * isbatch() updleds() kbunscroll() VTttyinit()
15: * vtdatainit() vtindex() isvtswitch() vtdeactivate()
16: * vtactivate() updterminal() vtkey_to_dev() isrint()
17: * isspecial()
18: */
19:
20: /*************************Included Files*********************************/
21:
22: #include <sys/coherent.h>
23: #include <sys/con.h>
24: #include <sys/devices.h>
25: #include <sys/errno.h>
26: #include <sys/stat.h>
27: #include <sys/tty.h>
28: #include <signal.h>
29: #include <sys/sched.h>
30: #include <sys/silo.h>
31: #include <sys/kb.h>
32: #include <sys/vt.h>
33:
34: /*************************Hardware Defines*****************************/
35:
36: #define ISVEC 1 /* Keyboard interrupt vector */
37: #define DEBUG 0
38:
39: #define SPC 0376 /* Special encoding */
40: #define XXX 0377 /* Non-character */
41: #define KBDATA 0x60 /* Keyboard data */
42: #define KBCTRL 0x61 /* Keyboard control */
43: #define KBFLAG 0x80 /* Keyboard reset flag */
44: #define LEDCMD 0xED /* status indicator command */
45: #define KBACK 0xFA /* status indicator acknowledge */
46: #define EXTENDED0 0xE0 /* extended key seq initiator */
47: #define EXTENDED1 0xE1 /* extended key seq initiator */
48:
49: #define KEYUP 0x80 /* Key up change */
50: #define KEYSC 0x7F /* Key scan code mask */
51: #define LSHIFT 0x2A-1 /* Left shift key */
52: #define LSHIFTA 0x2B-1 /* Alternate left-shift key */
53: #define RSHIFT 0x36-1 /* Right shift key */
54: #define CTRLkb 0x1D-1 /* Control key */
55: /*-- #define CAPLOCK 0x1D-1 --*/ /* Control key */
56: #define ALTkb 0x38-1 /* Alt key or ALT GR */
57: #define CAPLOCK 0x3A-1 /* Caps lock key */
58: /*-- #define CTRL 0x3A-1 --*/ /* Caps lock key */
59: #define NUMLOCK 0x45-1 /* Numeric lock key */
60: #define DELETE 0x53-1 /* Del, as in CTRL-ALT-DEL */
61: #define BACKSP 0x0E-1 /* Back space */
62: #define SCRLOCK 0x46-1 /* Scroll lock */
63:
64: /* Shift flags */
65: #define SRS 0x01 /* Right shift key on */
66: #define SLS 0x02 /* Left shift key on */
67: #define CTS 0x04 /* Ctrl key on */
68: #define ALS 0x08 /* Alt key on */
69: #define CPLS 0x10 /* Caps lock on */
70: #define NMLS 0x20 /* Num lock on */
71: #define AKPS 0x40 /* Alternate keypad shift */
72: #define SHFT 0x80 /* Shift key flag */
73: #define AGS 0x100 /* Alt Graphics on */
74:
75: /* Function key information */
76: #define NFKEY 50 /* Number of settable functions */
77: #define NFCHAR 150 /* Number of characters settable */
78: #define NFBUF (NFKEY*2+NFCHAR+1) /* Size of buffer */
79:
80:
81: /************************* Data Defines ******************************/
82:
83:
84: #define ESCAPE_CHAR '\x1B'
85: #define ESCAPE_STRING "\x1B"
86: #define HEXFF_STRING "\xFF"
87: #define DELETE_STRING "\x7F"
88:
89: #define SS0 0 /* No shift */
90: #define SS1 (SLS|SRS|CTS) /* Shift, Ctrl */
91: #define SES (SLS|SRS) /* Shift */
92: #define LET (SLS|SRS|CPLS|CTS) /* Shift, Caps, Ctrl */
93: #define KEY (SLS|SRS|NMLS|AKPS) /* Shift, Num, Alt keypad */
94:
95: #define KB_VIRTUAL 2
96: #define kb_lang_fr 4
97: #define kb_lang_de 8
98:
99:
100: /**************************** X Stuff ************************************/
101:
102: /*
103: * special struct for the KDMAPDISP call
104: */
105:
106: #define KDMAPDISP (('K' << 8) | 2) /* map display into user space */
107: #define KDSKBMODE (('K' << 8) | 6) /* turn scan code xlate on/off */
108: #define KDMEMDISP (('K' << 8) | 7) /* dump byte of virt/phys mem */
109: #define KDENABIO (('K' << 8) | 60) /* enable IO */
110: #define KIOCSOUND (('K' << 8) | 63) /* start sound generation */
111: #define KDSETLED (('K' << 8) | 66) /* set leds */
112:
113: #define TIMER_CTL 0x43 /* Timer control */
114: #define TIMER_CNT 0x42 /* Timer counter */
115: #define SPEAKER_CTL 0x61 /* Speaker control */
116:
117: struct kd_memloc {
118: char *vaddr; /* virtual address to map to */
119: char *physaddr; /* physical address to map to */
120: long length; /* size in bytes to map */
121: long ioflg; /* enable I/O addresses if non-zero */
122: };
123:
124:
125: /************************** Tables ************************************/
126:
127: /*
128: * Default function key strings (terminated by -1)
129: */
130: static char *deffuncs[] = {
131:
132: ESCAPE_STRING "[M" HEXFF_STRING, /* F1 */
133: ESCAPE_STRING "[N" HEXFF_STRING, /* F2 */
134: ESCAPE_STRING "[O" HEXFF_STRING, /* F3 */
135: ESCAPE_STRING "[P" HEXFF_STRING, /* F4 */
136: ESCAPE_STRING "[Q" HEXFF_STRING, /* F5 */
137: ESCAPE_STRING "[R" HEXFF_STRING, /* F6 */
138: ESCAPE_STRING "[S" HEXFF_STRING, /* F7 */
139: ESCAPE_STRING "[T" HEXFF_STRING, /* F8 */
140: ESCAPE_STRING "[U" HEXFF_STRING, /* F9 */
141: ESCAPE_STRING "[V" HEXFF_STRING, /* F10 - historical value */
142: /* No F11 or F12 on these keyboards */
143:
144: /* Shifted function keys */
145: ESCAPE_STRING "[Y" HEXFF_STRING, /* sF1 */
146: ESCAPE_STRING "[Z" HEXFF_STRING, /* sF2 */
147: ESCAPE_STRING "[a" HEXFF_STRING, /* sF3 */
148: ESCAPE_STRING "[b" HEXFF_STRING, /* sF4 */
149: ESCAPE_STRING "[c" HEXFF_STRING, /* sF5 */
150: ESCAPE_STRING "[d" HEXFF_STRING, /* sF6 */
151: ESCAPE_STRING "[e" HEXFF_STRING, /* sF7 */
152: ESCAPE_STRING "[f" HEXFF_STRING, /* sF8 */
153: ESCAPE_STRING "[g" HEXFF_STRING, /* sF9 */
154: ESCAPE_STRING "[h" HEXFF_STRING, /* sF10 */
155:
156: /* Ctrl-ed function keys */
157: ESCAPE_STRING "[k" HEXFF_STRING, /* cF1 */
158: ESCAPE_STRING "[l" HEXFF_STRING, /* cF2 */
159: ESCAPE_STRING "[m" HEXFF_STRING, /* cF3 */
160: ESCAPE_STRING "[n" HEXFF_STRING, /* cF4 */
161: ESCAPE_STRING "[o" HEXFF_STRING, /* cF5 */
162: ESCAPE_STRING "[p" HEXFF_STRING, /* cF6 */
163: ESCAPE_STRING "[q" HEXFF_STRING, /* cF7 */
164: ESCAPE_STRING "[r" HEXFF_STRING, /* cF8 */
165: ESCAPE_STRING "[s" HEXFF_STRING, /* cF9 */
166: ESCAPE_STRING "[t" HEXFF_STRING, /* cF10 */
167:
168: /* Ctrl-shifted function keys */
169: ESCAPE_STRING "[w" HEXFF_STRING, /* csF1 */
170: ESCAPE_STRING "[x" HEXFF_STRING, /* csF2 */
171: ESCAPE_STRING "[y" HEXFF_STRING, /* csF3 */
172: ESCAPE_STRING "[z" HEXFF_STRING, /* csF4 */
173: ESCAPE_STRING "[@" HEXFF_STRING, /* csF5 */
174: ESCAPE_STRING "[[" HEXFF_STRING, /* csF6 */
175: ESCAPE_STRING "[\\" HEXFF_STRING, /* csF7 */
176: ESCAPE_STRING "[]" HEXFF_STRING, /* csF8 */
177: ESCAPE_STRING "[^" HEXFF_STRING, /* csF9 */
178: ESCAPE_STRING "[_" HEXFF_STRING, /* csF10 */
179:
180: /* Alt keys -- use original 83-key setting since these are
181: * not defined for virtual terms; actually, many will never
182: * be used since intercepted by virtual term code, but
183: * should be there in case someone defines like 1 virtual term
184: * so the keys should return something useful.
185: */
186: ESCAPE_STRING "[1y" HEXFF_STRING, /* aF1 */
187: ESCAPE_STRING "[2y" HEXFF_STRING, /* aF2 */
188: ESCAPE_STRING "[3y" HEXFF_STRING, /* aF3 */
189: ESCAPE_STRING "[4y" HEXFF_STRING, /* aF4 */
190: ESCAPE_STRING "[5y" HEXFF_STRING, /* aF5 */
191: ESCAPE_STRING "[6y" HEXFF_STRING, /* aF6 */
192: ESCAPE_STRING "[7y" HEXFF_STRING, /* aF7 */
193: ESCAPE_STRING "[8y" HEXFF_STRING, /* aF8 */
194: ESCAPE_STRING "[9y" HEXFF_STRING, /* aF9 */
195: ESCAPE_STRING "[0y" HEXFF_STRING /* aF10 */
196: };
197:
198: /* The keypad is translated by the following table,
199: * the first entry is the normal sequence, the second the shifted,
200: * and the third the alternate keypad sequence.
201: */
202: static char *keypad[][3] = {
203: { ESCAPE_STRING "[H", "7", ESCAPE_STRING "?w" }, /* 71 */
204: { ESCAPE_STRING "[A", "8", ESCAPE_STRING "?x" }, /* 72 */
205: { ESCAPE_STRING "[I", "9", ESCAPE_STRING "?y" }, /* 73 */
206: { ESCAPE_STRING "[D", "4", ESCAPE_STRING "?t" }, /* 75 */
207: { ESCAPE_STRING "7", "5", ESCAPE_STRING "?u" }, /* 76 */
208: { ESCAPE_STRING "[C", "6", ESCAPE_STRING "?v" }, /* 77 */
209: { ESCAPE_STRING "[F", "1", ESCAPE_STRING "?q" }, /* 79 */
210: { ESCAPE_STRING "[B", "2", ESCAPE_STRING "?r" }, /* 80 */
211: { ESCAPE_STRING "[G", "3", ESCAPE_STRING "?s" }, /* 81 */
212: { ESCAPE_STRING "[L", "0", ESCAPE_STRING "?p" }, /* 82 */
213: { DELETE_STRING , ".", ESCAPE_STRING "?n" } /* 83 */
214: };
215:
216:
217: /*
218: * French Tables for converting key code to ASCII.
219: * lmaptab specifies unshifted conversion,
220: * umaptab specifies shifted conversion,
221: * smaptab specifies the shift states which are active.
222: * An entry of XXX says the key is dead.
223: * An entry of SPC requires further processing.
224: *
225: * Key codes:
226: * ESC .. <- == 1 .. 14
227: * -> .. \n == 15 .. 28
228: * CTRL .. ` == 29 .. 41
229: * ^Shift .. PrtSc == 42 .. 55
230: * ALT .. CapsLock == 56 .. 58
231: * F1 .. F10 == 59 .. 68
232: * NumLock .. Del == 69 .. 83
233: * ISO, F11, F12 == 86 .. 88
234: */
235:
236: static unsigned char fr_agmaptab[] ={ /* Alt Gr */
237: XXX, XXX, '~', '#', '{', '[', '|', /* 1 - 7 */
238: '`', '\\', '^', '@', ']', '}', XXX, XXX, /* 8 - 15 */
239: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 16 - 23 */
240: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 24 - 31 */
241: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 32 - 39 */
242: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 40 - 47 */
243: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 48 - 55 */
244: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 56 - 63 */
245: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 64 - 71 */
246: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 72 - 79 */
247: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 80 - 87 */
248: XXX /* 88 */
249: };
250:
251: static unsigned char fr_lmaptab[] ={
252: '\33', '&','\202', '"', '\'', '(', '-', /* 1 - 7 */
253: '\212','_','\207','\205',')', '=', '\b', '\t', /* 8 - 15 */
254: 'a', 'z', 'e', 'r', 't', 'y', 'u', 'i', /* 16 - 23 */
255: 'o', 'p','\260', '$', '\r', XXX, 'q', 's', /* 24 - 31 */
256: 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', /* 32 - 39 */
257: '\227','\375',XXX,'*', 'w', 'x', 'c', 'v', /* 40 - 47 */
258: 'b', 'n', ',', ';', ':', SPC, XXX, SPC, /* 48 - 55 */
259: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */
260: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */
261: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */
262: SPC, SPC, SPC, SPC, XXX, XXX, '<', XXX, /* 80 - 87 */
263: XXX /* 88 */
264: };
265:
266: static unsigned char fr_umaptab[] ={
267: '\33', '1', '2', '3', '4', '5', '6', /* 1 - 7 */
268: '7', '8', '9', '0','\370', '+', '\b', SPC, /* 8 - 15 */
269: 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16 - 23 */
270: 'O', 'P','\261','\234','\r', XXX, 'Q', 'S', /* 24 - 31 */
271: 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', /* 32 - 39 */
272: '%','\300',XXX,'\346', 'W', 'X', 'C', 'V', /* 40 - 47 */
273: 'B', 'N', '?', '.', '/', SPC, XXX, SPC, /* 48 - 55 */
274: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */
275: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */
276: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */
277: SPC, SPC, SPC, SPC, XXX, XXX, '>', XXX, /* 80 - 87 */
278: XXX /* 88 */
279: };
280:
281: static unsigned char fr_smaptab[] ={
282: SS0, SES, SS1, SES, SES, SES, SS1, /* 1 - 7 */
283: SES, SES, SES, SES, SS1, SES, CTS, SES, /* 8 - 15 */
284: LET, LET, LET, LET, LET, LET, LET, LET, /* 16 - 23 */
285: LET, LET, SS1, SS1, CTS, SHFT, LET, LET, /* 24 - 31 */
286: LET, LET, LET, LET, LET, LET, LET, SES, /* 32 - 39 */
287: SES, SS1, SHFT, SS1, LET, LET, LET, LET, /* 40 - 47 */
288: LET, LET, LET, SES, SES, SES, SHFT, SES, /* 48 - 55 */
289: SHFT, SS1, SHFT, SS1, SS1, SS1, SS1, SS1, /* 56 - 63 */
290: SS1, SS1, SS1, SS1, SS1, SHFT, KEY, KEY, /* 64 - 71 */
291: KEY, KEY, SS0, KEY, KEY, KEY, SS0, KEY, /* 72 - 79 */
292: KEY, KEY, KEY, KEY, SS0, SS0, SES, SS0, /* 80 - 87 */
293: SS0
294: };
295:
296: /*
297: * U.S. Tables for converting key code to ASCII.
298: * lmaptab specifies unshifted conversion,
299: * umaptab specifies shifted conversion,
300: * smaptab specifies the shift states which are active.
301: * An entry of XXX says the key is dead.
302: * An entry of SPC requires further processing.
303: *
304: * Key codes:
305: * ESC .. <- == 1 .. 14
306: * -> .. \n == 15 .. 28
307: * CTRL .. ` == 29 .. 41
308: * ^Shift .. PrtSc == 42 .. 55
309: * ALT .. CapsLock == 56 .. 58
310: * F1 .. F10 == 59 .. 68
311: * NumLock .. Del == 69 .. 83
312: */
313: static unsigned char us_lmaptab[] ={
314: ESCAPE_CHAR, '1', '2', '3', '4', '5', '6', /* 1 - 7 */
315: '7', '8', '9', '0', '-', '=', '\b', '\t', /* 8 - 15 */
316: 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 16 - 23 */
317: 'o', 'p', '[', ']', '\r', XXX, 'a', 's', /* 24 - 31 */
318: 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 32 - 39 */
319: '\'', '`', XXX, '\\', 'z', 'x', 'c', 'v', /* 40 - 47 */
320: 'b', 'n', 'm', ',', '.', '/', XXX, '*', /* 48 - 55 */
321: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */
322: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */
323: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */
324: SPC, SPC, SPC, SPC /* 80 - 83 */
325: };
326:
327: static unsigned char us_umaptab[] ={
328: ESCAPE_CHAR, '!', '@', '#', '$', '%', '^', /* 1 - 7 */
329: '&', '*', '(', ')', '_', '+', '\b', SPC, /* 8 - 15 */
330: 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16 - 23 */
331: 'O', 'P', '{', '}', '\r', XXX, 'A', 'S', /* 24 - 31 */
332: 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 32 - 39 */
333: '"', '~', XXX, '|', 'Z', 'X', 'C', 'V', /* 40 - 47 */
334: 'B', 'N', 'M', '<', '>', '?', XXX, '*', /* 48 - 55 */
335: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */
336: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */
337: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */
338: SPC, SPC, SPC, SPC /* 80 - 83 */
339: };
340:
341: static unsigned char us_smaptab[] ={
342: SS0, SES, SS1, SES, SES, SES, SS1, /* 1 - 7 */
343: SES, SES, SES, SES, SS1, SES, CTS, SES, /* 8 - 15 */
344: LET, LET, LET, LET, LET, LET, LET, LET, /* 16 - 23 */
345: LET, LET, SS1, SS1, CTS, SHFT, LET, LET, /* 24 - 31 */
346: LET, LET, LET, LET, LET, LET, LET, SES, /* 32 - 39 */
347: SES, SS1, SHFT, SS1, LET, LET, LET, LET, /* 40 - 47 */
348: LET, LET, LET, SES, SES, SES, SHFT, SES, /* 48 - 55 */
349: SHFT, SS1, SHFT, SS1, SS1, SS1, SS1, SS1, /* 56 - 63 */
350: SS1, SS1, SS1, SS1, SS1, SHFT, KEY, KEY, /* 64 - 71 */
351: KEY, KEY, SS0, KEY, KEY, KEY, SS0, KEY, /* 72 - 79 */
352: KEY, KEY, KEY, KEY /* 80 - 83 */
353: };
354:
355: /*
356: * German Tables for converting key code to ASCII.
357: * lmaptab specifies unshifted conversion,
358: * umaptab specifies shifted conversion,
359: * smaptab specifies the shift states which are active.
360: * An entry of XXX says the key is dead.
361: * An entry of SPC requires further processing.
362: *
363: * Key codes:
364: * ESC .. <- == 1 .. 14
365: * -> .. \n == 15 .. 28
366: * CTRL .. ` == 29 .. 41
367: * ^Shift .. PrtSc == 42 .. 55
368: * ALT .. CapsLock == 56 .. 58
369: * F1 .. F10 == 59 .. 68
370: * NumLock .. Del == 69 .. 83
371: * ISO, F11, F12 == 86 .. 88
372: */
373: unsigned char de_agmaptab[] ={ /* Alt Gr */
374: XXX, XXX,'\375','\374',XXX, XXX, XXX, /* 1 - 7 */
375: '{', '[', ']', '}', '\\', XXX, XXX, XXX, /* 8 - 15 */
376: '@', XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 16 - 23 */
377: XXX, XXX, XXX, '~', XXX, XXX, XXX, XXX, /* 24 - 31 */
378: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 32 - 39 */
379: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 40 - 47 */
380: XXX, XXX,'\346', XXX, XXX, XXX, XXX, XXX, /* 48 - 55 */
381: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 56 - 63 */
382: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 64 - 71 */
383: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 72 - 79 */
384: XXX, XXX, XXX, XXX, XXX, XXX, '|', XXX, /* 80 - 87 */
385: XXX /* 88 */
386: };
387:
388: static unsigned char de_lmaptab[] ={
389: ESCAPE_CHAR, '1', '2', '3', '4', '5', '6', /* 1 - 7 */
390: '7', '8', '9', '0','\341','\'', '\b', '\t', /* 8 - 15 */
391: 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* 16 - 23 */
392: 'o', 'p','\201', '+', '\r', XXX, 'a', 's', /* 24 - 31 */
393: 'd', 'f', 'g', 'h', 'j', 'k', 'l','\224', /* 32 - 39 */
394: '\204','^', XXX, '#', 'y', 'x', 'c', 'v', /* 40 - 47 */
395: 'b', 'n', 'm', ',', '.', SPC, XXX, SPC, /* 48 - 55 */
396: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */
397: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */
398: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */
399: SPC, SPC, SPC, SPC, XXX, XXX, '<', XXX, /* 80 - 87 */
400: XXX /* 88 */
401: };
402:
403: static unsigned char de_umaptab[] ={
404: ESCAPE_CHAR, '!', '"','\025', '$', '%', '&', /* 1 - 7 */
405: '/', '(', ')', '=', '?', '`', '\b', SPC, /* 8 - 15 */
406: 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', /* 16 - 23 */
407: 'O', 'P','\232', '*', '\r', XXX, 'A', 'S', /* 24 - 31 */
408: 'D', 'F', 'G', 'H', 'J', 'K', 'L','\231', /* 32 - 39 */
409: '\216','\370',XXX,'\'', 'Y', 'X', 'C', 'V', /* 40 - 47 */
410: 'B', 'N', 'M', ';', ':', SPC, XXX, SPC, /* 48 - 55 */
411: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */
412: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */
413: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */
414: SPC, SPC, SPC, SPC, XXX, XXX, '>', XXX, /* 80 - 87 */
415: XXX /* 88 */
416: };
417:
418: static unsigned char de_smaptab[] ={
419: SS0, SES, SS1, SES, SES, SES, SS1, /* 1 - 7 */
420: SES, SES, SES, SES, SS1, SES, CTS, SES, /* 8 - 15 */
421: LET, LET, LET, LET, LET, LET, LET, LET, /* 16 - 23 */
422: LET, LET, SS1, SS1, CTS, SHFT, LET, LET, /* 24 - 31 */
423: LET, LET, LET, LET, LET, LET, LET, SES, /* 32 - 39 */
424: SES, SS1, SHFT, SS1, LET, LET, LET, LET, /* 40 - 47 */
425: LET, LET, LET, SES, SES, SES, SHFT, SES, /* 48 - 55 */
426: SHFT, SS1, SHFT, SS1, SS1, SS1, SS1, SS1, /* 56 - 63 */
427: SS1, SS1, SS1, SS1, SS1, SHFT, KEY, KEY, /* 64 - 71 */
428: KEY, KEY, SS0, KEY, KEY, KEY, SS0, KEY, /* 72 - 79 */
429: KEY, KEY, KEY, KEY, SS0, SS0, SES, SS0, /* 80 - 87 */
430: SS0
431: };
432:
433:
434:
435: /************************** Functions. ****************************/
436:
437: int isrint();
438: int istime();
439: void isbatch();
440: int mmstart();
441: int isopen();
442: int isclose();
443: int isread();
444: int mmwrite();
445: int isioctl();
446: void mmwatch();
447: int isload();
448: int isuload();
449: int ispoll();
450: int nulldev();
451: int nonedev();
452: void isvtswitch(); /* deferred virtual terminal switch */
453:
454:
455:
456: /************************* Configuration table. *************************/
457:
458: CON iscon ={
459: DFCHR|DFPOL, /* Flags */
460: KB_MAJOR, /* Major index */
461: isopen, /* Open */
462: isclose, /* Close */
463: nulldev, /* Block */
464: isread, /* Read */
465: mmwrite, /* Write */
466: isioctl, /* Ioctl */
467: nulldev, /* Powerfail */
468: mmwatch, /* Timeout */
469: isload, /* Load */
470: isuload, /* Unload */
471: ispoll /* Poll */
472: };
473:
474: /************************** Virtual Term Stuff ********************/
475:
476: /* constants for vtdata[] */
477: #define VT_VGAPORT 0x3D4
478: #define VT_MONOPORT 0x3B4
479:
480: #define VT_MONOBASE (SEG_VIDEOa|DPL_1)
481: #define VT_VGABASE (SEG_VIDEOb|DPL_1)
482:
483: /*
484: Patchable table entries.
485: Indirect in order to produce a label which can be addressed.
486: */
487:
488: /* Configurable variables - see ker/conf/console/Space.c */
489: extern int vga_count;
490: extern int mono_count;
491: extern int kb_lang;
492:
493: HWentry VTVGA = { 4, 0, VT_VGAPORT, { 0, VT_VGABASE }, { 25, 80 } };
494: HWentry VTMONO = { 4, 0, VT_MONOPORT, { 0, VT_MONOBASE }, { 25, 80 } };
495:
496: HWentry *vtHWtable[] = {
497: VTVGA, /* VGA followed by MONO is compatible to DOS */
498: VTMONO,
499: 0 /* MUST STAY AS LAST ELEMENT !!! */
500: };
501:
502: extern int mminit();
503: static VTDATA const_vtdata = {
504: mminit, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 23, 24, 0, 0, 0, 23, 0, 0, 1
505: };
506:
507: /* later this should be dynamic */
508: VTDATA *vtconsole, **vtdata;
509:
510: int vtcount, vtmax;
511: extern int vtactive;
512: int vt_verbose = { 0 };
513: int vt_opened = { 0 };
514:
515: /* Terminal structure. */
516: TTY **vttty;
517:
518: /**************** State variables / Patchables ****************************/
519:
520: int islock; /* Keyboard locked flag */
521: int isbusy = 0; /* Raw input conversion busy */
522: int isvtbusy =0; /* VT switching busy (deferred) */
523: int isvtnotdone = 0; /* VT deferred not done */
524: int isturbo = 0; /* Flag indicating turbo machine. */
525: static unsigned shift; /* Overall shift state */
526: static char scrollkb; /* Scroll lock state */
527: static char lshiftkb = LSHIFT; /* Left shift alternate state */
528: static char isfbuf[NFBUF]; /* Function key values */
529: static char *isfval[NFKEY]; /* Function key string pointers */
530: static int ledcmd; /* LED update command count */
531: static int extended; /* extended key scan count */
532: static char extmode; /* use extended mode for this key */
533: static char ext0seen; /* 0xE0 prefix seen */
534: static char fk_loaded; /* true == funcion keys resident */
535: static int xlate = 1; /* scan code translation flag */
536: static TIM tp; /* X thingamabob */
537: static int X11led; /* Other X thingamabob */
538: static silo_t in_silo; /* Used by character silo */
539: static silo_t vt_silo; /* Queue of vt switches */
540: int kb_lang = KB_VIRTUAL; /* What to act like */
541: static int kb_in_byte;
542:
543: static unsigned char *lmaptab, *umaptab, *smaptab, *agmaptab;
544:
545:
546: /************************* Code *****************************************/
547:
548: /*
549: * This builds the queue of vt switches so they may be done as
550: * a deferred function. This had to be done since re-enabling a
551: * virtual term was slow enough that if vt's were switched rapidly,
552: * the deferred queue overflowed and things locked up.
553: *
554: * There is a small chance of a race condition about the variabl
555: * isvtbusy, but this has been minimized through the use of a lock
556: * variable in isvtswitch.
557: */
558:
559: static void queue_vt_switch(vt_key)
560: char vt_key; {
561: vt_silo.si_buf[vt_silo.si_ix] = vt_key;
562: if(++vt_silo.si_ix >= sizeof(vt_silo.si_buf))
563: vt_silo.si_ix = 0;
564:
565: if(!isvtbusy) {
566: isvtbusy = 1;
567: defer(isvtswitch, 0);
568: }
569: }
570:
571:
572: /*
573: * Load entry point.
574: * Do reset the keyboard because it gets terribly munged
575: * if you type during the boot.
576: */
577: isload()
578: {
579: register short i; /* was: int i */
580: register HWentry **hw;
581: register VTDATA *vp;
582:
583: /* Use stune et al to adjust vga_count and mono_count. */
584: VTVGA.count = vga_count;
585: VTMONO.count = mono_count;
586:
587: /*
588: * Set up keyboard tables
589: */
590:
591: switch(kb_lang) {
592: case kb_lang_fr:
593: agmaptab = fr_agmaptab;
594: lmaptab = fr_lmaptab;
595: umaptab = fr_umaptab;
596: smaptab = fr_smaptab;
597: break;
598: case kb_lang_de:
599: agmaptab = de_agmaptab;
600: lmaptab = de_lmaptab;
601: umaptab = de_umaptab;
602: smaptab = de_smaptab;
603: break;
604: default:
605: agmaptab = 0;
606: lmaptab = us_lmaptab;
607: umaptab = us_umaptab;
608: smaptab = us_smaptab;
609: break;
610: } /* switch */
611:
612: /*
613: * Reset keyboard if NOT an XT turbo.
614: */
615: if ( ! isturbo ) {
616: outb(KBCTRL, 0x0C); /* Clock low */
617: for (i = 10582; --i >= 0; ); /* For 20ms */
618: outb(KBCTRL, 0xCC); /* Clock high */
619: for (i = 0; --i != 0; )
620: ;
621: i = inb(KBDATA);
622: outb(KBCTRL, 0xCC); /* Clear keyboard */
623: outb(KBCTRL, 0x4D); /* Enable keyboard */
624: }
625:
626: PRINTV("vtload:\n");
627: fk_loaded = 0;
628:
629: /* figure out what our current max is */
630: for( vtmax = 0, hw = vtHWtable; *hw; ++hw ) {
631: vtmax += (*hw)->count;
632: (*hw)->found = 0; /* assume non-exist */
633: }
634: PRINTV( "vtload: %d screens possible\n", vtmax );
635:
636: vtdata = (VTDATA **) kalloc( vtmax * sizeof( *vtdata ) );
637: if( vtdata == NULL ) {
638: printf( "vtload: unable to obtain vtdata[%d]\n", vtmax );
639: u.u_error = -1;
640: return;
641: }
642: PRINTV( "vtload: obtained vtdata[%d] @%x\n", vtmax, vtdata );
643:
644: vttty = (TTY **) kalloc( vtmax * sizeof( *vttty ) );
645: if( vttty == NULL ) {
646: printf( "vtload: unable to obtain vttty[%d]\n", vtmax );
647: u.u_error = -1;
648: return;
649: }
650: PRINTV( "vtload: obtained vttty[%d] @%x\n", vtmax, vttty );
651:
652: /* determine which video adaptors are present */
653: for( vtcount = 0, hw = vtHWtable; *hw; ++hw ) {
654: /* remember our logical start */
655: (*hw)->start = vtcount;
656: PRINTV( ", start %d\n", vtcount );
657:
658: /* allocate the necessary memory */
659: for ( i = 0; i < (*hw)->count; ++i ) {
660: vp = vtdata[vtcount] = kalloc( sizeof(VTDATA) );
661: PRINTV( " vtdata[%d] = @%x\n", vtcount, vp );
662: if( vp == NULL || !VTttyinit(vtcount) ) {
663: printf("not enough memory for VTDATA\n" );
664: break;
665: }
666:
667: /* fill in appropriately */
668: *vp = const_vtdata;
669: vp->vmm_port = (*hw)->port;
670: vp->vmm_vseg = (*hw)->vidmemory.seg;
671: vp->vmm_voff = (*hw)->vidmemory.off;
672:
673: vp->vt_ind = vtcount;
674: vtdatainit(vp);
675: if (i == 0 ) {
676: vp->vmm_visible = VNKB_TRUE;
677: vp->vmm_seg = vp->vmm_vseg;
678: vp->vmm_off = vp->vmm_voff;
679: updscreen(vtcount);
680: }
681: (*hw)->found++;
682: vtcount++;
683: }
684: }
685:
686: /*
687: * initialize vtconsole
688: */
689: vtconsole = vtdata[vtactive = 0];
690: vtconsole->vmm_invis = 0; /* vtconsole cursor visible */
691:
692: /*
693: * Seize keyboard interrupt.
694: */
695: setivec(ISVEC, isrint);
696:
697: /*
698: * Enable mmwatch() invocation every second.
699: */
700: drvl[VT_MAJOR].d_time = 1;
701:
702: /*
703: * Initialize video display.
704: */
705: for ( i = 0; i < vtcount; ++i )
706: mmstart( vttty[i] );
707: }
708:
709: /*
710: * Unload entry point.
711: */
712: isuload()
713: {
714: register int i;
715: register level = sphi();
716:
717: clrivec(ISVEC);
718: spl( level );
719:
720: /* Restore pointers to original state. */
721: vtconsole = vtdata[0];
722: vtconsole->vmm_invis = 0;
723: vtconsole->vmm_visible = VNKB_TRUE;
724:
725: if( vt_opened )
726: printf( "VTclose with %d open screens\n", vt_opened );
727:
728: }
729:
730: /*
731: * Open routine.
732: */
733: isopen(dev, mode)
734: dev_t dev;
735: unsigned int mode;
736: {
737: register int s;
738: register TTY *tp;
739: int index = vtindex(dev);
740:
741: PRINTV("isopen: %x\n", dev);
742: if (index < 0 || index >= vtcount) {
743: u.u_error = ENXIO;
744: return;
745: }
746:
747: tp = vttty[index];
748: if ((tp->t_flags&T_EXCL) != 0 && !super()) {
749: u.u_error = ENODEV;
750: return;
751: }
752: ttsetgrp(tp, dev, mode);
753:
754: s = sphi();
755: if (tp->t_open++ == 0) {
756: initkeys(); /* init function keys */
757: tp->t_flags = T_CARR; /* indicate "carrier" */
758: ttopen(tp);
759: }
760: spl(s);
761: }
762:
763: /* Init function keys */
764: initkeys()
765: { register int i;
766: register char *cp1, *cp2;
767:
768: for (i=0; i<NFKEY; i++)
769: isfval[i] = 0; /* clear function key buffer */
770: cp2 = isfbuf; /* pointer to key buffer */
771: for (i=0; i<NFKEY; i++)
772: { isfval[i] = cp2; /* save pointer to key string */
773: cp1 = deffuncs[i]; /* get init string pointer */
774: while ((*cp2++ = *cp1++) != -1) /* copy key data */
775: if (cp2 >= &isfbuf[NFBUF-3]) /* overflow? */
776: return;
777: }
778: }
779:
780: /*
781: * Close a tty.
782: */
783: isclose(dev)
784: {
785: register int s;
786: int index = vtindex(dev);
787: register TTY *tp = vttty[index];
788:
789: if (--tp->t_open == 0)
790: ttclose(tp);
791:
792: }
793:
794: /*
795: * Read routine.
796: */
797: isread(dev, iop)
798: dev_t dev;
799: IO *iop;
800: {
801: int index = vtindex(dev);
802: register TTY *tp = vttty[index];
803:
804: ttread(tp, iop, 0);
805: if (tp->t_oq.cq_cc)
806: mmtime(tp);
807: }
808:
809: /*
810: * Ioctl routine.
811: */
812: int
813: kbstate(action)
814: int action;
815: {
816: int i;
817: if (action == 1) {
818: timeout(&tp,20,kbstate,2);
819: outb(KBCTRL, 0xCC); /* Clock high */
820: }
821: if (action == 2) {
822: i = inb(KBDATA);
823: outb(KBCTRL, 0xCC); /* Clear keyboard */
824: outb(KBCTRL, 0x4D); /* Enable keyboard */
825: }
826: }
827:
828:
829: isioctl(dev, com, vec)
830: dev_t dev;
831: struct sgttyb *vec;
832: {
833: register int s;
834:
835: switch(com) {
836: #define KDDEBUG 0
837: #if KDDEBUG
838: case KDMEMDISP:
839: {
840: struct kd_memloc* mem;
841: unsigned char ub, pb;
842: mem = vec;
843: pxcopy( mem->physaddr, &pb, 1, SEG_386_KD );
844: ub = getubd( mem->vaddr );
845: printf( "User's byte %x(%x), Physical byte %x, Addresses %x %x\n",
846: mem->ioflg, ub, pb, mem->vaddr, mem->physaddr );
847: goto ioc_done;;
848: }
849: #endif
850: case KDMAPDISP:
851: {
852: struct kd_memloc* mem;
853: mem = vec;
854: #if KDDEBUG
855: printf( "mapPhysUser(%x, %x, %x) = %d\n",
856: mem->vaddr, mem->physaddr, mem->length,
857: #endif
858: mapPhysUser(mem->vaddr, mem->physaddr, mem->length)
859: #if KDDEBUG
860: )
861: #endif
862: ;
863: }
864: case KDENABIO:
865: {
866: int i;
867: for (i = 0 ; i < 64 ; i++ )
868: iomapAnd(0,i);
869: goto ioc_done;;
870: }
871: case KIOCSOUND:
872: {
873: if (vec) {
874: outb(TIMER_CTL, 0xB6);
875: outb(TIMER_CNT, (int)vec&0xFF);
876: outb(TIMER_CNT, (int)vec>>8);
877: outb(SPEAKER_CTL, inb(SPEAKER_CTL) | 03); /* Turn speaker on */
878: }
879: else
880: outb(SPEAKER_CTL, inb(SPEAKER_CTL) & ~03 ); /* speaker off */
881: goto ioc_done;;
882: }
883: case KDSKBMODE:
884: {
885: outb(KBCTRL, 0x0C); /* Clock low */
886: timeout(&tp,3,kbstate,1); /* wait about 20-30ms */
887: xlate = (int)vec;
888: goto ioc_done;;
889: }
890: case KDSETLED:
891: {
892: X11led = (int)vec;
893: updleds();
894: goto ioc_done;;
895: }
896:
897: case TIOCSETF:
898: case TIOCGETF:
899: isfunction(com, (char *)vec);
900: goto ioc_done;;
901: case TIOCSHIFT: /* switch left-SHIFT and "\" */
902: lshiftkb = LSHIFTA; /* alternate values */
903: lmaptab[41] = '\\';
904: lmaptab[42] = XXX;
905: umaptab[41] = '|';
906: umaptab[42] = XXX;
907: smaptab[41] = SS1;
908: smaptab[42] = SHFT;
909: goto ioc_done;;
910: case TIOCCSHIFT: /* normal (default) left-SHIFT and "\" */
911: lshiftkb = LSHIFT; /* normal values */
912: lmaptab[41] = XXX;
913: lmaptab[42] = '\\';
914: umaptab[41] = XXX;
915: umaptab[42] = '|';
916: smaptab[41] = SHFT;
917: smaptab[42] = SS1;
918: goto ioc_done;;
919: default:
920: s = sphi();
921: ttioctl(vttty[vtindex(dev)], com, vec);
922: spl(s);
923: break;
924: }
925:
926: ioc_done:
927: return;
928: }
929:
930: /*
931: * Set and receive the function keys.
932: */
933: isfunction(c, v)
934: int c;
935: char *v;
936: {
937: register char *cp;
938: register int i;
939:
940: if (c == TIOCGETF) {
941: for (cp = isfbuf; cp < &isfbuf[NFBUF]; cp++)
942: putubd(v++, *cp);
943: } else {
944: for (i=0; i<NFKEY; i++) /* zap current settings */
945: isfval[i] = 0;
946: cp = isfbuf; /* pointer to key buffer */
947: for (i=0; i<NFKEY; i++) {
948: isfval[i] = cp; /* save pointer to key string */
949: while ((*cp++ = getubd(v++)) != -1) /* copy key data */
950: if (cp >= &isfbuf[NFBUF-3]) /* overflow? */
951: return;
952: }
953: }
954: }
955:
956:
957: /*
958: * Poll routine.
959: */
960: ispoll( dev, ev, msec )
961: dev_t dev;
962: int ev;
963: int msec;
964: {
965: register TTY *tp = vttty[vtindex(dev)];
966:
967: return ttpoll(tp, ev, msec);
968: }
969:
970: /*
971: * Process numeric keypad for virtual terminals.
972: */
973: vtnumeric(c)
974: int c;
975: {
976: switch (c) {
977: case 71: /* ctrl-7 */
978: queue_vt_switch(vt7);
979: break;
980: case 72: /* ctrl-8 */
981: queue_vt_switch(vt8);
982: break;
983: case 73: /* ctrl-9 */
984: queue_vt_switch(vt9);
985: break;
986: case 74: /* ctrl - */
987: queue_vt_switch(vtp);
988: break;
989: case 75:
990: queue_vt_switch(vt4);
991: break;
992: case 76:
993: queue_vt_switch(vt5);
994: break;
995: case 77: /* ctrl 4/5/6 (vt5, vt6, vt7) */
996: queue_vt_switch(vt6);
997: break;
998: case 78: /* ctrl + */
999: queue_vt_switch(vtn);
1000: break;
1001: case 79: /* ctrl-1 */
1002: queue_vt_switch(vt1);
1003: break;
1004: case 80: /* ctrl-2 */
1005: queue_vt_switch(vt2);
1006: break;
1007: case 81: /* ctrl-3 */
1008: queue_vt_switch(vt3);
1009: break;
1010: case 82: /* ctrl 0 (vt0) */
1011: queue_vt_switch(vt0);
1012: break;
1013: case 83: /* ctrl del (toggle) */
1014: c = vtt;
1015: queue_vt_switch(vtt);
1016: break;
1017: }
1018: }
1019:
1020: /*
1021: * Handle special input sequences.
1022: * The character passed is the key number.
1023: */
1024: isspecial(c)
1025: int c;
1026: {
1027: register char *cp;
1028: register int s;
1029: int update_leds = 0;
1030:
1031: cp = 0;
1032:
1033: switch (c) {
1034: case 15: /* cursor back tab */
1035: cp = "\033[Z";
1036: break;
1037: case 53:
1038: if(kb_lang == kb_lang_fr \
1039: || kb_lang == kb_lang_de) {
1040: if (extmode)
1041: cp = "/";
1042: else
1043: if (shift & SES)
1044: cp = "_";
1045: else
1046: cp = "-";
1047: break;
1048: }
1049: else
1050: break;
1051: case 55: /* ignore PrtScr */
1052: if(kb_lang == kb_lang_fr \
1053: || kb_lang == kb_lang_de) {
1054: if (!extmode)
1055: cp = "*";
1056: break;
1057: }
1058: else
1059: break;
1060: case 59: case 60: case 61: case 62: case 63: /* Function keys */
1061: case 64: case 65: case 66:
1062: /* offset to function string */
1063: /* Magic numbers 21 and 61 to mach vtnkb constants */
1064: if ( shift & ALS ) {
1065: switch(c) {
1066: case 59: /* Alt-F1 */
1067: queue_vt_switch(vt0);
1068: break;
1069: case 60: /* Alt-F2 */
1070: queue_vt_switch(vt1);
1071: break;
1072: case 61: /* Alt-F3 */
1073: queue_vt_switch(vt2);
1074: break;
1075: case 62: /* Alt-F4 */
1076: queue_vt_switch(vt3);
1077: break;
1078: case 63: /* Alt-F5 */
1079: queue_vt_switch(vt4);
1080: break;
1081: case 64: /* Alt-F6 */
1082: queue_vt_switch(vt5);
1083: break;
1084: case 65: /* Alt-F7 */
1085: queue_vt_switch(vt6);
1086: break;
1087: case 66: /* Alt-F8 */
1088: queue_vt_switch(vt7);
1089: break;
1090: default:
1091: break;
1092: }
1093: }
1094: else { if((shift & (SES)) && (shift & CTS)) /* ctrl-shft-Fx */
1095: cp = isfval[c-29];
1096: else { if(shift & CTS) /* ctrl-Fx */
1097: cp = isfval[c-39];
1098: else { if(shift & (SES)) /* shift-Fx */
1099: cp = isfval[c-49];
1100: else cp = isfval[c-59]; /* Plain Fx */
1101: }}}
1102: break;
1103: case 67: case 68:
1104: /* offset to function string */
1105: if ( shift & ALS ) {
1106: switch(c) {
1107: case 67: /* Alt-F9 */
1108: queue_vt_switch(vt8);
1109: break;
1110: case 68: /* Alt-F10 */
1111: queue_vt_switch(vt9);
1112: break;
1113: default:
1114: break;
1115: }
1116: }
1117: else { if((shift & (SES)) && (shift & CTS)) /* cs-Fx */
1118: cp = isfval[c-29];
1119: else { if(shift & CTS) /* c-Fx */
1120: cp = isfval[c-39];
1121: else { if(shift & (SES)) /* s-Fx */
1122: cp = isfval[c-49];
1123: else cp = isfval[c-59]; /* Fx */
1124: }}}
1125: break;
1126: case 70: /* Scroll Lock -- stop/start output */
1127: {
1128: static char cbuf[2];
1129:
1130: cp = &cbuf[0]; /* working buffer */
1131: if (!(vttty[vtactive]->t_sgttyb.sg_flags
1132: & RAWIN)) { /* not if in RAW mode */
1133:
1134: ++update_leds;
1135: if (vttty[vtactive]->t_flags&T_STOP){/* output stopped? */
1136: cbuf[0] = vttty[vtactive]->t_tchars.t_startc;
1137: scrollkb = 0;
1138: } else {
1139: cbuf[0] = vttty[vtactive]->t_tchars.t_stopc;
1140: scrollkb = 1;
1141: }
1142: }
1143: break;
1144: }
1145:
1146: case 79: /* 1/End */
1147: case 80: /* 2/DOWN */
1148: case 81: /* 3/PgDn */
1149: case 82: /* 0/Ins */
1150: case 83: /* ./Del */
1151: --c; /* adjust code */
1152: case 75: /* 4/LEFT */
1153: case 76: /* 5 */
1154: case 77: /* 6/RIGHT */
1155: --c; /* adjust code */
1156: case 71: /* 7/Home/Clear */
1157: case 72: /* 8/UP */
1158: case 73: /* 9/PgUp */
1159: s = 0; /* start off with normal keypad */
1160: if (shift & NMLS) /* num lock? */
1161: s = 1; /* set shift pad */
1162: if (shift & SES) /* shift? */
1163: s ^= 1; /* toggle shift pad */
1164: if (shift & AKPS) /* alternate pad? */
1165: s = 2; /* set alternate pad */
1166: if(kb_lang == kb_lang_fr || kb_lang == kb_lang_de) {
1167: if (extmode) /* not from keypad? */
1168: s = 0; /* force normal sequence */
1169: }
1170: cp = keypad[c-71][s]; /* get keypad value */
1171: break;
1172: }
1173: if (cp) /* send string */
1174: while ((*cp != 0) && (*cp != -1))
1175: isin( *cp++ & 0377 );
1176: return update_leds;
1177: }
1178:
1179: /**
1180: *
1181: * void
1182: * ismmfunc( c ) -- process keyboard related output escape sequences
1183: * char c;
1184: */
1185: void
1186: ismmfunc(c)
1187: register int c;
1188: {
1189: switch (c) {
1190: case 't': /* Enter numlock */
1191: shift |= NMLS;
1192: updleds(); /* update LED status */
1193: break;
1194: case 'u': /* Leave numlock */
1195: shift &= ~NMLS;
1196: updleds(); /* update LED status */
1197: break;
1198: case '=': /* Enter alternate keypad */
1199: shift |= AKPS;
1200: break;
1201: case '>': /* Exit alternate keypad */
1202: shift &= ~AKPS;
1203: break;
1204: case 'c': /* Reset terminal */
1205: islock = 0;
1206: shift = 0;
1207: initkeys();
1208: updleds(); /* update LED status */
1209: break;
1210: }
1211: }
1212:
1213: /**
1214: *
1215: * void
1216: * isin[B( c ) -- append character to raw input silo
1217: * char c;
1218: */
1219: static
1220: isin( c )
1221: register int c;
1222: {
1223: int cache_it = 1;
1224: TTY * tp = vttty[vtactive];
1225:
1226: /*
1227: * If using software incoming flow control, process and
1228: * discard t_stopc and t_startc.
1229: */
1230: if (_IS_IXON_MODE (tp)) {
1231: if (_IS_START_CHAR (tp, c) ||
1232: (_IS_IXANY_MODE (tp) && (tp->t_flags & T_STOP) != 0)) {
1233: tp->t_flags &= ~ (T_STOP | T_XSTOP);
1234: ttstart (tp);
1235: cache_it = 0;
1236: } else if (_IS_STOP_CHAR (tp, c)) {
1237: if ((tp->t_flags & T_STOP) == 0)
1238: tp->t_flags |= (T_STOP | T_XSTOP);
1239: cache_it = 0;
1240: }
1241: }
1242: /*
1243: * If the tty is not open the character is
1244: * just tossed away.
1245: */
1246: if (vttty [vtactive]->t_open == 0)
1247: return;
1248:
1249:
1250: /*
1251: * Cache received character.
1252: */
1253: if (cache_it) {
1254: in_silo.si_buf[ in_silo.si_ix ] = c;
1255:
1256: if ( ++in_silo.si_ix >= sizeof(in_silo.si_buf) )
1257: in_silo.si_ix = 0;
1258:
1259: }
1260: }
1261:
1262: /**
1263: *
1264: * void
1265: * isbatch() -- raw input conversion routine
1266: *
1267: * Action: Enable the video display.
1268: * Canonize the raw input silo.
1269: *
1270: * Notes: isbatch() was scheduled as a deferred process by isrint().
1271: */
1272: static void
1273: isbatch( tp )
1274: register TTY * tp;
1275: {
1276: register int c;
1277: static int lastc;
1278: VTDATA *vp = tp->t_ddp;
1279: int s;
1280:
1281: /*
1282: * Ensure video display is enabled.
1283: */
1284: if (vp->vmm_visible)
1285: mm_von(vp);
1286:
1287: isbusy = 0;
1288:
1289: /*
1290: * Process all cached characters.
1291: */
1292: while ( in_silo.si_ix != in_silo.si_ox ) {
1293:
1294: /*
1295: * Get next cached char.
1296: */
1297: s = sphi();
1298: c = in_silo.si_buf[ in_silo.si_ox ];
1299:
1300: if ( in_silo.si_ox >= sizeof(in_silo.si_buf) - 1 )
1301: in_silo.si_ox = 0;
1302: else
1303: in_silo.si_ox++;
1304: spl(s);
1305:
1306: if (islock == 0 || _IS_INTERRUPT_CHAR (tp, c) ||
1307: _IS_QUIT_CHAR (tp, c)) {
1308: ttin (tp, c);
1309: } else if (c == 'b' && lastc == ESCAPE_CHAR) {
1310: islock = 0;
1311: ttin (tp, lastc);
1312: ttin (tp, c);
1313: } else if (c == 'c' && lastc == ESCAPE_CHAR) {
1314: ttin (tp, lastc);
1315: ttin (tp, c);
1316: } else
1317: putchar ('\a');
1318:
1319: lastc = c;
1320: }
1321: }
1322:
1323: /*
1324: * update the keyboard status LEDS
1325: */
1326: updleds()
1327: {
1328: int s;
1329:
1330: s = sphi();
1331: outb(KBDATA, LEDCMD);
1332: ledcmd++;
1333: spl(s);
1334: }
1335:
1336:
1337: /*
1338: * unlock the scroll in case an interrupt character is received
1339: */
1340: kbunscroll()
1341: {
1342: scrollkb = 0;
1343: updleds();
1344: }
1345: int
1346: VTttyinit(i)
1347: int i;
1348: {
1349: TTY *tp;
1350:
1351: /*
1352: * get pointer to TTY structure from kernal memory space
1353: */
1354: if( (tp = vttty[i] = (TTY *)kalloc(sizeof (TTY))) == NULL )
1355: return(0);
1356: PRINTV( " vttty[%d]: @%x, ", i, tp );
1357:
1358: #if FAR_TTY
1359: /*
1360: * get pointers to the buffers pointed to by the TTY structure
1361: * from user memory space
1362: */
1363: tp->t_buffer = salloc( (fsize_t)NCIB+2*SI_BUFSIZ, SFSYST|SFNSWP );
1364: tp->t_ib = 0;
1365: tp->t_rawin.si_buf = NCIB;
1366: tp->t_rawout.si_buf = NCIB+SI_BUFSIZ;
1367: #endif
1368: tp->t_param = NULL;
1369: tp->t_start = &mmstart;
1370:
1371: tp->t_ddp = vtdata[i];
1372: PRINTV( "data @%lx\n", tp->t_ddp );
1373: return(1);
1374: }
1375:
1376: vtdatainit(vp)
1377: VTDATA *vp;
1378: {
1379: /*
1380: * vtdata init - vmm part
1381: */
1382: vp->vmm_invis = -1; /* cursor invisible */
1383:
1384: vp->vt_buffer = kalloc( TEXTBLOCK );
1385: vp->vmm_seg = vp->vmm_mseg = ds_sel();
1386: vp->vmm_off = vp->vmm_moff = vp->vt_buffer;
1387: PRINTV( "vt@%x init index %d,%d), seg %x, off %x\n",
1388: vp, vp->vt_ind, vp->vmm_mseg, vp->vmm_moff );
1389: /*
1390: * vtdata init - vnkb part
1391: */
1392: /* Make the first memory block active, if present */
1393: vp->vnkb_lastc = 0;
1394: vp->vnkb_fnkeys = 0;
1395: vp->vnkb_funkeyp = 0;
1396: vp->vnkb_fk_loaded = 0; /* no Fn keys yet */
1397: }
1398:
1399: /*
1400: * Given device number, return index for vtdata[], vttty[], etc.
1401: *
1402: * Major number must be VT_MAJOR for CPU to get here.
1403: *
1404: * Minor Number Index Value
1405: * ----- ------ ----- -----
1406: * 0000 0000 vtactive ... device (2,0) is the active screen
1407: * 0000 0001 0
1408: * 0000 0010 1
1409: * 0000 0011 2
1410: * ....
1411: * 0000 1111 14
1412: *
1413: * 0100 xxxx xxxx ... color devices only
1414: * 0101 xxxx xxxx - (# of color devices found) ... monochrome only
1415: *
1416: * Return value is in range 0 to vtcount-1 for valid minor numbers,
1417: * -1 for invalid minor numbers.
1418: */
1419: int
1420: vtindex( dev )
1421: dev_t dev;
1422: {
1423: register int ret = -1;
1424:
1425: if ( dev & VT_PHYSICAL ) {
1426: int hw = ( dev >> 4 ) & 3;
1427: int hw_index = dev & 0x0F;
1428:
1429: if( hw_index < vtHWtable[hw]->found )
1430: ret = vtHWtable[hw]->start + hw_index;
1431: } else {
1432: int lg_index = dev & 0x0F;
1433:
1434: if (lg_index == 0)
1435: ret = vtactive;
1436: if (lg_index > 0 && lg_index <= vtcount )
1437: ret = lg_index-1;
1438: }
1439: if (ret >= 0)
1440: ret %= vtcount;
1441: else
1442: PRINTV( "vtindex: (%x) %d. invalid !\n", dev, ret );
1443: return ret;
1444: }
1445:
1446: /*
1447: *
1448: * void
1449: * isvtswitch() -- deferred virtual terminal switch
1450: *
1451: * Action: - save current shift key status
1452: * - determine new active virtual terminal
1453: * - deactivate shift key status of the current virtual terminal
1454: * - deactivate current virtual terminal
1455: * - activate shift key status of the new virtual terminal with
1456: * the previously saved shift key status
1457: * - activate new virtual terminal
1458: *
1459: * Notes: isvtswitch() was scheduled as a deferred process by
1460: * process_key() which is a function called by isrint().
1461: */
1462: void
1463: isvtswitch(dummy)
1464: int dummy;
1465: {
1466: register int key_val;
1467: register int new_index, i;
1468: unsigned lockshift, nolockshift;
1469: VTDATA *vp = vtdata[vtactive];
1470: VTDATA *vp_old, *vp_new;
1471: static int vtprevious;
1472: int s;
1473:
1474: /*
1475: * When this is zero, queue_vt_switch() will crank off another
1476: * deferred function
1477: */
1478: isvtbusy = 0;
1479:
1480: /*
1481: * Process the whole queue
1482: */
1483:
1484: while(vt_silo.si_ix != vt_silo.si_ox) {
1485: lockshift = shift & (CPLS | NMLS);
1486: nolockshift = shift & ~(CPLS | NMLS);
1487:
1488: /*
1489: * We must lock on the manipulation of these variables
1490: * or we lose some vt switches. Trust me -- it happens.
1491: */
1492:
1493: s=sphi();
1494: key_val = vt_silo.si_buf[vt_silo.si_ox];
1495:
1496: if(vt_silo.si_ox >= sizeof(vt_silo.si_buf) - 1)
1497: vt_silo.si_ox = 0;
1498: else
1499: vt_silo.si_ox++;
1500: spl(s);
1501:
1502: PRINTV( "F%d: %d", key_val, vtactive );
1503:
1504: switch (key_val) {
1505: case VTKEY_HOME:
1506: new_index = 0;
1507: break;
1508: case VTKEY_NEXT:
1509: new_index = vtactive;
1510: for( i = 0; i < vtcount; ++i ) {
1511: new_index = ++new_index % vtcount;
1512: if( vttty[new_index]->t_open )
1513: break;
1514: }
1515: break;
1516: case VTKEY_PREV:
1517: new_index = vtactive;
1518: for( i = 0; i < vtcount; ++i ) {
1519: new_index = (--new_index+vtcount) % vtcount;
1520: if( vttty[new_index]->t_open )
1521: break;
1522: }
1523: break;
1524: case VTKEY_TOGL:
1525: new_index = vtprevious;
1526: break;
1527: default:
1528: new_index = vtindex(vtkey_to_dev(key_val));
1529: if( new_index < 0) {
1530: putchar( '\007' );
1531: return;
1532: }
1533: }
1534:
1535: T_CON(8, printf("%d->%d ", vtactive, new_index));
1536: if( new_index == vtactive )
1537: return;
1538:
1539: /* Save which locking shift states are in effect. */
1540:
1541: s = sphi();
1542: vp_old = vtdata[vtactive];
1543: vp_new = vtdata[new_index];
1544:
1545: vp_old->vnkb_shift = lockshift;
1546: vtdeactivate(vp_new, vp_old); /* deactivate old virtual terminal */
1547:
1548: /* Restore shift lock state, append current momentary shift state. */
1549: shift = vp_new->vnkb_shift | nolockshift;
1550: vtactivate(vp_new); /* activate new virtual terminal */
1551: updterminal(new_index);
1552: vtprevious = vtactive;
1553: vtactive = new_index; /* update vtactive */
1554: spl(s);
1555: }
1556: isvtnotdone = 0;
1557: }
1558:
1559: vtdeactivate(vp_new, vp_old)
1560: register VTDATA *vp_new, *vp_old;
1561: {
1562: register i;
1563: VTDATA *vpi;
1564:
1565: /* store old screen contents in memory segment */
1566: ffcopy (vp_old->vmm_voff, vp_old->vmm_vseg,
1567: vp_old->vmm_moff, vp_old->vmm_mseg, TEXTBLOCK);
1568:
1569: /*
1570: * if changing to another screen on same video board
1571: * for all screens on same board as new screen
1572: * deactivate, but don't update
1573: * else - changing to a screen on different board
1574: * for all screens NOT on same board as new screen
1575: * deactivate, but don't update
1576: */
1577: if ( vp_old->vmm_port == vp_new->vmm_port ) {
1578: T_CON(8, printf("deactivate on %x ", vp_new->vmm_port));
1579: for (i = 0; i < vtcount; ++i) {
1580: vpi = vtdata[i];
1581: if ( vpi->vmm_port == vp_new->vmm_port ) {
1582: /* deactivate, but don't update */
1583: vpi->vmm_invis = ~0;
1584: vpi->vmm_visible = VNKB_FALSE;
1585: vpi->vmm_seg = vpi->vmm_mseg;
1586: vpi->vmm_off = vpi->vmm_moff;
1587: if( vpi->vmm_seg == 0 )
1588: printf( "[1]vpi->vmm_seg = 0\n" );
1589: PRINTV( "vt.back %d. seg %x off %x\n", i,
1590: vpi->vmm_seg, vpi->vmm_off );
1591: }
1592: }
1593: } else {
1594: T_CON(8, printf("deactivate %x->%x ",
1595: vp_old->vmm_port, vp_new->vmm_port));
1596: for (i = 0; i < vtcount; ++i) {
1597: vpi = vtdata[i];
1598: if ( (vpi->vmm_port != vp_new->vmm_port)
1599: && (vpi->vmm_invis == 0) ) {
1600: /* update, but don't deactivate */
1601: vpi->vmm_invis = ~0;
1602: updscreen(i);
1603: }
1604: }
1605: }
1606: }
1607:
1608: vtactivate(vp)
1609: VTDATA *vp;
1610: {
1611: register VTDATA *vpi;
1612: register i;
1613:
1614: /*
1615: * copy from screen contents from heap segment to video memory
1616: * only if necessary
1617: */
1618: if (vp->vmm_visible == VNKB_FALSE)
1619: ffcopy (vp->vmm_moff, vp->vmm_mseg,
1620: vp->vmm_voff, vp->vmm_vseg, TEXTBLOCK);
1621:
1622: for (i = 0; i < vtcount; ++i) {
1623: vpi = vtdata[i];
1624: if (vpi->vmm_port == vp->vmm_port) {
1625: vpi->vmm_invis = -1;
1626: vpi->vmm_visible = VNKB_FALSE;
1627: vpi->vmm_seg = vpi->vmm_mseg;
1628: vpi->vmm_off = vpi->vmm_moff;
1629: if (vpi->vmm_seg == 0)
1630: printf ("[2]vpi->vmm_seg = 0\n");
1631: PRINTV ("vt.back seg %x off %x\n",
1632: vpi->vmm_seg, vpi->vmm_off);
1633: }
1634: }
1635: /*
1636: * Set new active terminal
1637: */
1638: vp->vmm_invis = 0;
1639: vp->vmm_visible = VNKB_TRUE;
1640: vp->vmm_seg = vp->vmm_vseg;
1641: vp->vmm_off = vp->vmm_voff;
1642: if (vp->vmm_seg == 0)
1643: printf ("vp->vmm_seg = 0\n");
1644: }
1645:
1646: /*
1647: * update the terminal to match vtactive
1648: */
1649: updterminal(index)
1650: int index;
1651: {
1652: updscreen(index);
1653: updleds();
1654: }
1655:
1656: /*
1657: * Given a function key number (e.g. vt0),
1658: * return the corresponding minor device number.
1659: *
1660: * Assume valid key number (VTKEY(fnum) is true) by the time we get here.
1661: */
1662: int
1663: vtkey_to_dev(fnum)
1664: int fnum;
1665: {
1666: if (fnum >=vt0 && fnum <= vt15)
1667: return fnum-vt0+1;
1668: if (fnum >=color0 && fnum <= color15)
1669: return (fnum-color0)|(VT_PHYSICAL|VT_HW_COLOR);
1670: if (fnum >=mono0 && fnum <= mono15)
1671: return (fnum-mono0)|(VT_PHYSICAL|VT_HW_MONO);
1672: printf("vtkey_to_dev(%d)! ", fnum);
1673: return 0;
1674: }
1675:
1676: /*
1677: * Receive interrupt.
1678: */
1679: isrint()
1680: {
1681: register int c;
1682: register int s;
1683: register int r;
1684: int savests;
1685: int update_leds = 0;
1686: int i;
1687:
1688: if ( isbusy == 0 ) {
1689: isbusy = 1;
1690: defer(isbatch, vttty[vtactive]);
1691: }
1692:
1693:
1694: /*
1695: * Pull character from the data
1696: * port. Pulse the KBFLAG in the control
1697: * port to reset the data buffer.
1698: */
1699: r = inb(KBDATA) & 0xFF;
1700: c = inb(KBCTRL);
1701: outb(KBCTRL, c|KBFLAG);
1702: outb(KBCTRL, c);
1703: if (!xlate) {
1704: if (ledcmd) {
1705: if (r == KBACK) { /* output to status LEDS */
1706: ledcmd--;
1707: outb(KBDATA, X11led);
1708: return;
1709: }
1710: }
1711: isin(r);
1712: return;
1713: }
1714:
1715: #if KBDEBUG
1716: printf("kbd: %d\n", r); /* print scan code/direction */
1717: #endif
1718: if (ledcmd) {
1719: if (r == KBACK) { /* output to status LEDS */
1720: ledcmd--;
1721: /*
1722: * This is a stupid delay for a stupid way
1723: * of doing things. Timing constraints between
1724: * an ACK receive and a sending of data should
1725: * have been implemented, so now we suffer.
1726: */
1727: busyWait2(0, 2500);
1728: c = scrollkb & 1;
1729: if (shift & NMLS)
1730: c |= 2;
1731: if (shift & CPLS)
1732: c |= 4;
1733: outb(KBDATA, c);
1734: }
1735: return;
1736: }
1737: if (extended > 0) { /* if multi-character seq, */
1738: --extended; /* ... ignore this char */
1739: return;
1740: }
1741: switch (r) {
1742: case EXTENDED0: /* 0xE0 prefix found */
1743: if(kb_lang == kb_lang_fr \
1744: || kb_lang == kb_lang_de) {
1745: ext0seen = 1;
1746: return;
1747: }
1748: case EXTENDED1: /* ignore extended sequences */
1749: extended = 5;
1750: return;
1751: case 0xFF: /* Overrun */
1752: return;
1753: }
1754:
1755: if(kb_lang == kb_lang_fr \
1756: || kb_lang == kb_lang_de) {
1757: if (ext0seen) {
1758: ext0seen = 0;
1759: extmode = 1;
1760: } else
1761: extmode = 0;
1762: }
1763:
1764: c = (r & KEYSC) - 1;
1765: /*
1766: * Check for reset.
1767: */
1768: if ((r&KEYUP) == 0 && c == DELETE && (shift&(CTS|ALS)) == (CTS|ALS))
1769: boot();
1770:
1771: /*
1772: * Track "shift" keys.
1773: */
1774: s = smaptab[c];
1775: if (s&SHFT) {
1776: if (r&KEYUP) { /* "shift" released */
1777: if (c == RSHIFT)
1778: shift &= ~SRS;
1779: else if (c == lshiftkb)
1780: shift &= ~SLS;
1781: else if (c == CTRLkb)
1782: shift &= ~CTS;
1783: else if (c == ALTkb) {
1784: if(kb_lang == kb_lang_fr \
1785: || kb_lang == kb_lang_de)
1786: shift &= extmode ? ~AGS : ~ALS;
1787: else
1788: shift &= ~ALS;
1789: }
1790: } else { /* "shift" pressed */
1791: if (c == lshiftkb)
1792: shift |= SLS;
1793: else if (c == RSHIFT)
1794: shift |= SRS;
1795: else if (c == CTRLkb)
1796: shift |= CTS;
1797: else if (c == ALTkb) {
1798: if(kb_lang == kb_lang_fr \
1799: || kb_lang == kb_lang_de)
1800: shift |= extmode ? AGS : ALS;
1801: else
1802: shift |= ALS;
1803: }
1804: else if (c == CAPLOCK) {
1805: shift ^= CPLS; /* toggle cap lock */
1806: updleds();
1807: } else if (c == NUMLOCK) {
1808: shift ^= NMLS; /* toggle num lock */
1809: updleds();
1810: }
1811: }
1812: return;
1813: }
1814:
1815: /*
1816: * No other key up codes of interest.
1817: */
1818: if (r&KEYUP)
1819: return;
1820:
1821: /*
1822: * Map character, based on the
1823: * current state of the shift, control, alt graphics,
1824: * meta (ALT) and lock flags.
1825: */
1826: if ((shift & AGS) && (kb_lang == kb_lang_fr)) /* Alt Graphics ? */
1827: c = agmaptab[c];
1828: else if (shift & CTS) {
1829: if (s == CTS) /* Map Ctrl (BS | NL) */
1830: c = (c == BACKSP) ? 0x7F : 0x0A;
1831: else if (s==SS1 || s==LET) {
1832: if((c = umaptab[c]) != SPC) /* Normal Ctrl map */
1833: c &= 0x1F; /* Clear bits 5-6 */
1834: } else { if (s==KEY || s==SS0)
1835: vtnumeric(r);
1836: return; /* Ignore this char */
1837: }
1838: } else if (s &= shift) {
1839: if (shift & SES) { /* if shift on */
1840: if (s & (CPLS|NMLS)) /* if caps/num lock */
1841: c = lmaptab[c]; /* use unshifted */
1842: else
1843: c = umaptab[c]; /* use shifted */
1844:
1845: } else { /* if shift not on */
1846: if (s & (CPLS|NMLS)) /* if caps/num lock */
1847: c = umaptab[c]; /* use shifted */
1848: else
1849: c = lmaptab[c]; /* use unshifted */
1850: }
1851: } else
1852: c = lmaptab[c]; /* use unshifted */
1853:
1854: /*
1855: * Act on character.
1856: */
1857: if (c == XXX)
1858: return; /* char to ignore */
1859:
1860: if (c != SPC) { /* not special char? */
1861: if (shift & ALS) /* ALT (meta bit)? */
1862: c |= 0x80; /* set meta */
1863: isin(c); /* send the char */
1864: } else
1865: update_leds += isspecial(r); /* special chars */
1866: if (update_leds) {
1867: savests = sphi();
1868: outb(KBDATA, LEDCMD);
1869: ledcmd++;
1870: spl(savests);
1871: }
1872: }
1873:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.