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