Commit | Line | Data |
---|---|---|
febf7236 WN |
1 | /*- |
2 | * Copyright (c) 1990 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * William Jolitz. | |
7 | * | |
50fc34ca DA |
8 | * Added support for ibmpc term type and improved keyboard support. -Don Ahn |
9 | * | |
febf7236 WN |
10 | * %sccs.include.386.c% |
11 | * | |
50fc34ca | 12 | * @(#)pccons.c 5.2 (Berkeley) %G% |
febf7236 WN |
13 | */ |
14 | ||
15 | /* | |
16 | * code to work keyboard & display for console | |
17 | */ | |
18 | #include "param.h" | |
19 | #include "conf.h" | |
20 | #include "dir.h" | |
21 | #include "ioctl.h" | |
22 | #include "user.h" | |
23 | #include "proc.h" | |
24 | #include "tty.h" | |
25 | #include "uio.h" | |
50fc34ca | 26 | #include "machine/device.h" |
febf7236 WN |
27 | #include "callout.h" |
28 | #include "systm.h" | |
29 | #include "kernel.h" | |
30 | #include "syslog.h" | |
31 | #include "icu.h" | |
32 | ||
33 | struct tty cons; | |
34 | ||
35 | struct consoftc { | |
36 | char cs_flags; | |
37 | #define CSF_ACTIVE 0x1 /* timeout active */ | |
38 | #define CSF_POLLING 0x2 /* polling for input */ | |
39 | char cs_lastc; /* last char sent */ | |
40 | int cs_timo; /* timeouts since interrupt */ | |
41 | u_long cs_wedgecnt; /* times restarted */ | |
42 | } consoftc; | |
43 | ||
50fc34ca DA |
44 | int cnprobe(), cnattach(); |
45 | ||
46 | struct driver cndriver = { | |
47 | cnprobe, cnattach, "cn", | |
48 | }; | |
49 | ||
febf7236 WN |
50 | /* |
51 | * We check the console periodically to make sure | |
52 | * that it hasn't wedged. Unfortunately, if an XOFF | |
53 | * is typed on the console, that can't be distinguished | |
54 | * from more catastrophic failure. | |
55 | */ | |
56 | #define CN_TIMERVAL (hz) /* frequency at which to check cons */ | |
57 | #define CN_TIMO (2*60) /* intervals to allow for output char */ | |
58 | ||
59 | int cnstart(); | |
60 | int ttrstrt(); | |
61 | char partab[]; | |
62 | ||
63 | /* | |
64 | * Wait for CP to accept last CP command sent | |
65 | * before setting up next command. | |
66 | */ | |
67 | #define waitforlast(timo) { \ | |
68 | if (cnlast) { \ | |
69 | (timo) = 10000; \ | |
70 | do \ | |
71 | uncache((char *)&cnlast->cp_unit); \ | |
72 | while ((cnlast->cp_unit&CPTAKE) == 0 && --(timo)); \ | |
73 | } \ | |
74 | } | |
75 | ||
76 | u_char inb(); | |
77 | ||
50fc34ca DA |
78 | cnprobe(dev) |
79 | struct device *dev; | |
80 | { | |
81 | u_char c; | |
82 | int again = 0; | |
83 | ||
84 | /* Enable interrupts and keyboard controller */ | |
85 | while (inb(0x64)&2); outb(0x64,0x60); | |
86 | while (inb(0x64)&2); outb(0x60,0x4D); | |
87 | ||
88 | /* Start keyboard stuff RESET */ | |
89 | while (inb(0x64)&2); /* wait input ready */ | |
90 | outb(0x60,0xFF); /* RESET */ | |
91 | while((c=inb(0x60))!=0xFA) { | |
92 | if ((c == 0xFE) || (c == 0xFF)) { | |
93 | if(!again)printf("KEYBOARD disconnected: RECONNECT \n"); | |
94 | while (inb(0x64)&2); /* wait input ready */ | |
95 | outb(0x60,0xFF); /* RESET */ | |
96 | again = 1; | |
97 | } | |
98 | } | |
99 | if (again) printf("KEYBOARD Reconnected\n"); | |
100 | /* pick up keyboard reset return code */ | |
101 | sgetc(1); | |
102 | return 1; | |
103 | } | |
104 | ||
105 | cnattach(dev) | |
106 | struct device *dev; | |
107 | { | |
108 | INTREN(IRQ1); | |
109 | } | |
110 | ||
febf7236 WN |
111 | /*ARGSUSED*/ |
112 | cnopen(dev, flag) | |
113 | dev_t dev; | |
114 | { | |
115 | register struct tty *tp; | |
116 | int unit = minor(dev); | |
117 | ||
118 | tp = &cons; | |
119 | if (tp->t_state&TS_XCLUDE && u.u_uid != 0) | |
120 | return (EBUSY); | |
121 | tp->t_oproc = cnstart; | |
122 | if ((tp->t_state&TS_ISOPEN) == 0) { | |
123 | ttychars(tp); | |
124 | tp->t_state = TS_ISOPEN|TS_CARR_ON; | |
125 | tp->t_flags = EVENP|ECHO|XTABS|CRMOD; | |
febf7236 WN |
126 | splnone(); |
127 | } | |
128 | return ((*linesw[tp->t_line].l_open)(dev, tp)); | |
129 | } | |
130 | ||
131 | ||
132 | cnclose(dev) | |
133 | dev_t dev; | |
134 | { | |
135 | (*linesw[cons.t_line].l_close)(&cons); | |
136 | ttyclose(&cons); | |
137 | INTRDIS(IRQ1); | |
138 | } | |
139 | ||
140 | /*ARGSUSED*/ | |
141 | cnread(dev, uio) | |
142 | dev_t dev; | |
143 | struct uio *uio; | |
144 | { | |
145 | return ((*linesw[cons.t_line].l_read)(&cons, uio)); | |
146 | } | |
147 | ||
148 | /*ARGSUSED*/ | |
149 | cnwrite(dev, uio) | |
150 | dev_t dev; | |
151 | struct uio *uio; | |
152 | { | |
153 | return ((*linesw[cons.t_line].l_write)(&cons, uio)); | |
154 | } | |
155 | ||
156 | /* | |
157 | * Got a console receive interrupt - | |
158 | * the console processor wants to give us a character. | |
159 | * Catch the character, and see who it goes to. | |
160 | */ | |
161 | cnrint(dev) | |
162 | dev_t dev; | |
163 | { | |
164 | int c; | |
165 | ||
166 | c = sgetc(1); | |
167 | if (c&0x100)return; | |
168 | if (consoftc.cs_flags&CSF_POLLING) | |
169 | return; | |
170 | #ifdef KDB | |
171 | if (kdbrintr(c, &cons)) | |
172 | return; | |
173 | #endif | |
174 | (*linesw[cons.t_line].l_rint)(c&0xff, &cons); | |
175 | } | |
176 | ||
177 | cnioctl(dev, cmd, addr, flag) | |
178 | dev_t dev; | |
179 | caddr_t addr; | |
180 | { | |
181 | register struct tty *tp = &cons; | |
182 | register error; | |
183 | ||
184 | error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); | |
185 | if (error >= 0) | |
186 | return error; | |
187 | if ((error = ttioctl(tp, cmd, addr, flag)) < 0) | |
188 | error = ENOTTY; | |
189 | else if (cmd == TIOCSETP || cmd == TIOCSETN) | |
190 | cnparams(tp); | |
191 | return (error); | |
192 | } | |
193 | ||
194 | int consintr = 1; | |
195 | /* | |
196 | * Got a console transmission interrupt - | |
197 | * the console processor wants another character. | |
198 | */ | |
199 | cnxint(dev) | |
200 | dev_t dev; | |
201 | { | |
202 | register struct tty *tp; | |
203 | register int unit; | |
204 | ||
205 | if (!consintr) | |
206 | return; | |
207 | cons.t_state &= ~TS_BUSY; | |
208 | consoftc.cs_timo = 0; | |
209 | if (cons.t_line) | |
210 | (*linesw[cons.t_line].l_start)(&cons); | |
211 | else | |
212 | cnstart(&cons); | |
213 | } | |
214 | ||
215 | cnstart(tp) | |
216 | register struct tty *tp; | |
217 | { | |
218 | register c, s; | |
219 | ||
220 | s = spltty(); | |
221 | if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) | |
222 | goto out; | |
223 | if (tp->t_outq.c_cc <= TTLOWAT(tp)) { | |
224 | if (tp->t_state&TS_ASLEEP) { | |
225 | tp->t_state &= ~TS_ASLEEP; | |
226 | wakeup((caddr_t)&tp->t_outq); | |
227 | } | |
228 | if (tp->t_wsel) { | |
229 | selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); | |
230 | tp->t_wsel = 0; | |
231 | tp->t_state &= ~TS_WCOLL; | |
232 | } | |
233 | } | |
234 | while (tp->t_outq.c_cc != 0) { | |
235 | c = getc(&tp->t_outq) & 0xff; | |
236 | if ((tp->t_flags & (RAW|LITOUT)) == 0) { | |
237 | if (c > 0177) | |
238 | { | |
239 | timeout(ttrstrt, (caddr_t)tp, (c&0177)); | |
240 | tp->t_state |= TS_TIMEOUT; | |
241 | break; | |
242 | } | |
243 | c &= 0177; | |
244 | } | |
50fc34ca DA |
245 | splx(s); |
246 | sput(c,0x7); | |
247 | s = spltty(); | |
febf7236 WN |
248 | } |
249 | out: | |
250 | splx(s); | |
251 | } | |
252 | ||
253 | cnputc(c) | |
254 | char c; | |
255 | { | |
febf7236 | 256 | if (c == '\n') |
50fc34ca DA |
257 | sput('\r',0x3); |
258 | sput(c, 0x3); | |
febf7236 WN |
259 | } |
260 | ||
261 | /* | |
262 | * Print a character on console. | |
263 | */ | |
264 | cnputchar(c, tp) | |
265 | char c; | |
266 | register struct tty *tp; | |
267 | { | |
50fc34ca | 268 | sput(c,0x2); |
febf7236 WN |
269 | if (c=='\n') getchar(); |
270 | } | |
271 | ||
272 | ||
273 | cngetc() | |
274 | { | |
275 | register int c, s; | |
276 | ||
277 | s = spltty(); /* block cnrint while we poll */ | |
50fc34ca DA |
278 | c = sgetc(0); |
279 | if (c == '\r') c = '\n'; | |
febf7236 WN |
280 | splx(s); |
281 | return (c); | |
282 | } | |
283 | ||
284 | cngetchar(tp) | |
285 | register struct tty *tp; | |
286 | { | |
287 | int c; | |
288 | ||
289 | c = sgetc(0); | |
290 | return (c&0xff); | |
291 | } | |
292 | ||
293 | /* | |
294 | * Set line parameters | |
295 | */ | |
296 | cnparams(tp) | |
297 | register struct tty *tp; | |
298 | { | |
299 | } | |
300 | ||
301 | #ifdef KDB | |
302 | /* | |
303 | * Turn input polling on/off (used by debugger). | |
304 | */ | |
305 | cnpoll(onoff) | |
306 | int onoff; | |
307 | { | |
308 | } | |
309 | #endif | |
310 | ||
50fc34ca DA |
311 | extern int hz; |
312 | ||
313 | sysbeepstop() | |
314 | { | |
315 | /* disable counter 2 */ | |
316 | outb(0x61,inb(0x61)&0xFC); | |
317 | } | |
318 | ||
319 | sysbeep() | |
320 | { | |
321 | /* enable counter 2 */ | |
322 | outb(0x61,inb(0x61)|3); | |
323 | /* set command for counter 2, 2 byte write */ | |
324 | outb(0x43,0xB6); | |
325 | /* send 0x637 for 750 HZ */ | |
326 | outb(0x42,0x37); | |
327 | outb(0x42,0x06); | |
328 | timeout(sysbeepstop,0,hz/4); | |
329 | } | |
330 | ||
febf7236 WN |
331 | #define COL 80 |
332 | #define ROW 25 | |
333 | #define CHR 2 | |
50fc34ca DA |
334 | #define MONO_BASE 0x3B4 |
335 | #define MONO_BUF 0xB0000 | |
336 | #define CGA_BASE 0x3D4 | |
337 | #define CGA_BUF 0xB8000 | |
338 | #define IOPHYSMEM 0xA0000 | |
febf7236 | 339 | |
febf7236 | 340 | u_char color = 0xe ; |
50fc34ca DA |
341 | static unsigned int addr_6845; |
342 | u_short *Crtat = (u_short *)MONO_BUF; | |
343 | ||
344 | /* cursor() sets an offset (0-1999) into the 80x25 text area */ | |
345 | /* Theoretically there should be a slight delay between outb's */ | |
346 | /* and if your display has cursor problems that may be it. */ | |
347 | /* This may have to be left as is since it is done after every */ | |
348 | /* char and can seriously affect performance . */ | |
349 | ||
350 | cursor(pos) | |
351 | int pos; | |
352 | { | |
353 | outb(addr_6845,14); | |
354 | outb(addr_6845+1,pos >> 8); | |
355 | outb(addr_6845,15); | |
356 | outb(addr_6845+1,pos&0xff); | |
357 | } | |
358 | ||
359 | /* sput has support for emulation of the 'ibmpc' termcap entry. */ | |
360 | /* This is a bare-bones implementation of a bare-bones entry */ | |
361 | /* One modification: Change li#24 to li#25 to reflect 25 lines */ | |
362 | /* sput tries to do 16-bit writes. This may not work on all. */ | |
363 | ||
364 | sput(c, ca) | |
365 | u_char c, ca; | |
366 | { | |
febf7236 | 367 | |
50fc34ca DA |
368 | static int esc,ebrac,eparm,cx,cy,row,so; |
369 | static u_short *crtat = 0; | |
370 | int s; | |
febf7236 | 371 | |
50fc34ca DA |
372 | s = splnone(); |
373 | ||
374 | /* | |
375 | if(inb(0x64)&1)sgetc(1); | |
376 | */ | |
febf7236 | 377 | if (crtat == 0) { |
50fc34ca DA |
378 | |
379 | /* Crtat initialized to point to MONO buffer */ | |
380 | /* if not present change to CGA_BUF offset */ | |
381 | /* ONLY ADD the difference since locore.s adds */ | |
382 | /* in the remapped offset at the right time */ | |
383 | ||
384 | *Crtat = (u_short) 0xA55A; | |
385 | if (*Crtat != 0xA55A) { | |
386 | Crtat = Crtat + (CGA_BUF-MONO_BUF)/CHR; | |
387 | addr_6845 = CGA_BASE; | |
388 | } else addr_6845 = MONO_BASE; | |
389 | crtat = Crtat; bzero (crtat,COL*ROW*CHR); | |
febf7236 | 390 | } |
febf7236 | 391 | switch(c) { |
50fc34ca DA |
392 | case 0x1B: |
393 | esc = 1; ebrac = 0; eparm = 0; | |
394 | break; | |
febf7236 WN |
395 | |
396 | case '\t': | |
397 | do { | |
398 | *crtat++ = (ca<<8)| ' '; row++ ; | |
399 | } while (row %8); | |
400 | break; | |
401 | ||
402 | case '\010': | |
403 | crtat--; row--; | |
50fc34ca | 404 | if (row < 0) row += COL; /* non-destructive backspace */ |
febf7236 WN |
405 | break; |
406 | ||
407 | case '\r': | |
50fc34ca | 408 | crtat -= row ; row = 0; |
febf7236 WN |
409 | break; |
410 | ||
411 | case '\n': | |
febf7236 WN |
412 | crtat += COL ; |
413 | break; | |
414 | ||
415 | default: | |
50fc34ca DA |
416 | if (esc) { |
417 | if (ebrac) { | |
418 | switch(c) { | |
419 | case 'm': /* no support for standout */ | |
420 | if (!cx) so = 0; | |
421 | else so = 1; | |
422 | esc = 0; ebrac = 0; eparm = 0; | |
423 | break; | |
424 | case 'A': /* back one row */ | |
425 | crtat -= COL; | |
426 | esc = 0; ebrac = 0; eparm = 0; | |
427 | break; | |
428 | case 'B': /* down one row */ | |
429 | crtat += COL; | |
430 | esc = 0; ebrac = 0; eparm = 0; | |
431 | break; | |
432 | case 'C': /* right cursor */ | |
433 | crtat++; row++; | |
434 | esc = 0; ebrac = 0; eparm = 0; | |
435 | break; | |
436 | case 'J': /* Clear to end of display */ | |
437 | bzero(crtat,(Crtat+COL*ROW-crtat)*CHR); | |
438 | esc = 0; ebrac = 0; eparm = 0; | |
439 | break; | |
440 | case 'K': /* Clear to EOL */ | |
441 | bzero(crtat,(COL-row)*CHR); | |
442 | esc = 0; ebrac = 0; eparm = 0; | |
443 | break; | |
444 | case 'H': /* Cursor move */ | |
445 | if ((!cx)||(!cy)) { | |
446 | crtat = Crtat; | |
447 | row = 0; | |
448 | } else { | |
449 | crtat = Crtat+(cx-1)*COL+cy-1; | |
450 | row = cy-1; | |
451 | } | |
452 | esc = 0; ebrac = 0; eparm = 0; | |
453 | break; | |
454 | case ';': /* Switch params in cursor def */ | |
455 | eparm = 1; | |
456 | splx(s); | |
457 | return; | |
458 | default: /* Only numbers valid here */ | |
459 | if ((c >= '0')&&(c <= '9')) { | |
460 | if (eparm) { | |
461 | cy *= 10; | |
462 | cy += c - '0'; | |
463 | } else { | |
464 | cx *= 10; | |
465 | cx += c - '0'; | |
466 | } | |
467 | } else { | |
468 | esc = 0; ebrac = 0; eparm = 0; | |
469 | } | |
470 | splx(s); | |
471 | return; | |
472 | } | |
473 | break; | |
474 | } else if (c == 'c') { /* Clear screen & home */ | |
475 | bzero(Crtat,COL*ROW*CHR); | |
476 | crtat = Crtat; row = 0; | |
477 | esc = 0; ebrac = 0; eparm = 0; | |
478 | }else if (c == '[') { /* Start ESC [ sequence */ | |
479 | ebrac = 1; cx = 0; cy = 0; eparm = 0; | |
480 | }else{ /* Invalid, clear state */ | |
481 | esc = 0; ebrac = 0; eparm = 0; | |
482 | } | |
483 | } else { | |
484 | if (c == 7) { | |
485 | sysbeep(); | |
486 | } | |
487 | /* Print only printables */ | |
488 | else if (c >= ' ') { | |
489 | if (so) { | |
490 | *crtat++ = 0x7000| c; row++ ; | |
491 | } else { | |
492 | *crtat++ = (ca<<8)| c; row++ ; | |
493 | } | |
494 | if (row >= COL) row = 0; | |
495 | break ; | |
496 | } | |
febf7236 | 497 | } |
febf7236 | 498 | } |
50fc34ca DA |
499 | if (crtat >= Crtat+COL*(ROW)) { /* scroll check */ |
500 | bcopy(Crtat+COL,Crtat,COL*(ROW-1)*CHR); | |
501 | bzero (Crtat+COL*(ROW-1),COL*CHR) ; | |
502 | crtat -= COL ; | |
503 | } | |
504 | cursor(crtat-Crtat); | |
505 | splx(s); | |
febf7236 | 506 | } |
50fc34ca DA |
507 | |
508 | ||
509 | ||
febf7236 WN |
510 | #define L 0x0001 /* locking function */ |
511 | #define SHF 0x0002 /* keyboard shift */ | |
512 | #define ALT 0x0004 /* alternate shift -- alternate chars */ | |
513 | #define NUM 0x0008 /* numeric shift cursors vs. numeric */ | |
514 | #define CTL 0x0010 /* control shift -- allows ctl function */ | |
515 | #define CPS 0x0020 /* caps shift -- swaps case of letter */ | |
516 | #define ASCII 0x0040 /* ascii code for this key */ | |
517 | #define STP 0x0080 /* stop output */ | |
518 | #define FUNC 0x0100 /* function key */ | |
50fc34ca | 519 | #define SCROLL 0x0200 /* scroll lock key */ |
febf7236 | 520 | |
50fc34ca | 521 | unsigned __debug = 0 ; |
febf7236 WN |
522 | u_short action[] = { |
523 | 0, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 0- 7 */ | |
524 | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 8-15 */ | |
525 | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 16-23 */ | |
526 | ASCII, ASCII, ASCII, ASCII, ASCII, CTL, ASCII, ASCII, /* scan 24-31 */ | |
527 | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 32-39 */ | |
528 | ASCII, ASCII, SHF , ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 40-47 */ | |
529 | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, SHF, ASCII, /* scan 48-55 */ | |
50fc34ca DA |
530 | ALT, ASCII, CPS , FUNC , FUNC , FUNC , FUNC , FUNC , /* scan 56-63 */ |
531 | FUNC , FUNC , FUNC , FUNC , FUNC , NUM, STP, ASCII, /* scan 64-71 */ | |
febf7236 WN |
532 | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 72-79 */ |
533 | ASCII, ASCII, ASCII, ASCII, 0, 0, 0, 0, /* scan 80-87 */ | |
534 | 0,0,0,0,0,0,0,0, | |
535 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, | |
536 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; | |
537 | ||
538 | u_char unshift[] = { /* no shift */ | |
539 | 0, 033 , '1' , '2' , '3' , '4' , '5' , '6' , /* scan 0- 7 */ | |
540 | '7' , '8' , '9' , '0' , '-' , '=' , 0177 ,'\t' , /* scan 8-15 */ | |
541 | ||
542 | 'q' , 'w' , 'e' , 'r' , 't' , 'y' , 'u' , 'i' , /* scan 16-23 */ | |
543 | 'o' , 'p' , '[' , ']' , '\r' , CTL , 'a' , 's' , /* scan 24-31 */ | |
544 | ||
545 | 'd' , 'f' , 'g' , 'h' , 'j' , 'k' , 'l' , ';' , /* scan 32-39 */ | |
546 | '\'' , '`' , SHF , '\\' , 'z' , 'x' , 'c' , 'v' , /* scan 40-47 */ | |
547 | ||
548 | 'b' , 'n' , 'm' , ',' , '.' , '/' , SHF , '*', /* scan 48-55 */ | |
50fc34ca | 549 | ALT , ' ' , CPS, 1, 2, 3 , 4, 5, /* scan 56-63 */ |
febf7236 | 550 | |
50fc34ca | 551 | 6, 7, 8, 9, 10, NUM, STP, '7', /* scan 64-71 */ |
febf7236 WN |
552 | '8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */ |
553 | ||
554 | '2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */ | |
555 | 0,0,0,0,0,0,0,0, | |
556 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, | |
557 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; | |
558 | ||
559 | u_char shift[] = { /* shift shift */ | |
560 | 0, 033 , '!' , '@' , '#' , '$' , '%' , '^' , /* scan 0- 7 */ | |
561 | '&' , '*' , '(' , ')' , '_' , '+' , 0177 ,'\t' , /* scan 8-15 */ | |
562 | 'Q' , 'W' , 'E' , 'R' , 'T' , 'Y' , 'U' , 'I' , /* scan 16-23 */ | |
563 | 'O' , 'P' , '{' , '}' , '\r' , CTL , 'A' , 'S' , /* scan 24-31 */ | |
564 | 'D' , 'F' , 'G' , 'H' , 'J' , 'K' , 'L' , ':' , /* scan 32-39 */ | |
565 | '"' , '~' , SHF , '|' , 'Z' , 'X' , 'C' , 'V' , /* scan 40-47 */ | |
566 | 'B' , 'N' , 'M' , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */ | |
50fc34ca DA |
567 | ALT , ' ' , CPS, 0, 0, ' ' , 0, 0, /* scan 56-63 */ |
568 | 0, 0, 0, 0, 0, NUM, STP, '7', /* scan 64-71 */ | |
febf7236 WN |
569 | '8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */ |
570 | '2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */ | |
571 | 0,0,0,0,0,0,0,0, | |
572 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, | |
573 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; | |
574 | ||
575 | u_char ctl[] = { /* CTL shift */ | |
576 | 0, 033 , '!' , 000 , '#' , '$' , '%' , 036 , /* scan 0- 7 */ | |
577 | '&' , '*' , '(' , ')' , 037 , '+' , 034 ,'\177', /* scan 8-15 */ | |
578 | 021 , 027 , 005 , 022 , 024 , 031 , 025 , 011 , /* scan 16-23 */ | |
579 | 017 , 020 , 033 , 035 , '\r' , CTL , 001 , 023 , /* scan 24-31 */ | |
580 | 004 , 006 , 007 , 010 , 012 , 013 , 014 , ';' , /* scan 32-39 */ | |
581 | '\'' , '`' , SHF , 034 , 032 , 030 , 003 , 026 , /* scan 40-47 */ | |
582 | 002 , 016 , 015 , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */ | |
50fc34ca DA |
583 | ALT , ' ' , CPS, 0, 0, ' ' , 0, 0, /* scan 56-63 */ |
584 | CPS, 0, 0, 0, 0, 0, 0, 0, /* scan 64-71 */ | |
febf7236 WN |
585 | 0, 0, 0, 0, 0, 0, 0, 0, /* scan 72-79 */ |
586 | 0, 0, 0, 0, 0, 0, 0, 0, /* scan 80-87 */ | |
50fc34ca DA |
587 | 0, 0, 033, '7' , '4' , '1' , 0, NUM, /* scan 88-95 */ |
588 | '8' , '5' , '2' , 0, STP, '9' , '6' , '3' , /*scan 96-103*/ | |
febf7236 WN |
589 | '.' , 0, '*' , '-' , '+' , 0, 0, 0, /*scan 104-111*/ |
590 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; | |
591 | ||
592 | #ifdef notdef | |
593 | struct key { | |
594 | u_short action; /* how this key functions */ | |
595 | char ascii[8]; /* ascii result character indexed by shifts */ | |
596 | }; | |
597 | #endif | |
598 | ||
50fc34ca | 599 | u_char shfts, ctls, alts, caps, num, stp, scroll; |
febf7236 | 600 | |
50fc34ca DA |
601 | #define KBSTAT 0x64 /* kbd status port */ |
602 | #define KBS_INP_BUF_FUL 0x02 /* kbd char ready */ | |
603 | #define KBDATA 0x60 /* kbd data port */ | |
febf7236 WN |
604 | #define KBSTATUSPORT 0x61 /* kbd status */ |
605 | ||
50fc34ca DA |
606 | update_led() |
607 | { | |
608 | while (inb(0x64)&2); /* wait input ready */ | |
609 | outb(0x60,0xED); /* LED Command */ | |
610 | while (inb(0x64)&2); /* wait input ready */ | |
611 | outb(0x60,scroll | 2*num | 4*caps); | |
612 | } | |
febf7236 | 613 | |
50fc34ca DA |
614 | /* |
615 | sgetc(noblock) : get a character from the keyboard. If noblock = 0 wait until | |
616 | a key is gotten. Otherwise return a 0x100 (256). | |
617 | */ | |
618 | int sgetc(noblock) | |
619 | { | |
620 | u_char dt; unsigned key; | |
febf7236 | 621 | loop: |
50fc34ca DA |
622 | /* First see if there is something in the keyboard port */ |
623 | if (inb(KBSTAT)&1) dt = inb(KBDATA); | |
624 | else { if (noblock) return (0x100); else goto loop; } | |
625 | ||
626 | /* Check for cntl-alt-del */ | |
627 | if ((dt == 83)&&ctls&&alts) _exit(); | |
628 | ||
629 | /* Check for make/break */ | |
630 | if (dt & 0x80) { | |
631 | /* break */ | |
632 | dt = dt & 0x7f ; | |
633 | switch (action[dt]) { | |
634 | case SHF: shfts = 0; break; | |
635 | case ALT: alts = 0; break; | |
636 | case CTL: ctls = 0; break; | |
637 | case FUNC: | |
638 | /* Toggle debug flags */ | |
639 | key = unshift[dt]; | |
640 | if(__debug & (1<<key)) __debug &= ~(1<<key) ; | |
641 | else __debug |= (1<<key) ; | |
642 | break; | |
643 | } | |
644 | } else { | |
645 | /* make */ | |
646 | dt = dt & 0x7f ; | |
647 | switch (action[dt]) { | |
648 | /* LOCKING KEYS */ | |
649 | case NUM: num ^= 1; update_led(); break; | |
650 | case CPS: caps ^= 1; update_led(); break; | |
651 | case SCROLL: scroll ^= 1; update_led(); break; | |
652 | case STP: stp ^= 1; if(stp) goto loop; break; | |
653 | ||
654 | /* NON-LOCKING KEYS */ | |
655 | case SHF: shfts = 1; break; | |
656 | case ALT: alts = 1; break; | |
657 | case CTL: ctls = 1; break; | |
658 | case ASCII: | |
659 | if (shfts) dt = shift[dt]; | |
660 | else if (ctls) dt = ctl[dt]; | |
661 | else dt = unshift[dt]; | |
662 | if (caps && (dt >= 'a' && dt <= 'z')) dt -= 'a' - 'A'; | |
663 | return(dt); | |
febf7236 | 664 | } |
febf7236 | 665 | } |
50fc34ca | 666 | if (noblock) return (0x100); else goto loop; |
febf7236 WN |
667 | } |
668 | ||
669 | pg(p,q,r,s,t,u,v,w,x,y,z) char *p; { | |
670 | printf(p,q,r,s,t,u,v,w,x,y,z); | |
671 | printf("\n"); | |
672 | return(getchar()); | |
673 | } | |
674 | ||
675 | /* special characters */ | |
676 | #define bs 8 | |
677 | #define lf 10 | |
678 | #define cr 13 | |
679 | #define cntlc 3 | |
680 | #define del 0177 | |
681 | #define cntld 4 | |
682 | ||
683 | getchar() | |
684 | { | |
685 | register char thechar; | |
686 | register delay; | |
687 | int x; | |
688 | ||
689 | consoftc.cs_flags |= CSF_POLLING; | |
690 | x=splhigh(); | |
50fc34ca | 691 | sput('>',0x6); |
febf7236 WN |
692 | while (1) { |
693 | thechar = (char) sgetc(0); | |
50fc34ca DA |
694 | consoftc.cs_flags &= ~CSF_POLLING; |
695 | splx(x); | |
febf7236 WN |
696 | switch (thechar) { |
697 | default: if (thechar >= ' ') | |
50fc34ca | 698 | sput(thechar,0x6); |
febf7236 WN |
699 | return(thechar); |
700 | case cr: | |
50fc34ca DA |
701 | case lf: sput(cr,0x6); |
702 | sput(lf,0x6); | |
febf7236 WN |
703 | return(lf); |
704 | case bs: | |
705 | case del: | |
50fc34ca DA |
706 | sput(bs,0x6); |
707 | sput(' ',0x6); | |
708 | sput(bs,0x6); | |
febf7236 | 709 | return(thechar); |
50fc34ca | 710 | /*case cntlc: |
febf7236 | 711 | sput('^',0xe) ; sput('C',0xe) ; sput('\r',0xe) ; sput('\n',0xe) ; |
50fc34ca | 712 | _exit(-2) ; */ |
febf7236 | 713 | case cntld: |
50fc34ca | 714 | sput('^',0x6) ; sput('D',0x6) ; sput('\r',0x6) ; sput('\n',0x6) ; |
febf7236 WN |
715 | return(0); |
716 | } | |
717 | } | |
718 | } |