pccons.c revision 1.37 1 /* $NetBSD: pccons.c,v 1.37 2003/08/07 16:26:48 agc Exp $ */
2 /* $OpenBSD: pccons.c,v 1.22 1999/01/30 22:39:37 imp Exp $ */
3 /* NetBSD: pccons.c,v 1.89 1995/05/04 19:35:20 cgd Exp */
4
5 /*-
6 * Copyright (c) 1990 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * William Jolitz and Don Ahn.
11 *
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)pccons.c 5.11 (Berkeley) 5/21/91
36 */
37
38 /*-
39 * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
40 *
41 * This code is derived from software contributed to Berkeley by
42 * William Jolitz and Don Ahn.
43 *
44 * Copyright (c) 1994 Charles M. Hannum.
45 * Copyright (c) 1992, 1993 Erik Forsberg.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed by the University of
58 * California, Berkeley and its contributors.
59 * 4. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 * @(#)pccons.c 5.11 (Berkeley) 5/21/91
76 */
77
78 /*
79 * code to work keyboard & display for PC-style console
80 */
81
82 #include <sys/cdefs.h>
83 __KERNEL_RCSID(0, "$NetBSD: pccons.c,v 1.37 2003/08/07 16:26:48 agc Exp $");
84
85 #include "opt_ddb.h"
86
87 #include <sys/param.h>
88 #include <sys/systm.h>
89 #include <sys/tty.h>
90 #include <sys/callout.h>
91 #include <sys/poll.h>
92 #include <sys/conf.h>
93 #include <sys/vnode.h>
94 #include <sys/kernel.h>
95 #include <sys/kcore.h>
96 #include <sys/device.h>
97 #include <sys/proc.h>
98
99 #include <machine/bus.h>
100
101 #include <machine/display.h>
102 #include <machine/pccons.h>
103 #include <machine/kbdreg.h>
104
105 #include <dev/cons.h>
106 #include <dev/isa/isavar.h>
107
108 #include <arc/arc/arcbios.h>
109 #include <arc/dev/pcconsvar.h>
110
111 #define XFREE86_BUG_COMPAT
112
113 #ifndef BEEP_FREQ
114 #define BEEP_FREQ 1600
115 #endif
116 #ifndef BEEP_TIME
117 #define BEEP_TIME (hz/5)
118 #endif
119
120 #define PCBURST 128
121
122 static u_short *Crtat; /* pointer to backing store */
123 static u_short *crtat; /* pointer to current char */
124 static u_char async, kernel, polling; /* Really, you don't want to know. */
125 static u_char lock_state = 0x00, /* all off */
126 old_lock_state = 0xff,
127 typematic_rate = 0xff, /* don't update until set by user */
128 old_typematic_rate = 0xff;
129 static u_short cursor_shape = 0xffff, /* don't update until set by user */
130 old_cursor_shape = 0xffff;
131 static pccons_keymap_t scan_codes[KB_NUM_KEYS];/* keyboard translation table */
132 int pc_xmode = 0;
133
134 /*
135 * Keyboard output queue.
136 */
137 int kb_oq_put = 0;
138 int kb_oq_get = 0;
139 u_char kb_oq[8];
140
141 #define PCUNIT(x) (minor(x))
142
143 static struct video_state {
144 int cx, cy; /* escape parameters */
145 int row, col; /* current cursor position */
146 int nrow, ncol, nchr; /* current screen geometry */
147 int offset; /* Saved cursor pos */
148 u_char state; /* parser state */
149 #define VSS_ESCAPE 1
150 #define VSS_EBRACE 2
151 #define VSS_EPARAM 3
152 char so; /* in standout mode? */
153 char color; /* color or mono display */
154 char at; /* normal attributes */
155 char so_at; /* standout attributes */
156 } vs;
157
158 static struct callout async_update_ch = CALLOUT_INITIALIZER;
159
160 void pc_xmode_on __P((void));
161 void pc_xmode_off __P((void));
162 static u_char kbc_get8042cmd __P((void));
163 int kbd_cmd __P((u_char, u_char));
164 static __inline int kbd_wait_output __P((void));
165 static __inline int kbd_wait_input __P((void));
166 void kbd_flush_input __P((void));
167 void set_cursor_shape __P((void));
168 void get_cursor_shape __P((void));
169 void async_update __P((void));
170 void do_async_update __P((u_char));
171
172 void pccnputc __P((dev_t, int c));
173 int pccngetc __P((dev_t));
174 void pccnpollc __P((dev_t, int));
175
176 extern struct cfdriver pc_cd;
177
178 dev_type_open(pcopen);
179 dev_type_close(pcclose);
180 dev_type_read(pcread);
181 dev_type_write(pcwrite);
182 dev_type_ioctl(pcioctl);
183 dev_type_tty(pctty);
184 dev_type_poll(pcpoll);
185 dev_type_mmap(pcmmap);
186
187 const struct cdevsw pc_cdevsw = {
188 pcopen, pcclose, pcread, pcwrite, pcioctl,
189 nostop, pctty, pcpoll, pcmmap, ttykqfilter, D_TTY
190 };
191
192 #define CHR 2
193
194 char *sget __P((void));
195 void sput __P((u_char *, int));
196
197 void pcstart __P((struct tty *));
198 int pcparam __P((struct tty *, struct termios *));
199 static __inline void wcopy __P((void *, void *, u_int));
200 void pc_context_init __P((bus_space_tag_t, bus_space_tag_t, bus_space_tag_t,
201 struct pccons_config *));
202
203 extern void fillw __P((int, u_int16_t *, int));
204
205 #define KBD_DELAY \
206 DELAY(10);
207
208 #define crtc_read_1(reg) \
209 bus_space_read_1(pccons_console_context.pc_crt_iot, \
210 pccons_console_context.pc_6845_ioh, reg)
211 #define crtc_write_1(reg, data) \
212 bus_space_write_1(pccons_console_context.pc_crt_iot, \
213 pccons_console_context.pc_6845_ioh, reg, data)
214
215 struct pccons_context pccons_console_context;
216
217 void
218 kbd_context_init(kbd_iot, config)
219 bus_space_tag_t kbd_iot;
220 struct pccons_config *config;
221 {
222 struct pccons_kbd_context *pkc = &pccons_console_context.pc_pkc;
223
224 if (pkc->pkc_initialized)
225 return;
226 pkc->pkc_initialized = 1;
227
228 pkc->pkc_iot = kbd_iot;
229
230 bus_space_map(kbd_iot, config->pc_kbd_cmdp, 1, 0,
231 &pkc->pkc_cmd_ioh);
232 bus_space_map(kbd_iot, config->pc_kbd_datap, 1, 0,
233 &pkc->pkc_data_ioh);
234 }
235
236 void
237 pc_context_init(crt_iot, crt_memt, kbd_iot, config)
238 bus_space_tag_t crt_iot, crt_memt, kbd_iot;
239 struct pccons_config *config;
240 {
241 struct pccons_context *pc = &pccons_console_context;
242
243 if (pc->pc_initialized)
244 return;
245 pc->pc_initialized = 1;
246
247 kbd_context_init(kbd_iot, config);
248
249 pc->pc_crt_iot = crt_iot;
250 pc->pc_crt_memt = crt_memt;
251
252 bus_space_map(crt_iot, config->pc_mono_iobase, 2, 0,
253 &pc->pc_mono_ioh);
254 bus_space_map(crt_memt, config->pc_mono_memaddr, 0x20000, 0,
255 &pc->pc_mono_memh);
256 bus_space_map(crt_iot, config->pc_cga_iobase, 2, 0,
257 &pc->pc_cga_ioh);
258 bus_space_map(crt_memt, config->pc_cga_memaddr, 0x20000, 0,
259 &pc->pc_cga_memh);
260
261 /*
262 * pc->pc_6845_ioh and pc->pc_crt_memh will be initialized later,
263 * when `Crtat' is initialized.
264 */
265
266 pc->pc_config = config;
267
268 (*config->pc_init)();
269 }
270
271 /*
272 * bcopy variant that only moves word-aligned 16-bit entities,
273 * for stupid VGA cards. cnt is required to be an even vale.
274 */
275 static __inline void
276 wcopy(src, tgt, cnt)
277 void *src, *tgt;
278 u_int cnt;
279 {
280 u_int16_t *from = src;
281 u_int16_t *to = tgt;
282
283 cnt >>= 1;
284 if (to < from || to >= from + cnt)
285 while(cnt--)
286 *to++ = *from++;
287 else {
288 to += cnt;
289 from += cnt;
290 while(cnt--)
291 *--to = *--from;
292 }
293 }
294
295 static __inline int
296 kbd_wait_output()
297 {
298 u_int i;
299
300 for (i = 100000; i; i--)
301 if ((kbd_cmd_read_1() & KBS_IBF) == 0) {
302 KBD_DELAY;
303 return 1;
304 }
305 return 0;
306 }
307
308 static __inline int
309 kbd_wait_input()
310 {
311 u_int i;
312
313 for (i = 100000; i; i--)
314 if ((kbd_cmd_read_1() & KBS_DIB) != 0) {
315 KBD_DELAY;
316 return 1;
317 }
318 return 0;
319 }
320
321 void
322 kbd_flush_input()
323 {
324 u_char c;
325
326 while ((c = kbd_cmd_read_1()) & 0x03)
327 if ((c & KBS_DIB) == KBS_DIB) {
328 /* XXX - delay is needed to prevent some keyboards from
329 wedging when the system boots */
330 delay(6);
331 (void) kbd_data_read_1();
332 }
333 }
334
335 #if 1
336 /*
337 * Get the current command byte.
338 */
339 static u_char
340 kbc_get8042cmd()
341 {
342
343 if (!kbd_wait_output())
344 return -1;
345 kbd_cmd_write_1(K_RDCMDBYTE);
346 if (!kbd_wait_input())
347 return -1;
348 return kbd_data_read_1();
349 }
350 #endif
351
352 /*
353 * Pass command byte to keyboard controller (8042).
354 */
355 int
356 kbc_put8042cmd(val)
357 u_char val;
358 {
359
360 if (!kbd_wait_output())
361 return 0;
362 kbd_cmd_write_1(K_LDCMDBYTE);
363 if (!kbd_wait_output())
364 return 0;
365 kbd_data_write_1(val);
366 return 1;
367 }
368
369 /*
370 * Pass command to keyboard itself
371 */
372 int
373 kbd_cmd(val, polling)
374 u_char val;
375 u_char polling;
376 {
377 u_int retries = 3;
378 u_int i;
379
380 if(!polling) {
381 i = spltty();
382 if(kb_oq_get == kb_oq_put) {
383 kbd_data_write_1(val);
384 }
385 kb_oq[kb_oq_put] = val;
386 kb_oq_put = (kb_oq_put + 1) & 7;
387 splx(i);
388 return(1);
389 }
390 else do {
391 if (!kbd_wait_output())
392 return 0;
393 kbd_data_write_1(val);
394 for (i = 100000; i; i--) {
395 if (kbd_cmd_read_1() & KBS_DIB) {
396 u_char c;
397
398 KBD_DELAY;
399 c = kbd_data_read_1();
400 if (c == KBR_ACK || c == KBR_ECHO) {
401 return 1;
402 }
403 if (c == KBR_RESEND) {
404 break;
405 }
406 #ifdef DIAGNOSTIC
407 printf("kbd_cmd: input char %x lost\n", c);
408 #endif
409 }
410 }
411 } while (--retries);
412 return 0;
413 }
414
415 void
416 set_cursor_shape()
417 {
418 crtc_write_1(0, 10);
419 crtc_write_1(1, cursor_shape >> 8);
420 crtc_write_1(0, 11);
421 crtc_write_1(1, cursor_shape);
422 old_cursor_shape = cursor_shape;
423 }
424
425 void
426 get_cursor_shape()
427 {
428 crtc_write_1(0, 10);
429 cursor_shape = crtc_read_1(1) << 8;
430 crtc_write_1(0, 11);
431 cursor_shape |= crtc_read_1(1);
432
433 /*
434 * real 6845's, as found on, MDA, Hercules or CGA cards, do
435 * not support reading the cursor shape registers. the 6845
436 * tri-states it's data bus. This is _normally_ read by the
437 * cpu as either 0x00 or 0xff.. in which case we just use
438 * a line cursor.
439 */
440 if (cursor_shape == 0x0000 || cursor_shape == 0xffff)
441 cursor_shape = 0x0b10;
442 else
443 cursor_shape &= 0x1f1f;
444 }
445
446 void
447 do_async_update(poll)
448 u_char poll;
449 {
450 int pos;
451 static int old_pos = -1;
452
453 async = 0;
454
455 if (lock_state != old_lock_state) {
456 old_lock_state = lock_state;
457 if (!kbd_cmd(KBC_MODEIND, poll) ||
458 !kbd_cmd(lock_state, poll)) {
459 printf("pc: timeout updating leds\n");
460 (void) kbd_cmd(KBC_ENABLE, poll);
461 }
462 }
463 if (typematic_rate != old_typematic_rate) {
464 old_typematic_rate = typematic_rate;
465 if (!kbd_cmd(KBC_TYPEMATIC, poll) ||
466 !kbd_cmd(typematic_rate, poll)) {
467 printf("pc: timeout updating typematic rate\n");
468 (void) kbd_cmd(KBC_ENABLE, poll);
469 }
470 }
471
472 if (pc_xmode > 0)
473 return;
474
475 pos = crtat - Crtat;
476 if (pos != old_pos) {
477 crtc_write_1(0, 14);
478 crtc_write_1(1, pos >> 8);
479 crtc_write_1(0, 15);
480 crtc_write_1(1, pos);
481 old_pos = pos;
482 }
483 if (cursor_shape != old_cursor_shape)
484 set_cursor_shape();
485 }
486
487 void
488 async_update()
489 {
490
491 if (kernel || polling) {
492 if (async)
493 callout_stop(&async_update_ch);
494 do_async_update(1);
495 } else {
496 if (async)
497 return;
498 async = 1;
499 callout_reset(&async_update_ch, 1,
500 (void(*)(void *))do_async_update, NULL);
501 }
502 }
503
504 /*
505 * these are both bad jokes
506 */
507 int
508 pccons_common_match(crt_iot, crt_memt, kbd_iot, config)
509 bus_space_tag_t crt_iot, crt_memt, kbd_iot;
510 struct pccons_config *config;
511 {
512 int i;
513
514 pc_context_init(crt_iot, crt_memt, kbd_iot, config);
515
516 /* Enable interrupts and keyboard, etc. */
517 if (!kbc_put8042cmd(CMDBYTE)) {
518 printf("pcprobe: command error\n");
519 return 0;
520 }
521
522 #if 1
523 /* Flush any garbage. */
524 kbd_flush_input();
525 /* Reset the keyboard. */
526 if (!kbd_cmd(KBC_RESET, 1)) {
527 printf("pcprobe: reset error %d\n", 1);
528 goto lose;
529 }
530 for (i = 600000; i; i--)
531 if ((kbd_cmd_read_1() & KBS_DIB) != 0) {
532 KBD_DELAY;
533 break;
534 }
535 if (i == 0 || kbd_data_read_1() != KBR_RSTDONE) {
536 printf("pcprobe: reset error %d\n", 2);
537 goto lose;
538 }
539 /*
540 * Some keyboards seem to leave a second ack byte after the reset.
541 * This is kind of stupid, but we account for them anyway by just
542 * flushing the buffer.
543 */
544 kbd_flush_input();
545 /* Just to be sure. */
546 if (!kbd_cmd(KBC_ENABLE, 1)) {
547 printf("pcprobe: reset error %d\n", 3);
548 goto lose;
549 }
550
551 /*
552 * Some keyboard/8042 combinations do not seem to work if the keyboard
553 * is set to table 1; in fact, it would appear that some keyboards just
554 * ignore the command altogether. So by default, we use the AT scan
555 * codes and have the 8042 translate them. Unfortunately, this is
556 * known to not work on some PS/2 machines. We try desparately to deal
557 * with this by checking the (lack of a) translate bit in the 8042 and
558 * attempting to set the keyboard to XT mode. If this all fails, well,
559 * tough luck.
560 *
561 * XXX It would perhaps be a better choice to just use AT scan codes
562 * and not bother with this.
563 */
564 if (kbc_get8042cmd() & KC8_TRANS) {
565 /* The 8042 is translating for us; use AT codes. */
566 if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(2, 1)) {
567 printf("pcprobe: reset error %d\n", 4);
568 goto lose;
569 }
570 } else {
571 /* Stupid 8042; set keyboard to XT codes. */
572 if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(1, 1)) {
573 printf("pcprobe: reset error %d\n", 5);
574 goto lose;
575 }
576 }
577
578 lose:
579 /*
580 * Technically, we should probably fail the probe. But we'll be nice
581 * and allow keyboard-less machines to boot with the console.
582 */
583 #endif
584
585 return 1;
586 }
587
588 void pccons_common_attach(sc, crt_iot, crt_memt, kbd_iot, config)
589 struct pc_softc *sc;
590 bus_space_tag_t crt_iot, crt_memt, kbd_iot;
591 struct pccons_config *config;
592 {
593 printf(": %s\n", vs.color ? "color" : "mono");
594 do_async_update(1);
595 }
596
597 int
598 pcopen(dev, flag, mode, p)
599 dev_t dev;
600 int flag, mode;
601 struct proc *p;
602 {
603 struct pc_softc *sc;
604 int unit = PCUNIT(dev);
605 struct tty *tp;
606
607 if (unit >= pc_cd.cd_ndevs)
608 return ENXIO;
609 sc = pc_cd.cd_devs[unit];
610 if (sc == 0)
611 return ENXIO;
612
613 if (!sc->sc_tty) {
614 tp = sc->sc_tty = ttymalloc();
615 }
616 else {
617 tp = sc->sc_tty;
618 }
619
620 tp->t_oproc = pcstart;
621 tp->t_param = pcparam;
622 tp->t_dev = dev;
623 if ((tp->t_state & TS_ISOPEN) == 0) {
624 ttychars(tp);
625 tp->t_iflag = TTYDEF_IFLAG;
626 tp->t_oflag = TTYDEF_OFLAG;
627 tp->t_cflag = TTYDEF_CFLAG;
628 tp->t_lflag = TTYDEF_LFLAG;
629 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
630 pcparam(tp, &tp->t_termios);
631 ttsetwater(tp);
632 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
633 return EBUSY;
634 tp->t_state |= TS_CARR_ON;
635
636 return ((*tp->t_linesw->l_open)(dev, tp));
637 }
638
639 int
640 pcclose(dev, flag, mode, p)
641 dev_t dev;
642 int flag, mode;
643 struct proc *p;
644 {
645 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
646 struct tty *tp = sc->sc_tty;
647
648 (*tp->t_linesw->l_close)(tp, flag);
649 ttyclose(tp);
650 #ifdef notyet /* XXX */
651 ttyfree(tp);
652 #endif
653 return(0);
654 }
655
656 int
657 pcread(dev, uio, flag)
658 dev_t dev;
659 struct uio *uio;
660 int flag;
661 {
662 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
663 struct tty *tp = sc->sc_tty;
664
665 return ((*tp->t_linesw->l_read)(tp, uio, flag));
666 }
667
668 int
669 pcwrite(dev, uio, flag)
670 dev_t dev;
671 struct uio *uio;
672 int flag;
673 {
674 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
675 struct tty *tp = sc->sc_tty;
676
677 return ((*tp->t_linesw->l_write)(tp, uio, flag));
678 }
679
680 int
681 pcpoll(dev, events, p)
682 dev_t dev;
683 int events;
684 struct proc *p;
685 {
686 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
687 struct tty *tp = sc->sc_tty;
688
689 return ((*tp->t_linesw->l_poll)(tp, events, p));
690 }
691
692 struct tty *
693 pctty(dev)
694 dev_t dev;
695 {
696 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
697 struct tty *tp = sc->sc_tty;
698
699 return (tp);
700 }
701
702 /*
703 * Got a console receive interrupt -
704 * the console processor wants to give us a character.
705 * Catch the character, and see who it goes to.
706 */
707 int
708 pcintr(arg)
709 void *arg;
710 {
711 struct pc_softc *sc = arg;
712 struct tty *tp = sc->sc_tty;
713 u_char *cp;
714
715 if ((kbd_cmd_read_1() & KBS_DIB) == 0)
716 return 0;
717 if (polling)
718 return 1;
719 do {
720 cp = sget();
721 if (!tp || (tp->t_state & TS_ISOPEN) == 0)
722 return 1;
723 if (cp)
724 do
725 (*tp->t_linesw->l_rint)(*cp++, tp);
726 while (*cp);
727 } while (kbd_cmd_read_1() & KBS_DIB);
728 return 1;
729 }
730
731 int
732 pcioctl(dev, cmd, data, flag, p)
733 dev_t dev;
734 u_long cmd;
735 caddr_t data;
736 int flag;
737 struct proc *p;
738 {
739 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
740 struct tty *tp = sc->sc_tty;
741 int error;
742
743 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
744 if (error != EPASSTHROUGH)
745 return error;
746 error = ttioctl(tp, cmd, data, flag, p);
747 if (error != EPASSTHROUGH)
748 return error;
749
750 switch (cmd) {
751 case CONSOLE_X_MODE_ON:
752 pc_xmode_on();
753 return 0;
754 case CONSOLE_X_MODE_OFF:
755 pc_xmode_off();
756 return 0;
757 case CONSOLE_X_BELL:
758 /*
759 * If set, data is a pointer to a length 2 array of
760 * integers. data[0] is the pitch in Hz and data[1]
761 * is the duration in msec.
762 */
763 if (data)
764 sysbeep(((int*)data)[0],
765 (((int*)data)[1] * hz) / 1000);
766 else
767 sysbeep(BEEP_FREQ, BEEP_TIME);
768 return 0;
769 case CONSOLE_SET_TYPEMATIC_RATE: {
770 u_char rate;
771
772 if (!data)
773 return EINVAL;
774 rate = *((u_char *)data);
775 /*
776 * Check that it isn't too big (which would cause it to be
777 * confused with a command).
778 */
779 if (rate & 0x80)
780 return EINVAL;
781 typematic_rate = rate;
782 async_update();
783 return 0;
784 }
785 case CONSOLE_SET_KEYMAP: {
786 pccons_keymap_t *map = (pccons_keymap_t *) data;
787 int i;
788
789 if (!data)
790 return EINVAL;
791 for (i = 0; i < KB_NUM_KEYS; i++)
792 if (map[i].unshift[KB_CODE_SIZE-1] ||
793 map[i].shift[KB_CODE_SIZE-1] ||
794 map[i].ctl[KB_CODE_SIZE-1] ||
795 map[i].altgr[KB_CODE_SIZE-1] ||
796 map[i].shift_altgr[KB_CODE_SIZE-1])
797 return EINVAL;
798
799 bcopy(data, scan_codes, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
800 return 0;
801 }
802 case CONSOLE_GET_KEYMAP:
803 if (!data)
804 return EINVAL;
805 bcopy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
806 return 0;
807
808 default:
809 return EPASSTHROUGH;
810 }
811
812 #ifdef DIAGNOSTIC
813 panic("pcioctl: impossible");
814 #endif
815 }
816
817 void
818 pcstart(tp)
819 struct tty *tp;
820 {
821 struct clist *cl;
822 int s, len;
823 u_char buf[PCBURST];
824
825 s = spltty();
826 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
827 goto out;
828 tp->t_state |= TS_BUSY;
829 splx(s);
830 /*
831 * We need to do this outside spl since it could be fairly
832 * expensive and we don't want our serial ports to overflow.
833 */
834 cl = &tp->t_outq;
835 len = q_to_b(cl, buf, PCBURST);
836 sput(buf, len);
837 s = spltty();
838 tp->t_state &= ~TS_BUSY;
839 if (cl->c_cc) {
840 tp->t_state |= TS_TIMEOUT;
841 callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp);
842 }
843 if (cl->c_cc <= tp->t_lowat) {
844 if (tp->t_state & TS_ASLEEP) {
845 tp->t_state &= ~TS_ASLEEP;
846 wakeup(cl);
847 }
848 selwakeup(&tp->t_wsel);
849 }
850 out:
851 splx(s);
852 }
853
854 /* ARGSUSED */
855 void pccons_common_cnattach(crt_iot, crt_memt, kbd_iot, config)
856 bus_space_tag_t crt_iot, crt_memt, kbd_iot;
857 struct pccons_config *config;
858 {
859 int maj;
860 static struct consdev pccons = {
861 NULL, NULL, pccngetc, pccnputc, pccnpollc, NULL, NULL,
862 NULL, NODEV, CN_NORMAL
863 };
864
865 /*
866 * For now, don't screw with it.
867 */
868 /* crtat = 0; */
869
870 pc_context_init(crt_iot, crt_memt, kbd_iot, config);
871
872 /* locate the major number */
873 maj = cdevsw_lookup_major(&pc_cdevsw);
874 pccons.cn_dev = makedev(maj, 0);
875
876 cn_tab = &pccons;
877 }
878
879 /* ARGSUSED */
880 void
881 pccnputc(dev, c)
882 dev_t dev;
883 int c;
884 {
885 u_char cc, oldkernel = kernel;
886
887 kernel = 1;
888 if (c == '\n') {
889 sput("\r\n", 2);
890 } else {
891 cc = c;
892 sput(&cc, 1);
893 }
894 kernel = oldkernel;
895 }
896
897 /* ARGSUSED */
898 int
899 pccngetc(dev)
900 dev_t dev;
901 {
902 char *cp;
903
904 if (pc_xmode > 0)
905 return 0;
906
907 do {
908 /* wait for byte */
909 while ((kbd_cmd_read_1() & KBS_DIB) == 0);
910 /* see if it's worthwhile */
911 cp = sget();
912 } while (!cp);
913 if (*cp == '\r')
914 return '\n';
915 return *cp;
916 }
917
918 void
919 pccnpollc(dev, on)
920 dev_t dev;
921 int on;
922 {
923
924 polling = on;
925 if (!on) {
926 int unit;
927 struct pc_softc *sc;
928 int s;
929
930 /*
931 * If disabling polling on a device that's been configured,
932 * make sure there are no bytes left in the FIFO, holding up
933 * the interrupt line. Otherwise we won't get any further
934 * interrupts.
935 */
936 unit = PCUNIT(dev);
937 if (pc_cd.cd_ndevs > unit) {
938 sc = pc_cd.cd_devs[unit];
939 if (sc != 0) {
940 s = spltty();
941 pcintr(sc);
942 splx(s);
943 }
944 }
945 }
946 }
947
948 /*
949 * Set line parameters.
950 */
951 int
952 pcparam(tp, t)
953 struct tty *tp;
954 struct termios *t;
955 {
956
957 tp->t_ispeed = t->c_ispeed;
958 tp->t_ospeed = t->c_ospeed;
959 tp->t_cflag = t->c_cflag;
960 return 0;
961 }
962
963 #define wrtchar(c, at) do {\
964 char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; \
965 } while (0)
966
967 /* translate ANSI color codes to standard pc ones */
968 static char fgansitopc[] = {
969 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
970 FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
971 };
972
973 static char bgansitopc[] = {
974 BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
975 BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
976 };
977
978 static u_char iso2ibm437[] =
979 {
980 0, 0, 0, 0, 0, 0, 0, 0,
981 0, 0, 0, 0, 0, 0, 0, 0,
982 0, 0, 0, 0, 0, 0, 0, 0,
983 0, 0, 0, 0, 0, 0, 0, 0,
984 0xff, 0xad, 0x9b, 0x9c, 0, 0x9d, 0, 0x40,
985 0x6f, 0x63, 0x61, 0xae, 0, 0, 0, 0,
986 0xf8, 0xf1, 0xfd, 0x33, 0, 0xe6, 0, 0xfa,
987 0, 0x31, 0x6f, 0xaf, 0xac, 0xab, 0, 0xa8,
988 0x41, 0x41, 0x41, 0x41, 0x8e, 0x8f, 0x92, 0x80,
989 0x45, 0x90, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
990 0x81, 0xa5, 0x4f, 0x4f, 0x4f, 0x4f, 0x99, 0x4f,
991 0x4f, 0x55, 0x55, 0x55, 0x9a, 0x59, 0, 0xe1,
992 0x85, 0xa0, 0x83, 0x61, 0x84, 0x86, 0x91, 0x87,
993 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b,
994 0, 0xa4, 0x95, 0xa2, 0x93, 0x6f, 0x94, 0x6f,
995 0x6f, 0x97, 0xa3, 0x96, 0x81, 0x98, 0, 0
996 };
997
998 /*
999 * `pc3' termcap emulation.
1000 */
1001 void
1002 sput(cp, n)
1003 u_char *cp;
1004 int n;
1005 {
1006 struct pccons_context *pc = &pccons_console_context;
1007 u_char c, scroll = 0;
1008
1009 if (pc_xmode > 0)
1010 return;
1011
1012 if (crtat == 0) {
1013 volatile u_short *cp;
1014 u_short was;
1015 unsigned cursorat;
1016
1017 cp = bus_space_vaddr(pc->pc_crt_memt, pc->pc_cga_memh);
1018 was = *cp;
1019 *cp = 0xA55A;
1020 if (*cp != 0xA55A) {
1021 cp = bus_space_vaddr(pc->pc_crt_memt,
1022 pc->pc_mono_memh);
1023 pc->pc_6845_ioh = pc->pc_mono_ioh;
1024 pc->pc_crt_memh = pc->pc_mono_memh;
1025 vs.color = 0;
1026 } else {
1027 *cp = was;
1028 pc->pc_6845_ioh = pc->pc_cga_ioh;
1029 pc->pc_crt_memh = pc->pc_cga_memh;
1030 vs.color = 1;
1031 }
1032
1033 #ifdef FAT_CURSOR
1034 cursor_shape = 0x0012;
1035 #else
1036 get_cursor_shape();
1037 #endif
1038
1039 bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow);
1040 vs.nchr = vs.ncol * vs.nrow;
1041 vs.col--;
1042 vs.row--;
1043 cursorat = vs.ncol * vs.row + vs.col;
1044 vs.at = FG_LIGHTGREY | BG_BLACK;
1045
1046 Crtat = (u_short *)cp;
1047 crtat = Crtat + cursorat;
1048
1049 if (vs.color == 0)
1050 vs.so_at = FG_BLACK | BG_LIGHTGREY;
1051 else
1052 vs.so_at = FG_YELLOW | BG_BLACK;
1053
1054 fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
1055 }
1056
1057 while (n--) {
1058 if (!(c = *cp++))
1059 continue;
1060
1061 switch (c) {
1062 case 0x1B:
1063 if (vs.state >= VSS_ESCAPE) {
1064 wrtchar(c, vs.so_at);
1065 vs.state = 0;
1066 goto maybe_scroll;
1067 } else
1068 vs.state = VSS_ESCAPE;
1069 break;
1070
1071 case 0x9B: /* CSI */
1072 vs.cx = vs.cy = 0;
1073 vs.state = VSS_EBRACE;
1074 break;
1075
1076 case '\t': {
1077 int inccol = 8 - (vs.col & 7);
1078 crtat += inccol;
1079 vs.col += inccol;
1080 }
1081 maybe_scroll:
1082 if (vs.col >= vs.ncol) {
1083 vs.col -= vs.ncol;
1084 scroll = 1;
1085 }
1086 break;
1087
1088 case '\b':
1089 if (crtat <= Crtat)
1090 break;
1091 --crtat;
1092 if (--vs.col < 0)
1093 vs.col += vs.ncol; /* non-destructive backspace */
1094 break;
1095
1096 case '\r':
1097 crtat -= vs.col;
1098 vs.col = 0;
1099 break;
1100
1101 case '\n':
1102 crtat += vs.ncol;
1103 scroll = 1;
1104 break;
1105
1106 default:
1107 switch (vs.state) {
1108 case 0:
1109 if (c == '\a')
1110 sysbeep(BEEP_FREQ, BEEP_TIME);
1111 else {
1112 /*
1113 * If we're outputting multiple printed
1114 * characters, just blast them to the
1115 * screen until we reach the end of the
1116 * buffer or a control character. This
1117 * saves time by short-circuiting the
1118 * switch.
1119 * If we reach the end of the line, we
1120 * break to do a scroll check.
1121 */
1122 for (;;) {
1123 if (c & 0x80)
1124 c = iso2ibm437[c&0x7f];
1125
1126 if (vs.so)
1127 wrtchar(c, vs.so_at);
1128 else
1129 wrtchar(c, vs.at);
1130 if (vs.col >= vs.ncol) {
1131 vs.col = 0;
1132 scroll = 1;
1133 break;
1134 }
1135 if (!n || (c = *cp) < ' ')
1136 break;
1137 n--, cp++;
1138 }
1139 }
1140 break;
1141 case VSS_ESCAPE:
1142 switch (c) {
1143 case '[': /* Start ESC [ sequence */
1144 vs.cx = vs.cy = 0;
1145 vs.state = VSS_EBRACE;
1146 break;
1147 case 'c': /* Create screen & home */
1148 fillw((vs.at << 8) | ' ',
1149 Crtat, vs.nchr);
1150 crtat = Crtat;
1151 vs.col = 0;
1152 vs.state = 0;
1153 break;
1154 case '7': /* save cursor pos */
1155 vs.offset = crtat - Crtat;
1156 vs.state = 0;
1157 break;
1158 case '8': /* restore cursor pos */
1159 crtat = Crtat + vs.offset;
1160 vs.row = vs.offset / vs.ncol;
1161 vs.col = vs.offset % vs.ncol;
1162 vs.state = 0;
1163 break;
1164 default: /* Invalid, clear state */
1165 wrtchar(c, vs.so_at);
1166 vs.state = 0;
1167 goto maybe_scroll;
1168 }
1169 break;
1170
1171 default: /* VSS_EBRACE or VSS_EPARAM */
1172 switch (c) {
1173 int pos;
1174 case 'm':
1175 if (!vs.cx)
1176 vs.so = 0;
1177 else
1178 vs.so = 1;
1179 vs.state = 0;
1180 break;
1181 case 'A': { /* back cx rows */
1182 int cx = vs.cx;
1183 if (cx <= 0)
1184 cx = 1;
1185 else
1186 cx %= vs.nrow;
1187 pos = crtat - Crtat;
1188 pos -= vs.ncol * cx;
1189 if (pos < 0)
1190 pos += vs.nchr;
1191 crtat = Crtat + pos;
1192 vs.state = 0;
1193 break;
1194 }
1195 case 'B': { /* down cx rows */
1196 int cx = vs.cx;
1197 if (cx <= 0)
1198 cx = 1;
1199 else
1200 cx %= vs.nrow;
1201 pos = crtat - Crtat;
1202 pos += vs.ncol * cx;
1203 if (pos >= vs.nchr)
1204 pos -= vs.nchr;
1205 crtat = Crtat + pos;
1206 vs.state = 0;
1207 break;
1208 }
1209 case 'C': { /* right cursor */
1210 int cx = vs.cx,
1211 col = vs.col;
1212 if (cx <= 0)
1213 cx = 1;
1214 else
1215 cx %= vs.ncol;
1216 pos = crtat - Crtat;
1217 pos += cx;
1218 col += cx;
1219 if (col >= vs.ncol) {
1220 pos -= vs.ncol;
1221 col -= vs.ncol;
1222 }
1223 vs.col = col;
1224 crtat = Crtat + pos;
1225 vs.state = 0;
1226 break;
1227 }
1228 case 'D': { /* left cursor */
1229 int cx = vs.cx,
1230 col = vs.col;
1231 if (cx <= 0)
1232 cx = 1;
1233 else
1234 cx %= vs.ncol;
1235 pos = crtat - Crtat;
1236 pos -= cx;
1237 col -= cx;
1238 if (col < 0) {
1239 pos += vs.ncol;
1240 col += vs.ncol;
1241 }
1242 vs.col = col;
1243 crtat = Crtat + pos;
1244 vs.state = 0;
1245 break;
1246 }
1247 case 'J': /* Clear ... */
1248 switch (vs.cx) {
1249 case 0:
1250 /* ... to end of display */
1251 fillw((vs.at << 8) | ' ',
1252 crtat,
1253 Crtat + vs.nchr - crtat);
1254 break;
1255 case 1:
1256 /* ... to next location */
1257 fillw((vs.at << 8) | ' ',
1258 Crtat,
1259 crtat - Crtat + 1);
1260 break;
1261 case 2:
1262 /* ... whole display */
1263 fillw((vs.at << 8) | ' ',
1264 Crtat,
1265 vs.nchr);
1266 break;
1267 }
1268 vs.state = 0;
1269 break;
1270 case 'K': /* Clear line ... */
1271 switch (vs.cx) {
1272 case 0:
1273 /* ... current to EOL */
1274 fillw((vs.at << 8) | ' ',
1275 crtat,
1276 vs.ncol - vs.col);
1277 break;
1278 case 1:
1279 /* ... beginning to next */
1280 fillw((vs.at << 8) | ' ',
1281 crtat - vs.col,
1282 vs.col + 1);
1283 break;
1284 case 2:
1285 /* ... entire line */
1286 fillw((vs.at << 8) | ' ',
1287 crtat - vs.col, vs.ncol);
1288 break;
1289 }
1290 vs.state = 0;
1291 break;
1292 case 'f': /* in system V consoles */
1293 case 'H': { /* Cursor move */
1294 int cx = vs.cx,
1295 cy = vs.cy;
1296 if (!cx || !cy) {
1297 crtat = Crtat;
1298 vs.col = 0;
1299 } else {
1300 if (cx > vs.nrow)
1301 cx = vs.nrow;
1302 if (cy > vs.ncol)
1303 cy = vs.ncol;
1304 crtat = Crtat +
1305 (cx - 1) * vs.ncol + cy - 1;
1306 vs.col = cy - 1;
1307 }
1308 vs.state = 0;
1309 break;
1310 }
1311 case 'M': { /* delete cx rows */
1312 u_short *crtAt = crtat - vs.col;
1313 int cx = vs.cx,
1314 row = (crtAt - Crtat) / vs.ncol,
1315 nrow = vs.nrow - row;
1316 if (cx <= 0)
1317 cx = 1;
1318 else if (cx > nrow)
1319 cx = nrow;
1320 if (cx < nrow)
1321 #ifdef PCCONS_FORCE_WORD
1322 wcopy(crtAt + vs.ncol * cx,
1323 crtAt, vs.ncol * (nrow -
1324 cx) * CHR);
1325 #else
1326 bcopy(crtAt + vs.ncol * cx,
1327 crtAt, vs.ncol * (nrow -
1328 cx) * CHR);
1329 #endif
1330 fillw((vs.at << 8) | ' ',
1331 crtAt + vs.ncol * (nrow - cx),
1332 vs.ncol * cx);
1333 vs.state = 0;
1334 break;
1335 }
1336 case 'S': { /* scroll up cx lines */
1337 int cx = vs.cx;
1338 if (cx <= 0)
1339 cx = 1;
1340 else if (cx > vs.nrow)
1341 cx = vs.nrow;
1342 if (cx < vs.nrow)
1343 #ifdef PCCONS_FORCE_WORD
1344 wcopy(Crtat + vs.ncol * cx,
1345 Crtat, vs.ncol * (vs.nrow -
1346 cx) * CHR);
1347 #else
1348 bcopy(Crtat + vs.ncol * cx,
1349 Crtat, vs.ncol * (vs.nrow -
1350 cx) * CHR);
1351 #endif
1352 fillw((vs.at << 8) | ' ',
1353 Crtat + vs.ncol * (vs.nrow - cx),
1354 vs.ncol * cx);
1355 /* crtat -= vs.ncol * cx; XXX */
1356 vs.state = 0;
1357 break;
1358 }
1359 case 'L': { /* insert cx rows */
1360 u_short *crtAt = crtat - vs.col;
1361 int cx = vs.cx,
1362 row = (crtAt - Crtat) / vs.ncol,
1363 nrow = vs.nrow - row;
1364 if (cx <= 0)
1365 cx = 1;
1366 else if (cx > nrow)
1367 cx = nrow;
1368 if (cx < nrow)
1369 #ifdef PCCONS_FORCE_WORD
1370 wcopy(crtAt,
1371 crtAt + vs.ncol * cx,
1372 vs.ncol * (nrow - cx) *
1373 CHR);
1374 #else
1375 bcopy(crtAt,
1376 crtAt + vs.ncol * cx,
1377 vs.ncol * (nrow - cx) *
1378 CHR);
1379 #endif
1380 fillw((vs.at << 8) | ' ', crtAt,
1381 vs.ncol * cx);
1382 vs.state = 0;
1383 break;
1384 }
1385 case 'T': { /* scroll down cx lines */
1386 int cx = vs.cx;
1387 if (cx <= 0)
1388 cx = 1;
1389 else if (cx > vs.nrow)
1390 cx = vs.nrow;
1391 if (cx < vs.nrow)
1392 #ifdef PCCONS_FORCE_WORD
1393 wcopy(Crtat,
1394 Crtat + vs.ncol * cx,
1395 vs.ncol * (vs.nrow - cx) *
1396 CHR);
1397 #else
1398 bcopy(Crtat,
1399 Crtat + vs.ncol * cx,
1400 vs.ncol * (vs.nrow - cx) *
1401 CHR);
1402 #endif
1403 fillw((vs.at << 8) | ' ', Crtat,
1404 vs.ncol * cx);
1405 /* crtat += vs.ncol * cx; XXX */
1406 vs.state = 0;
1407 break;
1408 }
1409 case ';': /* Switch params in cursor def */
1410 vs.state = VSS_EPARAM;
1411 break;
1412 case 'r':
1413 vs.so_at = (vs.cx & FG_MASK) |
1414 ((vs.cy << 4) & BG_MASK);
1415 vs.state = 0;
1416 break;
1417 case 's': /* save cursor pos */
1418 vs.offset = crtat - Crtat;
1419 vs.state = 0;
1420 break;
1421 case 'u': /* restore cursor pos */
1422 crtat = Crtat + vs.offset;
1423 vs.row = vs.offset / vs.ncol;
1424 vs.col = vs.offset % vs.ncol;
1425 vs.state = 0;
1426 break;
1427 case 'x': /* set attributes */
1428 switch (vs.cx) {
1429 case 0:
1430 vs.at = FG_LIGHTGREY | BG_BLACK;
1431 break;
1432 case 1:
1433 /* ansi background */
1434 if (!vs.color)
1435 break;
1436 vs.at &= FG_MASK;
1437 vs.at |= bgansitopc[vs.cy & 7];
1438 break;
1439 case 2:
1440 /* ansi foreground */
1441 if (!vs.color)
1442 break;
1443 vs.at &= BG_MASK;
1444 vs.at |= fgansitopc[vs.cy & 7];
1445 break;
1446 case 3:
1447 /* pc text attribute */
1448 if (vs.state >= VSS_EPARAM)
1449 vs.at = vs.cy;
1450 break;
1451 }
1452 vs.state = 0;
1453 break;
1454
1455 default: /* Only numbers valid here */
1456 if ((c >= '0') && (c <= '9')) {
1457 if (vs.state >= VSS_EPARAM) {
1458 vs.cy *= 10;
1459 vs.cy += c - '0';
1460 } else {
1461 vs.cx *= 10;
1462 vs.cx += c - '0';
1463 }
1464 } else
1465 vs.state = 0;
1466 break;
1467 }
1468 break;
1469 }
1470 }
1471 if (scroll) {
1472 scroll = 0;
1473 /* scroll check */
1474 if (crtat >= Crtat + vs.nchr) {
1475 if (!kernel) {
1476 int s = spltty();
1477 if (lock_state & KB_SCROLL)
1478 tsleep(&lock_state,
1479 PUSER, "pcputc", 0);
1480 splx(s);
1481 }
1482 #if PCCONS_FORCE_WORD
1483 wcopy(Crtat + vs.ncol, Crtat,
1484 (vs.nchr - vs.ncol) * CHR);
1485 #else
1486 bcopy(Crtat + vs.ncol, Crtat,
1487 (vs.nchr - vs.ncol) * CHR);
1488 #endif
1489 fillw((vs.at << 8) | ' ',
1490 Crtat + vs.nchr - vs.ncol,
1491 vs.ncol);
1492 crtat -= vs.ncol;
1493 }
1494 }
1495 }
1496 async_update();
1497 }
1498
1499 /* the unshifted code for KB_SHIFT keys is used by X to distinguish between
1500 left and right shift when reading the keyboard map */
1501 static pccons_keymap_t scan_codes[KB_NUM_KEYS] = {
1502 /* type unshift shift control altgr shift_altgr scancode */
1503 { KB_NONE, "", "", "", "", ""}, /* 0 unused */
1504 { KB_ASCII, "\033", "\033", "\033", "", ""}, /* 1 ESCape */
1505 { KB_ASCII, "1", "!", "!", "", ""}, /* 2 1 */
1506 { KB_ASCII, "2", "@", "\000", "", ""}, /* 3 2 */
1507 { KB_ASCII, "3", "#", "#", "", ""}, /* 4 3 */
1508 { KB_ASCII, "4", "$", "$", "", ""}, /* 5 4 */
1509 { KB_ASCII, "5", "%", "%", "", ""}, /* 6 5 */
1510 { KB_ASCII, "6", "^", "\036", "", ""}, /* 7 6 */
1511 { KB_ASCII, "7", "&", "&", "", ""}, /* 8 7 */
1512 { KB_ASCII, "8", "*", "\010", "", ""}, /* 9 8 */
1513 { KB_ASCII, "9", "(", "(", "", ""}, /* 10 9 */
1514 { KB_ASCII, "0", ")", ")", "", ""}, /* 11 0 */
1515 { KB_ASCII, "-", "_", "\037", "", ""}, /* 12 - */
1516 { KB_ASCII, "=", "+", "+", "", ""}, /* 13 = */
1517 { KB_ASCII, "\177", "\177", "\010", "", ""}, /* 14 backspace */
1518 { KB_ASCII, "\t", "\t", "\t", "", ""}, /* 15 tab */
1519 { KB_ASCII, "q", "Q", "\021", "", ""}, /* 16 q */
1520 { KB_ASCII, "w", "W", "\027", "", ""}, /* 17 w */
1521 { KB_ASCII, "e", "E", "\005", "", ""}, /* 18 e */
1522 { KB_ASCII, "r", "R", "\022", "", ""}, /* 19 r */
1523 { KB_ASCII, "t", "T", "\024", "", ""}, /* 20 t */
1524 { KB_ASCII, "y", "Y", "\031", "", ""}, /* 21 y */
1525 { KB_ASCII, "u", "U", "\025", "", ""}, /* 22 u */
1526 { KB_ASCII, "i", "I", "\011", "", ""}, /* 23 i */
1527 { KB_ASCII, "o", "O", "\017", "", ""}, /* 24 o */
1528 { KB_ASCII, "p", "P", "\020", "", ""}, /* 25 p */
1529 { KB_ASCII, "[", "{", "\033", "", ""}, /* 26 [ */
1530 { KB_ASCII, "]", "}", "\035", "", ""}, /* 27 ] */
1531 { KB_ASCII, "\r", "\r", "\n", "", ""}, /* 28 return */
1532 { KB_CTL, "", "", "", "", ""}, /* 29 control */
1533 { KB_ASCII, "a", "A", "\001", "", ""}, /* 30 a */
1534 { KB_ASCII, "s", "S", "\023", "", ""}, /* 31 s */
1535 { KB_ASCII, "d", "D", "\004", "", ""}, /* 32 d */
1536 { KB_ASCII, "f", "F", "\006", "", ""}, /* 33 f */
1537 { KB_ASCII, "g", "G", "\007", "", ""}, /* 34 g */
1538 { KB_ASCII, "h", "H", "\010", "", ""}, /* 35 h */
1539 { KB_ASCII, "j", "J", "\n", "", ""}, /* 36 j */
1540 { KB_ASCII, "k", "K", "\013", "", ""}, /* 37 k */
1541 { KB_ASCII, "l", "L", "\014", "", ""}, /* 38 l */
1542 { KB_ASCII, ";", ":", ";", "", ""}, /* 39 ; */
1543 { KB_ASCII, "'", "\"", "'", "", ""}, /* 40 ' */
1544 { KB_ASCII, "`", "~", "`", "", ""}, /* 41 ` */
1545 { KB_SHIFT, "\001", "", "", "", ""}, /* 42 shift */
1546 { KB_ASCII, "\\", "|", "\034", "", ""}, /* 43 \ */
1547 { KB_ASCII, "z", "Z", "\032", "", ""}, /* 44 z */
1548 { KB_ASCII, "x", "X", "\030", "", ""}, /* 45 x */
1549 { KB_ASCII, "c", "C", "\003", "", ""}, /* 46 c */
1550 { KB_ASCII, "v", "V", "\026", "", ""}, /* 47 v */
1551 { KB_ASCII, "b", "B", "\002", "", ""}, /* 48 b */
1552 { KB_ASCII, "n", "N", "\016", "", ""}, /* 49 n */
1553 { KB_ASCII, "m", "M", "\r", "", ""}, /* 50 m */
1554 { KB_ASCII, ",", "<", "<", "", ""}, /* 51 , */
1555 { KB_ASCII, ".", ">", ">", "", ""}, /* 52 . */
1556 { KB_ASCII, "/", "?", "\037", "", ""}, /* 53 / */
1557 { KB_SHIFT, "\002", "", "", "", ""}, /* 54 shift */
1558 { KB_KP, "*", "*", "*", "", ""}, /* 55 kp * */
1559 { KB_ALT, "", "", "", "", ""}, /* 56 alt */
1560 { KB_ASCII, " ", " ", "\000", "", ""}, /* 57 space */
1561 { KB_CAPS, "", "", "", "", ""}, /* 58 caps */
1562 { KB_FUNC, "\033[M", "\033[Y", "\033[k", "", ""}, /* 59 f1 */
1563 { KB_FUNC, "\033[N", "\033[Z", "\033[l", "", ""}, /* 60 f2 */
1564 { KB_FUNC, "\033[O", "\033[a", "\033[m", "", ""}, /* 61 f3 */
1565 { KB_FUNC, "\033[P", "\033[b", "\033[n", "", ""}, /* 62 f4 */
1566 { KB_FUNC, "\033[Q", "\033[c", "\033[o", "", ""}, /* 63 f5 */
1567 { KB_FUNC, "\033[R", "\033[d", "\033[p", "", ""}, /* 64 f6 */
1568 { KB_FUNC, "\033[S", "\033[e", "\033[q", "", ""}, /* 65 f7 */
1569 { KB_FUNC, "\033[T", "\033[f", "\033[r", "", ""}, /* 66 f8 */
1570 { KB_FUNC, "\033[U", "\033[g", "\033[s", "", ""}, /* 67 f9 */
1571 { KB_FUNC, "\033[V", "\033[h", "\033[t", "", ""}, /* 68 f10 */
1572 { KB_NUM, "", "", "", "", ""}, /* 69 num lock */
1573 { KB_SCROLL, "", "", "", "", ""}, /* 70 scroll lock */
1574 { KB_KP, "7", "\033[H", "7", "", ""}, /* 71 kp 7 */
1575 { KB_KP, "8", "\033[A", "8", "", ""}, /* 72 kp 8 */
1576 { KB_KP, "9", "\033[I", "9", "", ""}, /* 73 kp 9 */
1577 { KB_KP, "-", "-", "-", "", ""}, /* 74 kp - */
1578 { KB_KP, "4", "\033[D", "4", "", ""}, /* 75 kp 4 */
1579 { KB_KP, "5", "\033[E", "5", "", ""}, /* 76 kp 5 */
1580 { KB_KP, "6", "\033[C", "6", "", ""}, /* 77 kp 6 */
1581 { KB_KP, "+", "+", "+", "", ""}, /* 78 kp + */
1582 { KB_KP, "1", "\033[F", "1", "", ""}, /* 79 kp 1 */
1583 { KB_KP, "2", "\033[B", "2", "", ""}, /* 80 kp 2 */
1584 { KB_KP, "3", "\033[G", "3", "", ""}, /* 81 kp 3 */
1585 { KB_KP, "0", "\033[L", "0", "", ""}, /* 82 kp 0 */
1586 { KB_KP, ",", "\177", ",", "", ""}, /* 83 kp , */
1587 { KB_NONE, "", "", "", "", ""}, /* 84 0 */
1588 { KB_NONE, "", "", "", "", ""}, /* 85 0 */
1589 { KB_NONE, "", "", "", "", ""}, /* 86 0 */
1590 { KB_FUNC, "\033[W", "\033[i", "\033[u", "", ""}, /* 87 f11 */
1591 { KB_FUNC, "\033[X", "\033[j", "\033[v", "", ""}, /* 88 f12 */
1592 { KB_NONE, "", "", "", "", ""}, /* 89 0 */
1593 { KB_NONE, "", "", "", "", ""}, /* 90 0 */
1594 { KB_NONE, "", "", "", "", ""}, /* 91 0 */
1595 { KB_NONE, "", "", "", "", ""}, /* 92 0 */
1596 { KB_NONE, "", "", "", "", ""}, /* 93 0 */
1597 { KB_NONE, "", "", "", "", ""}, /* 94 0 */
1598 { KB_NONE, "", "", "", "", ""}, /* 95 0 */
1599 { KB_NONE, "", "", "", "", ""}, /* 96 0 */
1600 { KB_NONE, "", "", "", "", ""}, /* 97 0 */
1601 { KB_NONE, "", "", "", "", ""}, /* 98 0 */
1602 { KB_NONE, "", "", "", "", ""}, /* 99 0 */
1603 { KB_NONE, "", "", "", "", ""}, /* 100 */
1604 { KB_NONE, "", "", "", "", ""}, /* 101 */
1605 { KB_NONE, "", "", "", "", ""}, /* 102 */
1606 { KB_NONE, "", "", "", "", ""}, /* 103 */
1607 { KB_NONE, "", "", "", "", ""}, /* 104 */
1608 { KB_NONE, "", "", "", "", ""}, /* 105 */
1609 { KB_NONE, "", "", "", "", ""}, /* 106 */
1610 { KB_NONE, "", "", "", "", ""}, /* 107 */
1611 { KB_NONE, "", "", "", "", ""}, /* 108 */
1612 { KB_NONE, "", "", "", "", ""}, /* 109 */
1613 { KB_NONE, "", "", "", "", ""}, /* 110 */
1614 { KB_NONE, "", "", "", "", ""}, /* 111 */
1615 { KB_NONE, "", "", "", "", ""}, /* 112 */
1616 { KB_NONE, "", "", "", "", ""}, /* 113 */
1617 { KB_NONE, "", "", "", "", ""}, /* 114 */
1618 { KB_NONE, "", "", "", "", ""}, /* 115 */
1619 { KB_NONE, "", "", "", "", ""}, /* 116 */
1620 { KB_NONE, "", "", "", "", ""}, /* 117 */
1621 { KB_NONE, "", "", "", "", ""}, /* 118 */
1622 { KB_NONE, "", "", "", "", ""}, /* 119 */
1623 { KB_NONE, "", "", "", "", ""}, /* 120 */
1624 { KB_NONE, "", "", "", "", ""}, /* 121 */
1625 { KB_NONE, "", "", "", "", ""}, /* 122 */
1626 { KB_NONE, "", "", "", "", ""}, /* 123 */
1627 { KB_NONE, "", "", "", "", ""}, /* 124 */
1628 { KB_NONE, "", "", "", "", ""}, /* 125 */
1629 { KB_NONE, "", "", "", "", ""}, /* 126 */
1630 { KB_NONE, "", "", "", "", ""} /* 127 */
1631 };
1632
1633 /*
1634 * Get characters from the keyboard. If none are present, return NULL.
1635 */
1636 char *
1637 sget()
1638 {
1639 u_char dt;
1640 static u_char extended = 0, shift_state = 0;
1641 static u_char capchar[2];
1642
1643 top:
1644 KBD_DELAY;
1645 dt = kbd_data_read_1();
1646
1647 switch (dt) {
1648 case KBR_ACK: case KBR_ECHO:
1649 kb_oq_get = (kb_oq_get + 1) & 7;
1650 if(kb_oq_get != kb_oq_put) {
1651 kbd_data_write_1(kb_oq[kb_oq_get]);
1652 }
1653 goto loop;
1654 case KBR_RESEND:
1655 kbd_data_write_1(kb_oq[kb_oq_get]);
1656 goto loop;
1657 }
1658
1659 if (pc_xmode > 0) {
1660 #if defined(DDB) && defined(XSERVER_DDB)
1661 /* F12 enters the debugger while in X mode */
1662 if (dt == 88)
1663 Debugger();
1664 #endif
1665 capchar[0] = dt;
1666 capchar[1] = 0;
1667 /*
1668 * Check for locking keys.
1669 *
1670 * XXX Setting the LEDs this way is a bit bogus. What if the
1671 * keyboard has been remapped in X?
1672 */
1673 switch (scan_codes[dt & 0x7f].type) {
1674 case KB_NUM:
1675 if (dt & 0x80) {
1676 shift_state &= ~KB_NUM;
1677 break;
1678 }
1679 if (shift_state & KB_NUM)
1680 break;
1681 shift_state |= KB_NUM;
1682 lock_state ^= KB_NUM;
1683 async_update();
1684 break;
1685 case KB_CAPS:
1686 if (dt & 0x80) {
1687 shift_state &= ~KB_CAPS;
1688 break;
1689 }
1690 if (shift_state & KB_CAPS)
1691 break;
1692 shift_state |= KB_CAPS;
1693 lock_state ^= KB_CAPS;
1694 async_update();
1695 break;
1696 case KB_SCROLL:
1697 if (dt & 0x80) {
1698 shift_state &= ~KB_SCROLL;
1699 break;
1700 }
1701 if (shift_state & KB_SCROLL)
1702 break;
1703 shift_state |= KB_SCROLL;
1704 lock_state ^= KB_SCROLL;
1705 if ((lock_state & KB_SCROLL) == 0)
1706 wakeup((caddr_t)&lock_state);
1707 async_update();
1708 break;
1709 }
1710 return capchar;
1711 }
1712
1713 switch (dt) {
1714 case KBR_EXTENDED:
1715 extended = 1;
1716 goto loop;
1717 }
1718
1719 #ifdef DDB
1720 /*
1721 * Check for cntl-alt-esc.
1722 */
1723 if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
1724 /* XXX - check pccons_is_console */
1725 Debugger();
1726 dt |= 0x80; /* discard esc (ddb discarded ctl-alt) */
1727 }
1728 #endif
1729
1730 /*
1731 * Check for make/break.
1732 */
1733 if (dt & 0x80) {
1734 /*
1735 * break
1736 */
1737 dt &= 0x7f;
1738 switch (scan_codes[dt].type) {
1739 case KB_NUM:
1740 shift_state &= ~KB_NUM;
1741 break;
1742 case KB_CAPS:
1743 shift_state &= ~KB_CAPS;
1744 break;
1745 case KB_SCROLL:
1746 shift_state &= ~KB_SCROLL;
1747 break;
1748 case KB_SHIFT:
1749 shift_state &= ~KB_SHIFT;
1750 break;
1751 case KB_ALT:
1752 if (extended)
1753 shift_state &= ~KB_ALTGR;
1754 else
1755 shift_state &= ~KB_ALT;
1756 break;
1757 case KB_CTL:
1758 shift_state &= ~KB_CTL;
1759 break;
1760 }
1761 } else {
1762 /*
1763 * make
1764 */
1765 switch (scan_codes[dt].type) {
1766 /*
1767 * locking keys
1768 */
1769 case KB_NUM:
1770 if (shift_state & KB_NUM)
1771 break;
1772 shift_state |= KB_NUM;
1773 lock_state ^= KB_NUM;
1774 async_update();
1775 break;
1776 case KB_CAPS:
1777 if (shift_state & KB_CAPS)
1778 break;
1779 shift_state |= KB_CAPS;
1780 lock_state ^= KB_CAPS;
1781 async_update();
1782 break;
1783 case KB_SCROLL:
1784 if (shift_state & KB_SCROLL)
1785 break;
1786 shift_state |= KB_SCROLL;
1787 lock_state ^= KB_SCROLL;
1788 if ((lock_state & KB_SCROLL) == 0)
1789 wakeup((caddr_t)&lock_state);
1790 async_update();
1791 break;
1792 /*
1793 * non-locking keys
1794 */
1795 case KB_SHIFT:
1796 shift_state |= KB_SHIFT;
1797 break;
1798 case KB_ALT:
1799 if (extended)
1800 shift_state |= KB_ALTGR;
1801 else
1802 shift_state |= KB_ALT;
1803 break;
1804 case KB_CTL:
1805 shift_state |= KB_CTL;
1806 break;
1807 case KB_ASCII:
1808 /* control has highest priority */
1809 if (shift_state & KB_CTL)
1810 capchar[0] = scan_codes[dt].ctl[0];
1811 else if (shift_state & KB_ALTGR) {
1812 if (shift_state & KB_SHIFT)
1813 capchar[0] = scan_codes[dt].shift_altgr[0];
1814 else
1815 capchar[0] = scan_codes[dt].altgr[0];
1816 }
1817 else {
1818 if (shift_state & KB_SHIFT)
1819 capchar[0] = scan_codes[dt].shift[0];
1820 else
1821 capchar[0] = scan_codes[dt].unshift[0];
1822 }
1823 if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
1824 capchar[0] <= 'z') {
1825 capchar[0] -= ('a' - 'A');
1826 }
1827 capchar[0] |= (shift_state & KB_ALT);
1828 extended = 0;
1829 return capchar;
1830 case KB_NONE:
1831 printf("keycode %d\n",dt);
1832 break;
1833 case KB_FUNC: {
1834 char *more_chars;
1835 if (shift_state & KB_SHIFT)
1836 more_chars = scan_codes[dt].shift;
1837 else if (shift_state & KB_CTL)
1838 more_chars = scan_codes[dt].ctl;
1839 else
1840 more_chars = scan_codes[dt].unshift;
1841 extended = 0;
1842 return more_chars;
1843 }
1844 case KB_KP: {
1845 char *more_chars;
1846 if (shift_state & (KB_SHIFT | KB_CTL) ||
1847 (lock_state & KB_NUM) == 0 || extended)
1848 more_chars = scan_codes[dt].shift;
1849 else
1850 more_chars = scan_codes[dt].unshift;
1851 extended = 0;
1852 return more_chars;
1853 }
1854 }
1855 }
1856
1857 extended = 0;
1858 loop:
1859 if ((kbd_cmd_read_1() & KBS_DIB) == 0)
1860 return 0;
1861 goto top;
1862 }
1863
1864 paddr_t
1865 pcmmap(dev, offset, nprot)
1866 dev_t dev;
1867 off_t offset;
1868 int nprot;
1869 {
1870 struct pccons_context *pc = &pccons_console_context;
1871 paddr_t pa;
1872
1873 if (offset >= 0xa0000 && offset < 0xc0000) {
1874 if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
1875 return (-1);
1876 pa += offset - pc->pc_config->pc_mono_memaddr;
1877 return (mips_btop(pa));
1878 }
1879 if (offset >= 0x0000 && offset < 0x10000) {
1880 if (bus_space_paddr(pc->pc_crt_iot, pc->pc_mono_ioh, &pa))
1881 return (-1);
1882 pa += offset - pc->pc_config->pc_mono_iobase;
1883 return (mips_btop(pa));
1884 }
1885 if (offset >= 0x40000000 && offset < 0x40800000) {
1886 if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
1887 return (-1);
1888 pa += offset - 0x40000000 - pc->pc_config->pc_mono_memaddr;
1889 return (mips_btop(pa));
1890 }
1891 return (-1);
1892 }
1893
1894 void
1895 pc_xmode_on()
1896 {
1897 if (pc_xmode)
1898 return;
1899 pc_xmode = 1;
1900
1901 #ifdef XFREE86_BUG_COMPAT
1902 /* If still unchanged, get current shape. */
1903 if (cursor_shape == 0xffff)
1904 get_cursor_shape();
1905 #endif
1906 }
1907
1908 void
1909 pc_xmode_off()
1910 {
1911 if (pc_xmode == 0)
1912 return;
1913 pc_xmode = 0;
1914
1915 #ifdef XFREE86_BUG_COMPAT
1916 /* XXX It would be hard to justify why the X server doesn't do this. */
1917 set_cursor_shape();
1918 #endif
1919 async_update();
1920 }
1921