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