Commit | Line | Data |
---|---|---|
ac8faf51 WJ |
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 and Don Ahn. | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by the University of | |
19 | * California, Berkeley and its contributors. | |
20 | * 4. Neither the name of the University nor the names of its contributors | |
21 | * may be used to endorse or promote products derived from this software | |
22 | * without specific prior written permission. | |
23 | * | |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
35 | * | |
36 | * @(#)pccons.c 5.11 (Berkeley) 5/21/91 | |
37 | */ | |
38 | static char rcsid[] = "$Header: /usr/bill/working/sys/i386/isa/RCS/pccons.c,v 1.2 92/01/21 14:35:28 william Exp $"; | |
39 | ||
40 | /* | |
41 | * code to work keyboard & display for PC-style console | |
42 | */ | |
43 | #include "param.h" | |
44 | #include "conf.h" | |
45 | #include "ioctl.h" | |
46 | #include "proc.h" | |
47 | #include "user.h" | |
48 | #include "tty.h" | |
49 | #include "uio.h" | |
50 | #include "i386/isa/isa_device.h" | |
51 | #include "callout.h" | |
52 | #include "systm.h" | |
53 | #include "kernel.h" | |
54 | #include "syslog.h" | |
55 | #include "i386/isa/icu.h" | |
56 | #include "i386/i386/cons.h" | |
57 | ||
58 | struct tty pccons; | |
59 | ||
60 | struct pcconsoftc { | |
61 | char cs_flags; | |
62 | #define CSF_ACTIVE 0x1 /* timeout active */ | |
63 | #define CSF_POLLING 0x2 /* polling for input */ | |
64 | char cs_lastc; /* last char sent */ | |
65 | int cs_timo; /* timeouts since interrupt */ | |
66 | u_long cs_wedgecnt; /* times restarted */ | |
67 | } pcconsoftc; | |
68 | ||
69 | int pcprobe(), pcattach(); | |
70 | ||
71 | struct isa_driver pcdriver = { | |
72 | pcprobe, pcattach, "pc", | |
73 | }; | |
74 | ||
75 | #define COL 80 | |
76 | #define ROW 25 | |
77 | #define CHR 2 | |
78 | #define MONO_BASE 0x3B4 | |
79 | #define MONO_BUF 0xfe0B0000 | |
80 | #define CGA_BASE 0x3D4 | |
81 | #define CGA_BUF 0xfe0B8000 | |
82 | #define IOPHYSMEM 0xA0000 | |
83 | ||
84 | u_char color = 0xe ; | |
85 | static unsigned int addr_6845 = MONO_BASE; | |
86 | u_short *Crtat = (u_short *)MONO_BUF; | |
87 | static openf; | |
88 | ||
89 | /* | |
90 | * We check the console periodically to make sure | |
91 | * that it hasn't wedged. Unfortunately, if an XOFF | |
92 | * is typed on the console, that can't be distinguished | |
93 | * from more catastrophic failure. | |
94 | */ | |
95 | #define CN_TIMERVAL (hz) /* frequency at which to check cons */ | |
96 | #define CN_TIMO (2*60) /* intervals to allow for output char */ | |
97 | ||
98 | int pcstart(); | |
99 | int pcparam(); | |
100 | int ttrstrt(); | |
101 | char partab[]; | |
102 | ||
103 | extern pcopen __P((dev_t, int, int, struct proc *)); | |
104 | /* | |
105 | * Wait for CP to accept last CP command sent | |
106 | * before setting up next command. | |
107 | */ | |
108 | #define waitforlast(timo) { \ | |
109 | if (pclast) { \ | |
110 | (timo) = 10000; \ | |
111 | do \ | |
112 | uncache((char *)&pclast->cp_unit); \ | |
113 | while ((pclast->cp_unit&CPTAKE) == 0 && --(timo)); \ | |
114 | } \ | |
115 | } | |
116 | ||
117 | u_char inb(); | |
118 | ||
119 | pcprobe(dev) | |
120 | struct isa_device *dev; | |
121 | { | |
122 | u_char c; | |
123 | int again = 0; | |
124 | ||
125 | /* Enable interrupts and keyboard controller */ | |
126 | while (inb(0x64)&2); outb(0x64,0x60); | |
127 | while (inb(0x64)&2); outb(0x60,0x4D); | |
128 | ||
129 | /* Start keyboard stuff RESET */ | |
130 | while (inb(0x64)&2); /* wait input ready */ | |
131 | outb(0x60,0xFF); /* RESET */ | |
132 | while((c=inb(0x60))!=0xFA) { | |
133 | if ((c == 0xFE) || (c == 0xFF)) { | |
134 | if(!again)printf("KEYBOARD disconnected: RECONNECT \n"); | |
135 | while (inb(0x64)&2); /* wait input ready */ | |
136 | outb(0x60,0xFF); /* RESET */ | |
137 | again = 1; | |
138 | } | |
139 | } | |
140 | /* pick up keyboard reset return code */ | |
141 | while((c=inb(0x60))!=0xAA); | |
142 | return 1; | |
143 | } | |
144 | ||
145 | pcattach(dev) | |
146 | struct isa_device *dev; | |
147 | { | |
148 | u_short *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR; | |
149 | u_short was; | |
150 | ||
151 | /* Crtat initialized to point to MONO buffer */ | |
152 | /* if not present change to CGA_BUF offset */ | |
153 | /* ONLY ADD the difference since locore.s adds */ | |
154 | /* in the remapped offset at the right time */ | |
155 | ||
156 | was = *Crtat; | |
157 | *Crtat = (u_short) 0xA55A; | |
158 | if (*Crtat != 0xA55A) | |
159 | printf("<mono>"); | |
160 | else printf("<color>"); | |
161 | *Crtat = was; | |
162 | cursor(); | |
163 | } | |
164 | ||
165 | /* ARGSUSED */ | |
166 | #ifdef __STDC__ | |
167 | pcopen(dev_t dev, int flag, int mode, struct proc *p) | |
168 | #else | |
169 | pcopen(dev, flag, mode, p) | |
170 | dev_t dev; | |
171 | int flag, mode; | |
172 | struct proc *p; | |
173 | #endif | |
174 | { | |
175 | register struct tty *tp; | |
176 | ||
177 | tp = &pccons; | |
178 | tp->t_oproc = pcstart; | |
179 | tp->t_param = pcparam; | |
180 | tp->t_dev = dev; | |
181 | openf++; | |
182 | if ((tp->t_state & TS_ISOPEN) == 0) { | |
183 | tp->t_state |= TS_WOPEN; | |
184 | ttychars(tp); | |
185 | tp->t_iflag = TTYDEF_IFLAG; | |
186 | tp->t_oflag = TTYDEF_OFLAG; | |
187 | tp->t_cflag = TTYDEF_CFLAG; | |
188 | tp->t_lflag = TTYDEF_LFLAG; | |
189 | tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; | |
190 | pcparam(tp, &tp->t_termios); | |
191 | ttsetwater(tp); | |
192 | } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) | |
193 | return (EBUSY); | |
194 | tp->t_state |= TS_CARR_ON; | |
195 | return ((*linesw[tp->t_line].l_open)(dev, tp)); | |
196 | } | |
197 | ||
198 | pcclose(dev, flag, mode, p) | |
199 | dev_t dev; | |
200 | int flag, mode; | |
201 | struct proc *p; | |
202 | { | |
203 | (*linesw[pccons.t_line].l_close)(&pccons, flag); | |
204 | ttyclose(&pccons); | |
205 | return(0); | |
206 | } | |
207 | ||
208 | /*ARGSUSED*/ | |
209 | pcread(dev, uio, flag) | |
210 | dev_t dev; | |
211 | struct uio *uio; | |
212 | { | |
213 | return ((*linesw[pccons.t_line].l_read)(&pccons, uio, flag)); | |
214 | } | |
215 | ||
216 | /*ARGSUSED*/ | |
217 | pcwrite(dev, uio, flag) | |
218 | dev_t dev; | |
219 | struct uio *uio; | |
220 | { | |
221 | return ((*linesw[pccons.t_line].l_write)(&pccons, uio, flag)); | |
222 | } | |
223 | ||
224 | /* | |
225 | * Got a console receive interrupt - | |
226 | * the console processor wants to give us a character. | |
227 | * Catch the character, and see who it goes to. | |
228 | */ | |
229 | pcrint(dev, irq, cpl) | |
230 | dev_t dev; | |
231 | { | |
232 | int c; | |
233 | ||
234 | c = sgetc(1); | |
235 | if (c&0x100) return; | |
236 | if (pcconsoftc.cs_flags&CSF_POLLING) | |
237 | return; | |
238 | #ifdef KDB | |
239 | if (kdbrintr(c, &pccons)) | |
240 | return; | |
241 | #endif | |
242 | (*linesw[pccons.t_line].l_rint)(c&0xff, &pccons); | |
243 | } | |
244 | ||
245 | pcioctl(dev, cmd, data, flag) | |
246 | dev_t dev; | |
247 | caddr_t data; | |
248 | { | |
249 | register struct tty *tp = &pccons; | |
250 | register error; | |
251 | ||
252 | error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); | |
253 | if (error >= 0) | |
254 | return (error); | |
255 | error = ttioctl(tp, cmd, data, flag); | |
256 | if (error >= 0) | |
257 | return (error); | |
258 | return (ENOTTY); | |
259 | } | |
260 | ||
261 | int pcconsintr = 1; | |
262 | /* | |
263 | * Got a console transmission interrupt - | |
264 | * the console processor wants another character. | |
265 | */ | |
266 | pcxint(dev) | |
267 | dev_t dev; | |
268 | { | |
269 | register struct tty *tp; | |
270 | register int unit; | |
271 | ||
272 | if (!pcconsintr) | |
273 | return; | |
274 | pccons.t_state &= ~TS_BUSY; | |
275 | pcconsoftc.cs_timo = 0; | |
276 | if (pccons.t_line) | |
277 | (*linesw[pccons.t_line].l_start)(&pccons); | |
278 | else | |
279 | pcstart(&pccons); | |
280 | } | |
281 | ||
282 | pcstart(tp) | |
283 | register struct tty *tp; | |
284 | { | |
285 | register c, s; | |
286 | ||
287 | s = spltty(); | |
288 | if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) | |
289 | goto out; | |
290 | do { | |
291 | if (RB_LEN(&tp->t_out) <= tp->t_lowat) { | |
292 | if (tp->t_state&TS_ASLEEP) { | |
293 | tp->t_state &= ~TS_ASLEEP; | |
294 | wakeup((caddr_t)&tp->t_out); | |
295 | } | |
296 | if (tp->t_wsel) { | |
297 | selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); | |
298 | tp->t_wsel = 0; | |
299 | tp->t_state &= ~TS_WCOLL; | |
300 | } | |
301 | } | |
302 | if (RB_LEN(&tp->t_out) == 0) | |
303 | goto out; | |
304 | c = getc(&tp->t_out); | |
305 | splx(s); | |
306 | sput(c,0x7); | |
307 | s = spltty(); | |
308 | } while(1); | |
309 | out: | |
310 | splx(s); | |
311 | } | |
312 | ||
313 | pccnprobe(cp) | |
314 | struct consdev *cp; | |
315 | { | |
316 | int maj; | |
317 | ||
318 | /* locate the major number */ | |
319 | for (maj = 0; maj < nchrdev; maj++) | |
320 | if (cdevsw[maj].d_open == pcopen) | |
321 | break; | |
322 | ||
323 | /* initialize required fields */ | |
324 | cp->cn_dev = makedev(maj, 0); | |
325 | cp->cn_tp = &pccons; | |
326 | cp->cn_pri = CN_INTERNAL; | |
327 | } | |
328 | ||
329 | /* ARGSUSED */ | |
330 | pccninit(cp) | |
331 | struct consdev *cp; | |
332 | { | |
333 | /* | |
334 | * For now, don't screw with it. | |
335 | */ | |
336 | /* crtat = 0; */ | |
337 | } | |
338 | ||
339 | static __color; | |
340 | ||
341 | /* ARGSUSED */ | |
342 | pccnputc(dev, c) | |
343 | dev_t dev; | |
344 | char c; | |
345 | { | |
346 | int clr = __color; | |
347 | ||
348 | if (clr == 0) | |
349 | clr = 0x30; | |
350 | else | |
351 | clr |= 0x60; | |
352 | if (c == '\n') | |
353 | sput('\r', clr); | |
354 | sput(c, clr); | |
355 | } | |
356 | ||
357 | /* | |
358 | * Print a character on console. | |
359 | */ | |
360 | pcputchar(c, tp) | |
361 | char c; | |
362 | register struct tty *tp; | |
363 | { | |
364 | sput(c,0x2); | |
365 | if (c=='\n') getchar(); | |
366 | } | |
367 | ||
368 | ||
369 | /* ARGSUSED */ | |
370 | pccngetc(dev) | |
371 | dev_t dev; | |
372 | { | |
373 | register int c, s; | |
374 | ||
375 | s = spltty(); /* block pcrint while we poll */ | |
376 | c = sgetc(0); | |
377 | if (c == '\r') c = '\n'; | |
378 | splx(s); | |
379 | return (c); | |
380 | } | |
381 | ||
382 | pcgetchar(tp) | |
383 | register struct tty *tp; | |
384 | { | |
385 | int c; | |
386 | ||
387 | c = sgetc(0); | |
388 | return (c&0xff); | |
389 | } | |
390 | ||
391 | /* | |
392 | * Set line parameters | |
393 | */ | |
394 | pcparam(tp, t) | |
395 | register struct tty *tp; | |
396 | register struct termios *t; | |
397 | { | |
398 | register int cflag = t->c_cflag; | |
399 | /* and copy to tty */ | |
400 | tp->t_ispeed = t->c_ispeed; | |
401 | tp->t_ospeed = t->c_ospeed; | |
402 | tp->t_cflag = cflag; | |
403 | ||
404 | return(0); | |
405 | } | |
406 | ||
407 | #ifdef KDB | |
408 | /* | |
409 | * Turn input polling on/off (used by debugger). | |
410 | */ | |
411 | pcpoll(onoff) | |
412 | int onoff; | |
413 | { | |
414 | } | |
415 | #endif | |
416 | ||
417 | extern int hz; | |
418 | ||
419 | static beeping; | |
420 | sysbeepstop() | |
421 | { | |
422 | /* disable counter 2 */ | |
423 | outb(0x61,inb(0x61)&0xFC); | |
424 | beeping = 0; | |
425 | } | |
426 | ||
427 | sysbeep() | |
428 | { | |
429 | ||
430 | /* enable counter 2 */ | |
431 | outb(0x61,inb(0x61)|3); | |
432 | /* set command for counter 2, 2 byte write */ | |
433 | outb(0x43,0xB6); | |
434 | /* send 0x637 for 750 HZ */ | |
435 | outb(0x42,0x37); | |
436 | outb(0x42,0x06); | |
437 | if(!beeping)timeout(sysbeepstop,0,hz/4); | |
438 | beeping = 1; | |
439 | } | |
440 | ||
441 | /* cursor() sets an offset (0-1999) into the 80x25 text area */ | |
442 | ||
443 | static u_short *crtat = 0; | |
444 | char bg_at = 0x0f; | |
445 | char so_at = 0x70; | |
446 | ||
447 | cursor() | |
448 | { int pos = crtat - Crtat; | |
449 | ||
450 | outb(addr_6845,14); | |
451 | outb(addr_6845+1,pos >> 8); | |
452 | outb(addr_6845,15); | |
453 | outb(addr_6845+1,pos&0xff); | |
454 | timeout(cursor,0,hz/10); | |
455 | } | |
456 | ||
457 | u_char shfts, ctls, alts, caps, num, stp, scroll; | |
458 | ||
459 | /* | |
460 | * Compensate for abysmally stupid frame buffer aribitration with macro | |
461 | */ | |
462 | #define wrtchar(c) { do *crtat = (c); while ((c) != *crtat); crtat++; row++; } | |
463 | ||
464 | /* sput has support for emulation of the 'ibmpc' termcap entry. */ | |
465 | /* This is a bare-bones implementation of a bare-bones entry */ | |
466 | /* One modification: Change li#24 to li#25 to reflect 25 lines */ | |
467 | ||
468 | sput(c, ca) | |
469 | u_char c, ca; | |
470 | { | |
471 | ||
472 | static int esc,ebrac,eparm,cx,cy,row,so; | |
473 | ||
474 | if (crtat == 0) { | |
475 | u_short *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR, was; | |
476 | unsigned cursorat; | |
477 | ||
478 | /* Crtat initialized to point to MONO buffer */ | |
479 | /* if not present change to CGA_BUF offset */ | |
480 | /* ONLY ADD the difference since locore.s adds */ | |
481 | /* in the remapped offset at the right time */ | |
482 | ||
483 | was = *cp; | |
484 | *cp = (u_short) 0xA55A; | |
485 | if (*cp != 0xA55A) { | |
486 | addr_6845 = MONO_BASE; | |
487 | } else { | |
488 | *cp = was; | |
489 | addr_6845 = CGA_BASE; | |
490 | Crtat = Crtat + (CGA_BUF-MONO_BUF)/CHR; | |
491 | } | |
492 | /* Extract cursor location */ | |
493 | outb(addr_6845,14); | |
494 | cursorat = inb(addr_6845+1)<<8 ; | |
495 | outb(addr_6845,15); | |
496 | cursorat |= inb(addr_6845+1); | |
497 | ||
498 | crtat = Crtat + cursorat; | |
499 | fillw((bg_at<<8)|' ', crtat, COL*ROW-cursorat); | |
500 | } | |
501 | switch(c) { | |
502 | case 0x1B: | |
503 | esc = 1; ebrac = 0; eparm = 0; | |
504 | break; | |
505 | ||
506 | case '\t': | |
507 | do { | |
508 | wrtchar((ca<<8)| ' '); | |
509 | } while (row % 8); | |
510 | break; | |
511 | ||
512 | case '\010': | |
513 | crtat--; row--; | |
514 | if (row < 0) row += COL; /* non-destructive backspace */ | |
515 | break; | |
516 | ||
517 | case '\r': | |
518 | crtat -= row ; row = 0; | |
519 | break; | |
520 | ||
521 | case '\n': | |
522 | crtat += COL ; | |
523 | break; | |
524 | ||
525 | default: | |
526 | if (esc) { | |
527 | if (ebrac) { | |
528 | switch(c) { | |
529 | case 'm': /* no support for standout */ | |
530 | if (!cx) so = 0; | |
531 | else so = 1; | |
532 | esc = 0; ebrac = 0; eparm = 0; | |
533 | break; | |
534 | case 'A': /* back one row */ | |
535 | crtat -= COL; | |
536 | esc = 0; ebrac = 0; eparm = 0; | |
537 | break; | |
538 | case 'B': /* down one row */ | |
539 | crtat += COL; | |
540 | esc = 0; ebrac = 0; eparm = 0; | |
541 | break; | |
542 | case 'C': /* right cursor */ | |
543 | crtat++; row++; | |
544 | esc = 0; ebrac = 0; eparm = 0; | |
545 | break; | |
546 | case 'J': /* Clear to end of display */ | |
547 | fillw((bg_at<<8)+' ', crtat, | |
548 | Crtat+COL*ROW-crtat); | |
549 | esc = 0; ebrac = 0; eparm = 0; | |
550 | break; | |
551 | case 'K': /* Clear to EOL */ | |
552 | fillw((bg_at<<8)+' ', crtat, | |
553 | COL-(crtat-Crtat)%COL); | |
554 | esc = 0; ebrac = 0; eparm = 0; | |
555 | break; | |
556 | case 'H': /* Cursor move */ | |
557 | if ((!cx)||(!cy)) { | |
558 | crtat = Crtat; | |
559 | row = 0; | |
560 | } else { | |
561 | crtat = Crtat+(cx-1)*COL+cy-1; | |
562 | row = cy-1; | |
563 | } | |
564 | esc = 0; ebrac = 0; eparm = 0; | |
565 | break; | |
566 | case ';': /* Switch params in cursor def */ | |
567 | eparm = 1; | |
568 | return; | |
569 | default: /* Only numbers valid here */ | |
570 | if ((c >= '0')&&(c <= '9')) { | |
571 | if (eparm) { | |
572 | cy *= 10; | |
573 | cy += c - '0'; | |
574 | } else { | |
575 | cx *= 10; | |
576 | cx += c - '0'; | |
577 | } | |
578 | } else { | |
579 | esc = 0; ebrac = 0; eparm = 0; | |
580 | } | |
581 | return; | |
582 | } | |
583 | break; | |
584 | } else if (c == 'c') { /* Clear screen & home */ | |
585 | fillw((bg_at<<8)+' ', Crtat,COL*ROW); | |
586 | crtat = Crtat; row = 0; | |
587 | esc = 0; ebrac = 0; eparm = 0; | |
588 | } else if (c == '[') { /* Start ESC [ sequence */ | |
589 | ebrac = 1; cx = 0; cy = 0; eparm = 0; | |
590 | } else { /* Invalid, clear state */ | |
591 | esc = 0; ebrac = 0; eparm = 0; | |
592 | } | |
593 | } else { | |
594 | if (c == 7) | |
595 | sysbeep(); | |
596 | /* Print only printables */ | |
597 | else /*if (c >= ' ') */ { | |
598 | if (so) { | |
599 | wrtchar((so_at<<8)| c); | |
600 | } else { | |
601 | wrtchar((ca<<8)| c); | |
602 | } | |
603 | if (row >= COL) row = 0; | |
604 | break ; | |
605 | } | |
606 | } | |
607 | } | |
608 | if (crtat >= Crtat+COL*(ROW)) { /* scroll check */ | |
609 | if (openf) do sgetc(1); while (scroll); | |
610 | bcopy(Crtat+COL,Crtat,COL*(ROW-1)*CHR); | |
611 | fillw ((bg_at<<8) + ' ', Crtat+COL*(ROW-1),COL) ; | |
612 | crtat -= COL ; | |
613 | } | |
614 | } | |
615 | ||
616 | #define L 0x0001 /* locking function */ | |
617 | #define SHF 0x0002 /* keyboard shift */ | |
618 | #define ALT 0x0004 /* alternate shift -- alternate chars */ | |
619 | #define NUM 0x0008 /* numeric shift cursors vs. numeric */ | |
620 | #define CTL 0x0010 /* control shift -- allows ctl function */ | |
621 | #define CPS 0x0020 /* caps shift -- swaps case of letter */ | |
622 | #define ASCII 0x0040 /* ascii code for this key */ | |
623 | #define STP 0x0080 /* stop output */ | |
624 | #define FUNC 0x0100 /* function key */ | |
625 | #define SCROLL 0x0200 /* scroll lock key */ | |
626 | ||
627 | unsigned __debug = 0; /*0xffe */; | |
628 | u_short action[] = { | |
629 | 0, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 0- 7 */ | |
630 | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 8-15 */ | |
631 | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 16-23 */ | |
632 | ASCII, ASCII, ASCII, ASCII, ASCII, CTL, ASCII, ASCII, /* scan 24-31 */ | |
633 | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 32-39 */ | |
634 | ASCII, ASCII, SHF , ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 40-47 */ | |
635 | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, SHF, ASCII, /* scan 48-55 */ | |
636 | ALT, ASCII, CPS , FUNC , FUNC , FUNC , FUNC , FUNC , /* scan 56-63 */ | |
637 | FUNC , FUNC , FUNC , FUNC , FUNC , NUM, SCROLL, ASCII, /* scan 64-71 */ | |
638 | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 72-79 */ | |
639 | ASCII, ASCII, ASCII, ASCII, 0, 0, 0, 0, /* scan 80-87 */ | |
640 | 0,0,0,0,0,0,0,0, | |
641 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, | |
642 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; | |
643 | ||
644 | u_char unshift[] = { /* no shift */ | |
645 | 0, 033 , '1' , '2' , '3' , '4' , '5' , '6' , /* scan 0- 7 */ | |
646 | '7' , '8' , '9' , '0' , '-' , '=' , 0177 ,'\t' , /* scan 8-15 */ | |
647 | ||
648 | 'q' , 'w' , 'e' , 'r' , 't' , 'y' , 'u' , 'i' , /* scan 16-23 */ | |
649 | 'o' , 'p' , '[' , ']' , '\r' , CTL , 'a' , 's' , /* scan 24-31 */ | |
650 | ||
651 | 'd' , 'f' , 'g' , 'h' , 'j' , 'k' , 'l' , ';' , /* scan 32-39 */ | |
652 | '\'' , '`' , SHF , '\\' , 'z' , 'x' , 'c' , 'v' , /* scan 40-47 */ | |
653 | ||
654 | 'b' , 'n' , 'm' , ',' , '.' , '/' , SHF , '*', /* scan 48-55 */ | |
655 | ALT , ' ' , CPS, 1, 2, 3 , 4, 5, /* scan 56-63 */ | |
656 | ||
657 | 6, 7, 8, 9, 10, NUM, STP, '7', /* scan 64-71 */ | |
658 | '8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */ | |
659 | ||
660 | '2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */ | |
661 | 0,0,0,0,0,0,0,0, | |
662 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, | |
663 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; | |
664 | ||
665 | u_char shift[] = { /* shift shift */ | |
666 | 0, 033 , '!' , '@' , '#' , '$' , '%' , '^' , /* scan 0- 7 */ | |
667 | '&' , '*' , '(' , ')' , '_' , '+' , 0177 ,'\t' , /* scan 8-15 */ | |
668 | 'Q' , 'W' , 'E' , 'R' , 'T' , 'Y' , 'U' , 'I' , /* scan 16-23 */ | |
669 | 'O' , 'P' , '{' , '}' , '\r' , CTL , 'A' , 'S' , /* scan 24-31 */ | |
670 | 'D' , 'F' , 'G' , 'H' , 'J' , 'K' , 'L' , ':' , /* scan 32-39 */ | |
671 | '"' , '~' , SHF , '|' , 'Z' , 'X' , 'C' , 'V' , /* scan 40-47 */ | |
672 | 'B' , 'N' , 'M' , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */ | |
673 | ALT , ' ' , CPS, 0, 0, ' ' , 0, 0, /* scan 56-63 */ | |
674 | 0, 0, 0, 0, 0, NUM, STP, '7', /* scan 64-71 */ | |
675 | '8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */ | |
676 | '2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */ | |
677 | 0,0,0,0,0,0,0,0, | |
678 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, | |
679 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; | |
680 | ||
681 | u_char ctl[] = { /* CTL shift */ | |
682 | 0, 033 , '!' , 000 , '#' , '$' , '%' , 036 , /* scan 0- 7 */ | |
683 | '&' , '*' , '(' , ')' , 037 , '+' , 034 ,'\177', /* scan 8-15 */ | |
684 | 021 , 027 , 005 , 022 , 024 , 031 , 025 , 011 , /* scan 16-23 */ | |
685 | 017 , 020 , 033 , 035 , '\r' , CTL , 001 , 023 , /* scan 24-31 */ | |
686 | 004 , 006 , 007 , 010 , 012 , 013 , 014 , ';' , /* scan 32-39 */ | |
687 | '\'' , '`' , SHF , 034 , 032 , 030 , 003 , 026 , /* scan 40-47 */ | |
688 | 002 , 016 , 015 , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */ | |
689 | ALT , ' ' , CPS, 0, 0, ' ' , 0, 0, /* scan 56-63 */ | |
690 | CPS, 0, 0, 0, 0, 0, 0, 0, /* scan 64-71 */ | |
691 | 0, 0, 0, 0, 0, 0, 0, 0, /* scan 72-79 */ | |
692 | 0, 0, 0, 0, 0, 0, 0, 0, /* scan 80-87 */ | |
693 | 0, 0, 033, '7' , '4' , '1' , 0, NUM, /* scan 88-95 */ | |
694 | '8' , '5' , '2' , 0, STP, '9' , '6' , '3' , /*scan 96-103*/ | |
695 | '.' , 0, '*' , '-' , '+' , 0, 0, 0, /*scan 104-111*/ | |
696 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; | |
697 | ||
698 | #ifdef notdef | |
699 | struct key { | |
700 | u_short action; /* how this key functions */ | |
701 | char ascii[8]; /* ascii result character indexed by shifts */ | |
702 | }; | |
703 | #endif | |
704 | ||
705 | ||
706 | #define KBSTAT 0x64 /* kbd status port */ | |
707 | #define KBS_INP_BUF_FUL 0x02 /* kbd char ready */ | |
708 | #define KBDATA 0x60 /* kbd data port */ | |
709 | #define KBSTATUSPORT 0x61 /* kbd status */ | |
710 | ||
711 | update_led() | |
712 | { | |
713 | while (inb(0x64)&2); /* wait input ready */ | |
714 | outb(0x60,0xED); /* LED Command */ | |
715 | while (inb(0x64)&2); /* wait input ready */ | |
716 | outb(0x60,scroll | 2*num | 4*caps); | |
717 | } | |
718 | ||
719 | reset_cpu() { | |
720 | while(1) { | |
721 | while (inb(0x64)&2); /* wait input ready */ | |
722 | outb(0x64,0xFE); /* Reset Command */ | |
723 | DELAY(4000000); | |
724 | while (inb(0x64)&2); /* wait input ready */ | |
725 | outb(0x64,0xFF); /* Keyboard Reset Command */ | |
726 | } | |
727 | /* NOTREACHED */ | |
728 | } | |
729 | ||
730 | /* | |
731 | sgetc(noblock) : get a character from the keyboard. If noblock = 0 wait until | |
732 | a key is gotten. Otherwise return a 0x100 (256). | |
733 | */ | |
734 | int sgetc(noblock) | |
735 | { | |
736 | u_char dt; unsigned key; | |
737 | loop: | |
738 | /* First see if there is something in the keyboard port */ | |
739 | if (inb(KBSTAT)&1) dt = inb(KBDATA); | |
740 | else { if (noblock) return (0x100); else goto loop; } | |
741 | ||
742 | /* Check for cntl-alt-del */ | |
743 | if ((dt == 83)&&ctls&&alts) _exit(); | |
744 | ||
745 | /* Check for make/break */ | |
746 | if (dt & 0x80) { | |
747 | /* break */ | |
748 | dt = dt & 0x7f ; | |
749 | switch (action[dt]) { | |
750 | case SHF: shfts = 0; break; | |
751 | case ALT: alts = 0; break; | |
752 | case CTL: ctls = 0; break; | |
753 | case FUNC: | |
754 | /* Toggle debug flags */ | |
755 | key = unshift[dt]; | |
756 | if(__debug & (1<<key)) __debug &= ~(1<<key) ; | |
757 | else __debug |= (1<<key) ; | |
758 | break; | |
759 | } | |
760 | } else { | |
761 | /* make */ | |
762 | dt = dt & 0x7f ; | |
763 | switch (action[dt]) { | |
764 | /* LOCKING KEYS */ | |
765 | case NUM: num ^= 1; update_led(); break; | |
766 | case CPS: caps ^= 1; update_led(); break; | |
767 | case SCROLL: scroll ^= 1; update_led(); break; | |
768 | case STP: stp ^= 1; if(stp) goto loop; break; | |
769 | ||
770 | /* NON-LOCKING KEYS */ | |
771 | case SHF: shfts = 1; break; | |
772 | case ALT: alts = 1; break; | |
773 | case CTL: ctls = 1; break; | |
774 | case ASCII: | |
775 | if (shfts) dt = shift[dt]; | |
776 | else if (ctls) dt = ctl[dt]; | |
777 | else dt = unshift[dt]; | |
778 | if (caps && (dt >= 'a' && dt <= 'z')) dt -= 'a' - 'A'; | |
779 | return(dt); | |
780 | } | |
781 | } | |
782 | if (noblock) return (0x100); else goto loop; | |
783 | } | |
784 | ||
785 | pg(p,q,r,s,t,u,v,w,x,y,z) char *p; { | |
786 | printf(p,q,r,s,t,u,v,w,x,y,z); | |
787 | printf("\n"); | |
788 | return(getchar()); | |
789 | } | |
790 | ||
791 | /* special characters */ | |
792 | #define bs 8 | |
793 | #define lf 10 | |
794 | #define cr 13 | |
795 | #define cntlc 3 | |
796 | #define del 0177 | |
797 | #define cntld 4 | |
798 | ||
799 | getchar() | |
800 | { | |
801 | register char thechar; | |
802 | register delay; | |
803 | int x; | |
804 | ||
805 | pcconsoftc.cs_flags |= CSF_POLLING; | |
806 | x=splhigh(); | |
807 | sput('>',0x6); | |
808 | /*while (1) {*/ | |
809 | thechar = (char) sgetc(0); | |
810 | pcconsoftc.cs_flags &= ~CSF_POLLING; | |
811 | splx(x); | |
812 | switch (thechar) { | |
813 | default: if (thechar >= ' ') | |
814 | sput(thechar,0x6); | |
815 | return(thechar); | |
816 | case cr: | |
817 | case lf: sput(cr,0x6); | |
818 | sput(lf,0x6); | |
819 | return(lf); | |
820 | case bs: | |
821 | case del: | |
822 | sput(bs,0x6); | |
823 | sput(' ',0x6); | |
824 | sput(bs,0x6); | |
825 | return(thechar); | |
826 | /*case cntlc: | |
827 | sput('^',0xe) ; sput('C',0xe) ; sput('\r',0xe) ; sput('\n',0xe) ; | |
828 | _exit(-2) ; */ | |
829 | case cntld: | |
830 | sput('^',0x6) ; sput('D',0x6) ; sput('\r',0x6) ; sput('\n',0x6) ; | |
831 | return(0); | |
832 | } | |
833 | /*}*/ | |
834 | } | |
835 | ||
836 | #include "machine/stdarg.h" | |
837 | static nrow; | |
838 | ||
839 | #define DPAUSE 1 | |
840 | void | |
841 | #ifdef __STDC__ | |
842 | dprintf(unsigned flgs, const char *fmt, ...) | |
843 | #else | |
844 | dprintf(flgs, fmt /*, va_alist */) | |
845 | char *fmt; | |
846 | unsigned flgs; | |
847 | #endif | |
848 | { extern unsigned __debug; | |
849 | va_list ap; | |
850 | ||
851 | if((flgs&__debug) > DPAUSE) { | |
852 | __color = ffs(flgs&__debug)+1; | |
853 | va_start(ap,fmt); | |
854 | kprintf(fmt, 1, (struct tty *)0, ap); | |
855 | va_end(ap); | |
856 | if (flgs&DPAUSE || nrow%24 == 23) { | |
857 | int x; | |
858 | x = splhigh(); | |
859 | if (nrow%24 == 23) nrow = 0; | |
860 | sgetc(0); | |
861 | splx(x); | |
862 | } | |
863 | } | |
864 | __color = 0; | |
865 | } | |
866 | ||
867 | consinit() {} |