new copyright notice
[unix-history] / usr / src / sys / i386 / isa / pccons.c
CommitLineData
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 *
8 * %sccs.include.386.c%
9 *
10 * @(#)pccons.c 5.1 (Berkeley) %G%
11 */
12
13/*
14 * code to work keyboard & display for console
15 */
16#include "param.h"
17#include "conf.h"
18#include "dir.h"
19#include "ioctl.h"
20#include "user.h"
21#include "proc.h"
22#include "tty.h"
23#include "uio.h"
24#include "callout.h"
25#include "systm.h"
26#include "kernel.h"
27#include "syslog.h"
28#include "icu.h"
29
30struct tty cons;
31
32struct consoftc {
33 char cs_flags;
34#define CSF_ACTIVE 0x1 /* timeout active */
35#define CSF_POLLING 0x2 /* polling for input */
36 char cs_lastc; /* last char sent */
37 int cs_timo; /* timeouts since interrupt */
38 u_long cs_wedgecnt; /* times restarted */
39} consoftc;
40
41/*
42 * We check the console periodically to make sure
43 * that it hasn't wedged. Unfortunately, if an XOFF
44 * is typed on the console, that can't be distinguished
45 * from more catastrophic failure.
46 */
47#define CN_TIMERVAL (hz) /* frequency at which to check cons */
48#define CN_TIMO (2*60) /* intervals to allow for output char */
49
50int cnstart();
51int ttrstrt();
52char partab[];
53
54/*
55 * Wait for CP to accept last CP command sent
56 * before setting up next command.
57 */
58#define waitforlast(timo) { \
59 if (cnlast) { \
60 (timo) = 10000; \
61 do \
62 uncache((char *)&cnlast->cp_unit); \
63 while ((cnlast->cp_unit&CPTAKE) == 0 && --(timo)); \
64 } \
65}
66
67u_char inb();
68
69/*ARGSUSED*/
70cnopen(dev, flag)
71 dev_t dev;
72{
73 register struct tty *tp;
74 int unit = minor(dev);
75
76 tp = &cons;
77 if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
78 return (EBUSY);
79 tp->t_oproc = cnstart;
80 if ((tp->t_state&TS_ISOPEN) == 0) {
81 ttychars(tp);
82 tp->t_state = TS_ISOPEN|TS_CARR_ON;
83 tp->t_flags = EVENP|ECHO|XTABS|CRMOD;
84 INTREN(IRQ1);
85 splnone();
86 }
87 return ((*linesw[tp->t_line].l_open)(dev, tp));
88}
89
90
91cnclose(dev)
92 dev_t dev;
93{
94 (*linesw[cons.t_line].l_close)(&cons);
95 ttyclose(&cons);
96 INTRDIS(IRQ1);
97}
98
99/*ARGSUSED*/
100cnread(dev, uio)
101 dev_t dev;
102 struct uio *uio;
103{
104 return ((*linesw[cons.t_line].l_read)(&cons, uio));
105}
106
107/*ARGSUSED*/
108cnwrite(dev, uio)
109 dev_t dev;
110 struct uio *uio;
111{
112 return ((*linesw[cons.t_line].l_write)(&cons, uio));
113}
114
115/*
116 * Got a console receive interrupt -
117 * the console processor wants to give us a character.
118 * Catch the character, and see who it goes to.
119 */
120cnrint(dev)
121 dev_t dev;
122{
123 int c;
124
125 c = sgetc(1);
126 if (c&0x100)return;
127 if (consoftc.cs_flags&CSF_POLLING)
128 return;
129#ifdef KDB
130 if (kdbrintr(c, &cons))
131 return;
132#endif
133 (*linesw[cons.t_line].l_rint)(c&0xff, &cons);
134}
135
136cnioctl(dev, cmd, addr, flag)
137 dev_t dev;
138 caddr_t addr;
139{
140 register struct tty *tp = &cons;
141 register error;
142
143 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
144 if (error >= 0)
145 return error;
146 if ((error = ttioctl(tp, cmd, addr, flag)) < 0)
147 error = ENOTTY;
148 else if (cmd == TIOCSETP || cmd == TIOCSETN)
149 cnparams(tp);
150 return (error);
151}
152
153int consintr = 1;
154/*
155 * Got a console transmission interrupt -
156 * the console processor wants another character.
157 */
158cnxint(dev)
159 dev_t dev;
160{
161 register struct tty *tp;
162 register int unit;
163
164 if (!consintr)
165 return;
166 cons.t_state &= ~TS_BUSY;
167 consoftc.cs_timo = 0;
168 if (cons.t_line)
169 (*linesw[cons.t_line].l_start)(&cons);
170 else
171 cnstart(&cons);
172}
173
174cnstart(tp)
175 register struct tty *tp;
176{
177 register c, s;
178
179 s = spltty();
180 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
181 goto out;
182 if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
183 if (tp->t_state&TS_ASLEEP) {
184 tp->t_state &= ~TS_ASLEEP;
185 wakeup((caddr_t)&tp->t_outq);
186 }
187 if (tp->t_wsel) {
188 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
189 tp->t_wsel = 0;
190 tp->t_state &= ~TS_WCOLL;
191 }
192 }
193 while (tp->t_outq.c_cc != 0) {
194 c = getc(&tp->t_outq) & 0xff;
195 if ((tp->t_flags & (RAW|LITOUT)) == 0) {
196 if (c > 0177)
197 {
198 timeout(ttrstrt, (caddr_t)tp, (c&0177));
199 tp->t_state |= TS_TIMEOUT;
200 break;
201 }
202 c &= 0177;
203 }
204 sput(c,0xc);
205 }
206out:
207 splx(s);
208}
209
210cnputc(c)
211 char c;
212{
213
214 if (c == '\n')
215 sput('\r',0xb);
216 sput(c, 0xb);
217}
218
219/*
220 * Print a character on console.
221 */
222cnputchar(c, tp)
223 char c;
224 register struct tty *tp;
225{
226 sput(c,0xa);
227 if (c=='\n') getchar();
228}
229
230
231cngetc()
232{
233 register int c, s;
234
235 s = spltty(); /* block cnrint while we poll */
236 if (c == '\r')
237 c = '\n';
238 splx(s);
239 return (c);
240}
241
242cngetchar(tp)
243 register struct tty *tp;
244{
245 int c;
246
247 c = sgetc(0);
248 return (c&0xff);
249}
250
251/*
252 * Set line parameters
253 */
254cnparams(tp)
255 register struct tty *tp;
256{
257}
258
259#ifdef KDB
260/*
261 * Turn input polling on/off (used by debugger).
262 */
263cnpoll(onoff)
264 int onoff;
265{
266}
267#endif
268
269#define CRT_TXTADDR Crtat
270#define COL 80
271#define ROW 25
272#define CHR 2
273
274
275u_short *Crtat = ((u_short *)0xb8000);
276u_short *crtat ;
277u_char color = 0xe ;
278int row;
279
280sput(c, ca) u_char c, ca; {
281
282 if(inb(0x64)&2 == 0)sgetc(1);
283 if (crtat == 0) {
284 INTREN(IRQ1); /* XXX */
285 crtat = CRT_TXTADDR; bzero (crtat,COL*ROW*CHR);
286 }
287 /*if (crtat >= (CRT_TXTADDR+COL*(ROW-1))) {
288 crtat = CRT_TXTADDR+COL*(ROW-1); row = 0;
289 }*/
290 if (crtat >= CRT_TXTADDR+COL*(ROW-1)) { /* scroll */
291 bcopy(CRT_TXTADDR+COL, CRT_TXTADDR,COL*(ROW-1)*CHR);
292 bzero (CRT_TXTADDR+COL*(ROW-1),COL*CHR) ;
293 crtat -= COL ;
294 }
295 switch(c) {
296
297 case '\t':
298 do {
299 *crtat++ = (ca<<8)| ' '; row++ ;
300 } while (row %8);
301 break;
302
303 case '\010':
304 crtat--; row--;
305 break;
306
307 case '\r':
308 /*bzero (crtat,(COL-row)*CHR) ;*/ crtat -= row ; row = 0;
309 break;
310
311 case '\n':
312 if (crtat >= CRT_TXTADDR+COL*(ROW-1)) { /* scroll */
313 bcopy(CRT_TXTADDR+COL, CRT_TXTADDR,COL*(ROW-1)*CHR);
314 bzero (CRT_TXTADDR+COL*(ROW-1),COL*CHR) ;
315 crtat -= COL ;
316 }
317 crtat += COL ;
318 break;
319
320 default:
321 *crtat++ = (ca<<8)| c; row++ ;
322 if (row >= COL) {
323 /*bzero (crtat,(COL-row)*CHR) ;*/ crtat -= row ; row = 0;
324 if (crtat >= CRT_TXTADDR+COL*(ROW-1)) { /* scroll */
325 bcopy(CRT_TXTADDR+COL, CRT_TXTADDR,COL*(ROW-1)*CHR);
326 bzero (CRT_TXTADDR+COL*(ROW-1),COL*CHR) ;
327 crtat -= COL ;
328 }
329 crtat += COL ;
330 }
331 break ;
332 }
333}
334#define L 0x0001 /* locking function */
335#define SHF 0x0002 /* keyboard shift */
336#define ALT 0x0004 /* alternate shift -- alternate chars */
337#define NUM 0x0008 /* numeric shift cursors vs. numeric */
338#define CTL 0x0010 /* control shift -- allows ctl function */
339#define CPS 0x0020 /* caps shift -- swaps case of letter */
340#define ASCII 0x0040 /* ascii code for this key */
341#define STP 0x0080 /* stop output */
342#define FUNC 0x0100 /* function key */
343#define SYSREQ 0x0200 /* sys req key */
344
345unsigned __debug ;
346u_short action[] = {
3470, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 0- 7 */
348ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 8-15 */
349ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 16-23 */
350ASCII, ASCII, ASCII, ASCII, ASCII, CTL, ASCII, ASCII, /* scan 24-31 */
351ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 32-39 */
352ASCII, ASCII, SHF , ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 40-47 */
353ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, SHF, ASCII, /* scan 48-55 */
354 ALT, ASCII, CPS|L, FUNC , FUNC , FUNC , FUNC , FUNC , /* scan 56-63 */
355FUNC , FUNC , FUNC , FUNC , FUNC , NUM|L, STP|L, ASCII, /* scan 64-71 */
356ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 72-79 */
357ASCII, ASCII, ASCII, ASCII, 0, 0, 0, 0, /* scan 80-87 */
3580,0,0,0,0,0,0,0,
3590,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
3600,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
361
362u_char unshift[] = { /* no shift */
3630, 033 , '1' , '2' , '3' , '4' , '5' , '6' , /* scan 0- 7 */
364'7' , '8' , '9' , '0' , '-' , '=' , 0177 ,'\t' , /* scan 8-15 */
365
366'q' , 'w' , 'e' , 'r' , 't' , 'y' , 'u' , 'i' , /* scan 16-23 */
367'o' , 'p' , '[' , ']' , '\r' , CTL , 'a' , 's' , /* scan 24-31 */
368
369'd' , 'f' , 'g' , 'h' , 'j' , 'k' , 'l' , ';' , /* scan 32-39 */
370'\'' , '`' , SHF , '\\' , 'z' , 'x' , 'c' , 'v' , /* scan 40-47 */
371
372'b' , 'n' , 'm' , ',' , '.' , '/' , SHF , '*', /* scan 48-55 */
373ALT , ' ' , CPS|L, 1, 2, 3 , 4, 5, /* scan 56-63 */
374
375 6, 7, 8, 9, 10, NUM|L, STP|L, '7', /* scan 64-71 */
376 '8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */
377
378 '2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */
3790,0,0,0,0,0,0,0,
3800,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
3810,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
382
383u_char shift[] = { /* shift shift */
3840, 033 , '!' , '@' , '#' , '$' , '%' , '^' , /* scan 0- 7 */
385'&' , '*' , '(' , ')' , '_' , '+' , 0177 ,'\t' , /* scan 8-15 */
386'Q' , 'W' , 'E' , 'R' , 'T' , 'Y' , 'U' , 'I' , /* scan 16-23 */
387'O' , 'P' , '{' , '}' , '\r' , CTL , 'A' , 'S' , /* scan 24-31 */
388'D' , 'F' , 'G' , 'H' , 'J' , 'K' , 'L' , ':' , /* scan 32-39 */
389'"' , '~' , SHF , '|' , 'Z' , 'X' , 'C' , 'V' , /* scan 40-47 */
390'B' , 'N' , 'M' , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */
391ALT , ' ' , CPS|L, 0, 0, ' ' , 0, 0, /* scan 56-63 */
392 0, 0, 0, 0, 0, NUM|L, STP|L, '7', /* scan 64-71 */
393 '8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */
394 '2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */
3950,0,0,0,0,0,0,0,
3960,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
3970,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
398
399u_char ctl[] = { /* CTL shift */
4000, 033 , '!' , 000 , '#' , '$' , '%' , 036 , /* scan 0- 7 */
401'&' , '*' , '(' , ')' , 037 , '+' , 034 ,'\177', /* scan 8-15 */
402021 , 027 , 005 , 022 , 024 , 031 , 025 , 011 , /* scan 16-23 */
403017 , 020 , 033 , 035 , '\r' , CTL , 001 , 023 , /* scan 24-31 */
404004 , 006 , 007 , 010 , 012 , 013 , 014 , ';' , /* scan 32-39 */
405'\'' , '`' , SHF , 034 , 032 , 030 , 003 , 026 , /* scan 40-47 */
406002 , 016 , 015 , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */
407ALT , ' ' , CPS|L, 0, 0, ' ' , 0, 0, /* scan 56-63 */
408CPS|L, 0, 0, 0, 0, 0, 0, 0, /* scan 64-71 */
409 0, 0, 0, 0, 0, 0, 0, 0, /* scan 72-79 */
410 0, 0, 0, 0, 0, 0, 0, 0, /* scan 80-87 */
411 0, 0, 033, '7' , '4' , '1' , 0, NUM|L, /* scan 88-95 */
412'8' , '5' , '2' , 0, STP|L, '9' , '6' , '3' , /*scan 96-103*/
413'.' , 0, '*' , '-' , '+' , 0, 0, 0, /*scan 104-111*/
4140,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
415
416#ifdef notdef
417struct key {
418 u_short action; /* how this key functions */
419 char ascii[8]; /* ascii result character indexed by shifts */
420};
421#endif
422
423u_char shfts, ctls, alts, caps, num, stp;
424
425#define KBSTATP 0x64 /* kbd status port */
426#define KBS_INP_BUF_FUL 0x02 /* kbd char ready */
427#define KBDATAP 0x60 /* kbd data port */
428#define KBSTATUSPORT 0x61 /* kbd status */
429
430u_char odt;
431
432int sgetc(on) {
433 u_char dt, brk;
434 u_short act;
435
436loop:
437 do {
438 while (inb(0x64)&2) ;
439 dt = inb(0x60);
440 } while (dt == odt);
441 odt = dt;
442if(dt == 0x54) _exit();
443 brk = dt & 0x80 ; dt = dt & 0x7f ;
444
445 act = action[dt];
446 if (act&SHF) {
447 if(brk) shfts = 0; else shfts = 1;
448 }
449 if (act&ALT) {
450 if(brk) alts = 0; else alts = 1;
451 }
452 if (act&NUM) {
453 if (act&L) {
454 if(!brk) num ^= 1;
455 } else if(brk) num = 0; else num = 1;
456 }
457 if (act&CTL) {
458 if(brk) ctls = 0; else ctls = 1;
459 }
460 if (act&CPS) {
461 if (act&L) {
462 if(!brk) caps ^= 1;
463 } else if(brk) caps = 0; else caps = 1;
464 }
465 if (act&STP) {
466 if (act&L) {
467 if(!brk) stp ^= 1;
468 } else if(brk) stp = 0; else stp = 1;
469 }
470 if ((act&FUNC) && brk) {
471 unsigned key = unshift[dt] ;
472 if(__debug & (1<<key))
473 __debug &= ~(1<<key) ;
474 else
475 __debug |= (1<<key) ;
476 }
477 if(stp) goto loop;
478 if ((act&ASCII) && !brk) {
479 u_char chr;
480
481 if (shfts){
482 chr = shift[dt] ; } else {
483 if (ctls) {
484 chr = ctl[dt] ; } else {
485 chr = unshift[dt] ; } }
486 if (caps && (chr >= 'a' && chr <= 'z')) {
487 chr -= 'a' - 'A' ;
488 }
489 return(chr);
490 }
491 if(on) return (0x100); else goto loop;
492}
493
494pg(p,q,r,s,t,u,v,w,x,y,z) char *p; {
495 printf(p,q,r,s,t,u,v,w,x,y,z);
496 printf("\n");
497 return(getchar());
498}
499
500/* special characters */
501#define bs 8
502#define lf 10
503#define cr 13
504#define cntlc 3
505#define del 0177
506#define cntld 4
507
508getchar()
509{
510 register char thechar;
511 register delay;
512 int x;
513
514 consoftc.cs_flags |= CSF_POLLING;
515 x=splhigh();
516sput('>',0xe);
517 while (1) {
518 thechar = (char) sgetc(0);
519 consoftc.cs_flags &= ~CSF_POLLING;
520 splx(x);
521 switch (thechar) {
522 default: if (thechar >= ' ')
523 sput(thechar,0xe);
524 return(thechar);
525 case cr:
526 case lf: sput(cr,0xe);
527 sput(lf,0xe);
528 return(lf);
529 case bs:
530 case del:
531 sput(bs,0xe);
532 sput(' ',0xe);
533 sput(bs,0xe);
534 return(thechar);
535 case cntlc:
536 sput('^',0xe) ; sput('C',0xe) ; sput('\r',0xe) ; sput('\n',0xe) ;
537 _exit(-2) ;
538 case cntld:
539 sput('^',0xe) ; sput('D',0xe) ; sput('\r',0xe) ; sput('\n',0xe) ;
540 return(0);
541 }
542 }
543}