Home | History | Annotate | Line # | Download | only in dev
pccons.c revision 1.57
      1 /*	$NetBSD: pccons.c,v 1.57 2009/03/14 21:04:04 dsl 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.57 2009/03/14 21:04:04 dsl 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 callout_t async_update_ch;
    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(const 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 value.
    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(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 polled)
    369 {
    370 	u_int retries = 3;
    371 	u_int i;
    372 
    373 	if (!polled) {
    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 
    384 	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 	callout_init(&async_update_ch, 0);
    589 	do_async_update(1);
    590 }
    591 
    592 int
    593 pcopen(dev_t dev, int flag, int mode, struct lwp *l)
    594 {
    595 	struct pc_softc *sc;
    596 	struct tty *tp;
    597 
    598 	sc = device_lookup_private(&pc_cd, PCUNIT(dev));
    599 	if (sc == NULL)
    600 		return ENXIO;
    601 
    602 	if (!sc->sc_tty) {
    603 		tp = sc->sc_tty = ttymalloc();
    604 	}
    605 	else {
    606 		tp = sc->sc_tty;
    607 	}
    608 
    609 	tp->t_oproc = pcstart;
    610 	tp->t_param = pcparam;
    611 	tp->t_dev = dev;
    612 
    613 	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
    614 		return (EBUSY);
    615 
    616 	if ((tp->t_state & TS_ISOPEN) == 0) {
    617 		ttychars(tp);
    618 		tp->t_iflag = TTYDEF_IFLAG;
    619 		tp->t_oflag = TTYDEF_OFLAG;
    620 		tp->t_cflag = TTYDEF_CFLAG;
    621 		tp->t_lflag = TTYDEF_LFLAG;
    622 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
    623 		pcparam(tp, &tp->t_termios);
    624 		ttsetwater(tp);
    625 	}
    626 
    627 	tp->t_state |= TS_CARR_ON;
    628 
    629 	return (*tp->t_linesw->l_open)(dev, tp);
    630 }
    631 
    632 int
    633 pcclose(dev_t dev, int flag, int mode, struct lwp *l)
    634 {
    635 	struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
    636 	struct tty *tp = sc->sc_tty;
    637 
    638 	(*tp->t_linesw->l_close)(tp, flag);
    639 	ttyclose(tp);
    640 #ifdef notyet /* XXX */
    641 	ttyfree(tp);
    642 #endif
    643 	return 0;
    644 }
    645 
    646 int
    647 pcread(dev_t dev, struct uio *uio, int flag)
    648 {
    649 	struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
    650 	struct tty *tp = sc->sc_tty;
    651 
    652 	return (*tp->t_linesw->l_read)(tp, uio, flag);
    653 }
    654 
    655 int
    656 pcwrite(dev_t dev, struct uio *uio, int flag)
    657 {
    658 	struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
    659 	struct tty *tp = sc->sc_tty;
    660 
    661 	return (*tp->t_linesw->l_write)(tp, uio, flag);
    662 }
    663 
    664 int
    665 pcpoll(dev_t dev, int events, struct lwp *l)
    666 {
    667 	struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
    668 	struct tty *tp = sc->sc_tty;
    669 
    670 	return (*tp->t_linesw->l_poll)(tp, events, l);
    671 }
    672 
    673 struct tty *
    674 pctty(dev_t dev)
    675 {
    676 	struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
    677 	struct tty *tp = sc->sc_tty;
    678 
    679 	return tp;
    680 }
    681 
    682 /*
    683  * Got a console receive interrupt -
    684  * the console processor wants to give us a character.
    685  * Catch the character, and see who it goes to.
    686  */
    687 int
    688 pcintr(void *arg)
    689 {
    690 	struct pc_softc *sc = arg;
    691 	struct tty *tp = sc->sc_tty;
    692 	uint8_t *cp;
    693 
    694 	if ((kbd_cmd_read_1() & KBS_DIB) == 0)
    695 		return 0;
    696 	if (polling)
    697 		return 1;
    698 	do {
    699 		cp = sget();
    700 		if (!tp || (tp->t_state & TS_ISOPEN) == 0)
    701 			return 1;
    702 		if (cp)
    703 			do
    704 				(*tp->t_linesw->l_rint)(*cp++, tp);
    705 			while (*cp);
    706 	} while (kbd_cmd_read_1() & KBS_DIB);
    707 	return 1;
    708 }
    709 
    710 int
    711 pcioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
    712 {
    713 	struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
    714 	struct tty *tp = sc->sc_tty;
    715 	int error;
    716 
    717 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
    718 	if (error != EPASSTHROUGH)
    719 		return error;
    720 	error = ttioctl(tp, cmd, data, flag, l);
    721 	if (error != EPASSTHROUGH)
    722 		return error;
    723 
    724 	switch (cmd) {
    725 	case CONSOLE_X_MODE_ON:
    726 		pc_xmode_on();
    727 		return 0;
    728 	case CONSOLE_X_MODE_OFF:
    729 		pc_xmode_off();
    730 		return 0;
    731 	case CONSOLE_X_BELL:
    732 		/*
    733 		 * If set, data is a pointer to a length 2 array of
    734 		 * integers.  data[0] is the pitch in Hz and data[1]
    735 		 * is the duration in msec.
    736 		 */
    737 		if (data)
    738 			sysbeep(((int*)data)[0],
    739 				(((int*)data)[1] * hz) / 1000);
    740 		else
    741 			sysbeep(BEEP_FREQ, BEEP_TIME);
    742 		return 0;
    743 	case CONSOLE_SET_TYPEMATIC_RATE: {
    744  		u_char	rate;
    745 
    746  		if (!data)
    747 			return EINVAL;
    748 		rate = *((u_char *)data);
    749 		/*
    750 		 * Check that it isn't too big (which would cause it to be
    751 		 * confused with a command).
    752 		 */
    753 		if (rate & 0x80)
    754 			return EINVAL;
    755 		typematic_rate = rate;
    756 		async_update();
    757 		return 0;
    758  	}
    759 	case CONSOLE_SET_KEYMAP: {
    760 		pccons_keymap_t *map = (pccons_keymap_t *) data;
    761 		int i;
    762 
    763 		if (!data)
    764 			return EINVAL;
    765 		for (i = 0; i < KB_NUM_KEYS; i++)
    766 			if (map[i].unshift[KB_CODE_SIZE-1] ||
    767 			    map[i].shift[KB_CODE_SIZE-1] ||
    768 			    map[i].ctl[KB_CODE_SIZE-1] ||
    769 			    map[i].altgr[KB_CODE_SIZE-1] ||
    770 			    map[i].shift_altgr[KB_CODE_SIZE-1])
    771 				return EINVAL;
    772 
    773 		memcpy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
    774 		return 0;
    775 	}
    776 	case CONSOLE_GET_KEYMAP:
    777 		if (!data)
    778 			return EINVAL;
    779 		memcpy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
    780 		return 0;
    781 
    782 	default:
    783 		return EPASSTHROUGH;
    784 	}
    785 
    786 #ifdef DIAGNOSTIC
    787 	panic("pcioctl: impossible");
    788 #endif
    789 }
    790 
    791 void
    792 pcstart(struct tty *tp)
    793 {
    794 	struct clist *cl;
    795 	int s, len;
    796 	u_char buf[PCBURST];
    797 
    798 	s = spltty();
    799 	if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
    800 		goto out;
    801 	tp->t_state |= TS_BUSY;
    802 	splx(s);
    803 	/*
    804 	 * We need to do this outside spl since it could be fairly
    805 	 * expensive and we don't want our serial ports to overflow.
    806 	 */
    807 	cl = &tp->t_outq;
    808 	len = q_to_b(cl, buf, PCBURST);
    809 	sput(buf, len);
    810 	s = spltty();
    811 	tp->t_state &= ~TS_BUSY;
    812 	if (ttypull(tp)) {
    813 		tp->t_state |= TS_TIMEOUT;
    814 		callout_schedule(&tp->t_rstrt_ch, 1);
    815 	}
    816 out:
    817 	splx(s);
    818 }
    819 
    820 /* ARGSUSED */
    821 void pccons_common_cnattach(bus_space_tag_t crt_iot, bus_space_tag_t crt_memt,
    822     bus_space_tag_t kbd_iot, struct pccons_config *config)
    823 {
    824 	int maj;
    825 	static struct consdev pccons = {
    826 		NULL, NULL, pccngetc, pccnputc, pccnpollc, NULL, NULL,
    827 		    NULL, NODEV, CN_NORMAL
    828 	};
    829 
    830 	/*
    831 	 * For now, don't screw with it.
    832 	 */
    833 	/* crtat = 0; */
    834 
    835 	pc_context_init(crt_iot, crt_memt, kbd_iot, config);
    836 
    837 	/* locate the major number */
    838 	maj = cdevsw_lookup_major(&pc_cdevsw);
    839 	pccons.cn_dev = makedev(maj, 0);
    840 
    841 	cn_tab = &pccons;
    842 }
    843 
    844 /* ARGSUSED */
    845 void
    846 pccnputc(dev_t dev, int c)
    847 {
    848 	u_char cc, oldkernel = kernel;
    849 
    850 	kernel = 1;
    851 	if (c == '\n') {
    852 		sput("\r\n", 2);
    853 	} else {
    854 		cc = c;
    855 		sput(&cc, 1);
    856 	}
    857 	kernel = oldkernel;
    858 }
    859 
    860 /* ARGSUSED */
    861 int
    862 pccngetc(dev_t dev)
    863 {
    864 	char *cp;
    865 
    866 	if (pc_xmode > 0)
    867 		return 0;
    868 
    869 	do {
    870 		/* wait for byte */
    871 		while ((kbd_cmd_read_1() & KBS_DIB) == 0);
    872 		/* see if it's worthwhile */
    873 		cp = sget();
    874 	} while (!cp);
    875 	if (*cp == '\r')
    876 		return '\n';
    877 	return *cp;
    878 }
    879 
    880 void
    881 pccnpollc(dev_t dev, int on)
    882 {
    883 
    884 	polling = on;
    885 	if (!on) {
    886 		int unit;
    887 		struct pc_softc *sc;
    888 		int s;
    889 
    890 		/*
    891 		 * If disabling polling on a device that's been configured,
    892 		 * make sure there are no bytes left in the FIFO, holding up
    893 		 * the interrupt line.  Otherwise we won't get any further
    894 		 * interrupts.
    895 		 */
    896 		unit = PCUNIT(dev);
    897 		if (pc_cd.cd_ndevs > unit) {
    898 			sc = device_lookup_private(&pc_cd, unit);
    899 			if (sc != NULL) {
    900 				s = spltty();
    901 				pcintr(sc);
    902 				splx(s);
    903 			}
    904 		}
    905 	}
    906 }
    907 
    908 /*
    909  * Set line parameters.
    910  */
    911 int
    912 pcparam(struct tty *tp, struct termios *t)
    913 {
    914 
    915 	tp->t_ispeed = t->c_ispeed;
    916 	tp->t_ospeed = t->c_ospeed;
    917 	tp->t_cflag = t->c_cflag;
    918 	return 0;
    919 }
    920 
    921 #define	wrtchar(c, at) do {\
    922 	char *cp0 = (char *)crtat; *cp0++ = (c); *cp0 = (at); crtat++; vs.col++; \
    923 } while (0)
    924 
    925 /* translate ANSI color codes to standard pc ones */
    926 static char fgansitopc[] = {
    927 	FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
    928 	FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
    929 };
    930 
    931 static char bgansitopc[] = {
    932 	BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
    933 	BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
    934 };
    935 
    936 static u_char iso2ibm437[] =
    937 {
    938             0,     0,     0,     0,     0,     0,     0,     0,
    939             0,     0,     0,     0,     0,     0,     0,     0,
    940             0,     0,     0,     0,     0,     0,     0,     0,
    941             0,     0,     0,     0,     0,     0,     0,     0,
    942          0xff,  0xad,  0x9b,  0x9c,     0,  0x9d,     0,  0x40,
    943          0x6f,  0x63,  0x61,  0xae,     0,     0,     0,     0,
    944          0xf8,  0xf1,  0xfd,  0x33,     0,  0xe6,     0,  0xfa,
    945             0,  0x31,  0x6f,  0xaf,  0xac,  0xab,     0,  0xa8,
    946          0x41,  0x41,  0x41,  0x41,  0x8e,  0x8f,  0x92,  0x80,
    947          0x45,  0x90,  0x45,  0x45,  0x49,  0x49,  0x49,  0x49,
    948          0x81,  0xa5,  0x4f,  0x4f,  0x4f,  0x4f,  0x99,  0x4f,
    949          0x4f,  0x55,  0x55,  0x55,  0x9a,  0x59,     0,  0xe1,
    950          0x85,  0xa0,  0x83,  0x61,  0x84,  0x86,  0x91,  0x87,
    951          0x8a,  0x82,  0x88,  0x89,  0x8d,  0xa1,  0x8c,  0x8b,
    952             0,  0xa4,  0x95,  0xa2,  0x93,  0x6f,  0x94,  0x6f,
    953          0x6f,  0x97,  0xa3,  0x96,  0x81,  0x98,     0,     0
    954 };
    955 
    956 /*
    957  * `pc3' termcap emulation.
    958  */
    959 void
    960 sput(const u_char *cp, int n)
    961 {
    962 	struct pccons_context *pc = &pccons_console_context;
    963 	u_char c, scroll = 0;
    964 
    965 	if (pc_xmode > 0)
    966 		return;
    967 
    968 	if (crtat == 0) {
    969 		volatile u_short *dp;
    970 		u_short was;
    971 		unsigned cursorat;
    972 
    973 		dp = bus_space_vaddr(pc->pc_crt_memt, pc->pc_cga_memh);
    974 		was = *dp;
    975 		*dp = 0xA55A;
    976 		if (*dp != 0xA55A) {
    977 			dp = bus_space_vaddr(pc->pc_crt_memt,
    978 			    pc->pc_mono_memh);
    979 			pc->pc_6845_ioh = pc->pc_mono_ioh;
    980 			pc->pc_crt_memh = pc->pc_mono_memh;
    981 			vs.color = 0;
    982 		} else {
    983 			*dp = was;
    984 			pc->pc_6845_ioh = pc->pc_cga_ioh;
    985 			pc->pc_crt_memh = pc->pc_cga_memh;
    986 			vs.color = 1;
    987 		}
    988 
    989 #ifdef FAT_CURSOR
    990 		cursor_shape = 0x0012;
    991 #else
    992 		get_cursor_shape();
    993 #endif
    994 
    995 		bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow);
    996 		vs.nchr = vs.ncol * vs.nrow;
    997 		vs.col--;
    998 		vs.row--;
    999 		cursorat = vs.ncol * vs.row + vs.col;
   1000 		vs.at = FG_LIGHTGREY | BG_BLACK;
   1001 
   1002 		Crtat = (u_short *)__UNVOLATILE(dp);
   1003 		crtat = Crtat + cursorat;
   1004 
   1005 		if (vs.color == 0)
   1006 			vs.so_at = FG_BLACK | BG_LIGHTGREY;
   1007 		else
   1008 			vs.so_at = FG_YELLOW | BG_BLACK;
   1009 
   1010 		fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
   1011 	}
   1012 
   1013 	while (n--) {
   1014 		if (!(c = *cp++))
   1015 			continue;
   1016 
   1017 		switch (c) {
   1018 		case 0x1B:
   1019 			if (vs.state >= VSS_ESCAPE) {
   1020 				wrtchar(c, vs.so_at);
   1021 				vs.state = 0;
   1022 				goto maybe_scroll;
   1023 			} else
   1024 				vs.state = VSS_ESCAPE;
   1025 			break;
   1026 
   1027 		case 0x9B:	/* CSI */
   1028 			vs.cx = vs.cy = 0;
   1029 			vs.state = VSS_EBRACE;
   1030 			break;
   1031 
   1032 		case '\t': {
   1033 			int inccol = 8 - (vs.col & 7);
   1034 			crtat += inccol;
   1035 			vs.col += inccol;
   1036 		}
   1037 		maybe_scroll:
   1038 			if (vs.col >= vs.ncol) {
   1039 				vs.col -= vs.ncol;
   1040 				scroll = 1;
   1041 			}
   1042 			break;
   1043 
   1044 		case '\b':
   1045 			if (crtat <= Crtat)
   1046 				break;
   1047 			--crtat;
   1048 			if (--vs.col < 0)
   1049 				vs.col += vs.ncol;	/* non-destructive backspace */
   1050 			break;
   1051 
   1052 		case '\r':
   1053 			crtat -= vs.col;
   1054 			vs.col = 0;
   1055 			break;
   1056 
   1057 		case '\n':
   1058 			crtat += vs.ncol;
   1059 			scroll = 1;
   1060 			break;
   1061 
   1062 		default:
   1063 			switch (vs.state) {
   1064 			case 0:
   1065 				if (c == '\a')
   1066 					sysbeep(BEEP_FREQ, BEEP_TIME);
   1067 				else {
   1068 					/*
   1069 					 * If we're outputting multiple printed
   1070 					 * characters, just blast them to the
   1071 					 * screen until we reach the end of the
   1072 					 * buffer or a control character.  This
   1073 					 * saves time by short-circuiting the
   1074 					 * switch.
   1075 					 * If we reach the end of the line, we
   1076 					 * break to do a scroll check.
   1077 					 */
   1078 					for (;;) {
   1079 						if (c & 0x80)
   1080 							c = iso2ibm437[c&0x7f];
   1081 
   1082 						if (vs.so)
   1083 							wrtchar(c, vs.so_at);
   1084 						else
   1085 							wrtchar(c, vs.at);
   1086 						if (vs.col >= vs.ncol) {
   1087 							vs.col = 0;
   1088 							scroll = 1;
   1089 							break;
   1090 						}
   1091 						if (!n || (c = *cp) < ' ')
   1092 							break;
   1093 						n--, cp++;
   1094 					}
   1095 				}
   1096 				break;
   1097 			case VSS_ESCAPE:
   1098 				switch (c) {
   1099 					case '[': /* Start ESC [ sequence */
   1100 						vs.cx = vs.cy = 0;
   1101 						vs.state = VSS_EBRACE;
   1102 						break;
   1103 					case 'c': /* Create screen & home */
   1104 						fillw((vs.at << 8) | ' ',
   1105 						    Crtat, vs.nchr);
   1106 						crtat = Crtat;
   1107 						vs.col = 0;
   1108 						vs.state = 0;
   1109 						break;
   1110 					case '7': /* save cursor pos */
   1111 						vs.offset = crtat - Crtat;
   1112 						vs.state = 0;
   1113 						break;
   1114 					case '8': /* restore cursor pos */
   1115 						crtat = Crtat + vs.offset;
   1116 						vs.row = vs.offset / vs.ncol;
   1117 						vs.col = vs.offset % vs.ncol;
   1118 						vs.state = 0;
   1119 						break;
   1120 					default: /* Invalid, clear state */
   1121 						wrtchar(c, vs.so_at);
   1122 						vs.state = 0;
   1123 						goto maybe_scroll;
   1124 				}
   1125 				break;
   1126 
   1127 			default: /* VSS_EBRACE or VSS_EPARAM */
   1128 				switch (c) {
   1129 					int pos;
   1130 				case 'm':
   1131 					if (!vs.cx)
   1132 						vs.so = 0;
   1133 					else
   1134 						vs.so = 1;
   1135 					vs.state = 0;
   1136 					break;
   1137 				case 'A': { /* back cx rows */
   1138 					int cx = vs.cx;
   1139 					if (cx <= 0)
   1140 						cx = 1;
   1141 					else
   1142 						cx %= vs.nrow;
   1143 					pos = crtat - Crtat;
   1144 					pos -= vs.ncol * cx;
   1145 					if (pos < 0)
   1146 						pos += vs.nchr;
   1147 					crtat = Crtat + pos;
   1148 					vs.state = 0;
   1149 					break;
   1150 				}
   1151 				case 'B': { /* down cx rows */
   1152 					int cx = vs.cx;
   1153 					if (cx <= 0)
   1154 						cx = 1;
   1155 					else
   1156 						cx %= vs.nrow;
   1157 					pos = crtat - Crtat;
   1158 					pos += vs.ncol * cx;
   1159 					if (pos >= vs.nchr)
   1160 						pos -= vs.nchr;
   1161 					crtat = Crtat + pos;
   1162 					vs.state = 0;
   1163 					break;
   1164 				}
   1165 				case 'C': { /* right cursor */
   1166 					int cx = vs.cx,
   1167 					    col = vs.col;
   1168 					if (cx <= 0)
   1169 						cx = 1;
   1170 					else
   1171 						cx %= vs.ncol;
   1172 					pos = crtat - Crtat;
   1173 					pos += cx;
   1174 					col += cx;
   1175 					if (col >= vs.ncol) {
   1176 						pos -= vs.ncol;
   1177 						col -= vs.ncol;
   1178 					}
   1179 					vs.col = col;
   1180 					crtat = Crtat + pos;
   1181 					vs.state = 0;
   1182 					break;
   1183 				}
   1184 				case 'D': { /* left cursor */
   1185 					int cx = vs.cx,
   1186 					    col = vs.col;
   1187 					if (cx <= 0)
   1188 						cx = 1;
   1189 					else
   1190 						cx %= vs.ncol;
   1191 					pos = crtat - Crtat;
   1192 					pos -= cx;
   1193 					col -= cx;
   1194 					if (col < 0) {
   1195 						pos += vs.ncol;
   1196 						col += vs.ncol;
   1197 					}
   1198 					vs.col = col;
   1199 					crtat = Crtat + pos;
   1200 					vs.state = 0;
   1201 					break;
   1202 				}
   1203 				case 'J': /* Clear ... */
   1204 					switch (vs.cx) {
   1205 					case 0:
   1206 						/* ... to end of display */
   1207 						fillw((vs.at << 8) | ' ',
   1208 						    crtat,
   1209 						    Crtat + vs.nchr - crtat);
   1210 						break;
   1211 					case 1:
   1212 						/* ... to next location */
   1213 						fillw((vs.at << 8) | ' ',
   1214 						    Crtat,
   1215 						    crtat - Crtat + 1);
   1216 						break;
   1217 					case 2:
   1218 						/* ... whole display */
   1219 						fillw((vs.at << 8) | ' ',
   1220 						    Crtat,
   1221 						    vs.nchr);
   1222 						break;
   1223 					}
   1224 					vs.state = 0;
   1225 					break;
   1226 				case 'K': /* Clear line ... */
   1227 					switch (vs.cx) {
   1228 					case 0:
   1229 						/* ... current to EOL */
   1230 						fillw((vs.at << 8) | ' ',
   1231 						    crtat,
   1232 						    vs.ncol - vs.col);
   1233 						break;
   1234 					case 1:
   1235 						/* ... beginning to next */
   1236 						fillw((vs.at << 8) | ' ',
   1237 						    crtat - vs.col,
   1238 						    vs.col + 1);
   1239 						break;
   1240 					case 2:
   1241 						/* ... entire line */
   1242 						fillw((vs.at << 8) | ' ',
   1243 						    crtat - vs.col, vs.ncol);
   1244 						break;
   1245 					}
   1246 					vs.state = 0;
   1247 					break;
   1248 				case 'f': /* in system V consoles */
   1249 				case 'H': { /* Cursor move */
   1250 					int cx = vs.cx,
   1251 					    cy = vs.cy;
   1252 					if (!cx || !cy) {
   1253 						crtat = Crtat;
   1254 						vs.col = 0;
   1255 					} else {
   1256 						if (cx > vs.nrow)
   1257 							cx = vs.nrow;
   1258 						if (cy > vs.ncol)
   1259 							cy = vs.ncol;
   1260 						crtat = Crtat +
   1261 						    (cx - 1) * vs.ncol + cy - 1;
   1262 						vs.col = cy - 1;
   1263 					}
   1264 					vs.state = 0;
   1265 					break;
   1266 				}
   1267 				case 'M': { /* delete cx rows */
   1268 					u_short *crtAt = crtat - vs.col;
   1269 					int cx = vs.cx,
   1270 					    row = (crtAt - Crtat) / vs.ncol,
   1271 					    nrow = vs.nrow - row;
   1272 					if (cx <= 0)
   1273 						cx = 1;
   1274 					else if (cx > nrow)
   1275 						cx = nrow;
   1276 					if (cx < nrow)
   1277 #ifdef PCCONS_FORCE_WORD
   1278 						wcopy(crtAt + vs.ncol * cx,
   1279 						    crtAt, vs.ncol * (nrow -
   1280 						    cx) * CHR);
   1281 #else
   1282 						memmove(crtAt,
   1283 						    crtAt + vs.ncol * cx,
   1284 						    vs.ncol * (nrow - cx) *
   1285 						    CHR);
   1286 #endif
   1287 					fillw((vs.at << 8) | ' ',
   1288 					    crtAt + vs.ncol * (nrow - cx),
   1289 					    vs.ncol * cx);
   1290 					vs.state = 0;
   1291 					break;
   1292 				}
   1293 				case 'S': { /* scroll up cx lines */
   1294 					int cx = vs.cx;
   1295 					if (cx <= 0)
   1296 						cx = 1;
   1297 					else if (cx > vs.nrow)
   1298 						cx = vs.nrow;
   1299 					if (cx < vs.nrow)
   1300 #ifdef PCCONS_FORCE_WORD
   1301 						wcopy(Crtat + vs.ncol * cx,
   1302 						    Crtat, vs.ncol * (vs.nrow -
   1303 						    cx) * CHR);
   1304 #else
   1305 						memmove(Crtat,
   1306 						    Crtat + vs.ncol * cx,
   1307 						    vs.ncol * (vs.nrow - cx) *
   1308 						    CHR);
   1309 #endif
   1310 					fillw((vs.at << 8) | ' ',
   1311 					    Crtat + vs.ncol * (vs.nrow - cx),
   1312 					    vs.ncol * cx);
   1313 					/* crtat -= vs.ncol * cx; XXX */
   1314 					vs.state = 0;
   1315 					break;
   1316 				}
   1317 				case 'L': { /* insert cx rows */
   1318 					u_short *crtAt = crtat - vs.col;
   1319 					int cx = vs.cx,
   1320 					    row = (crtAt - Crtat) / vs.ncol,
   1321 					    nrow = vs.nrow - row;
   1322 					if (cx <= 0)
   1323 						cx = 1;
   1324 					else if (cx > nrow)
   1325 						cx = nrow;
   1326 					if (cx < nrow)
   1327 #ifdef PCCONS_FORCE_WORD
   1328 						wcopy(crtAt,
   1329 						    crtAt + vs.ncol * cx,
   1330 						    vs.ncol * (nrow - cx) *
   1331 						    CHR);
   1332 #else
   1333 						memmove(crtAt + vs.ncol * cx,
   1334 						    crtAt,
   1335 						    vs.ncol * (nrow - cx) *
   1336 						    CHR);
   1337 #endif
   1338 					fillw((vs.at << 8) | ' ', crtAt,
   1339 					    vs.ncol * cx);
   1340 					vs.state = 0;
   1341 					break;
   1342 				}
   1343 				case 'T': { /* scroll down cx lines */
   1344 					int cx = vs.cx;
   1345 					if (cx <= 0)
   1346 						cx = 1;
   1347 					else if (cx > vs.nrow)
   1348 						cx = vs.nrow;
   1349 					if (cx < vs.nrow)
   1350 #ifdef PCCONS_FORCE_WORD
   1351 						wcopy(Crtat,
   1352 						    Crtat + vs.ncol * cx,
   1353 						    vs.ncol * (vs.nrow - cx) *
   1354 						    CHR);
   1355 #else
   1356 						memmove(Crtat + vs.ncol * cx,
   1357 						    Crtat,
   1358 						    vs.ncol * (vs.nrow - cx) *
   1359 						    CHR);
   1360 #endif
   1361 					fillw((vs.at << 8) | ' ', Crtat,
   1362 					    vs.ncol * cx);
   1363 					/* crtat += vs.ncol * cx; XXX */
   1364 					vs.state = 0;
   1365 					break;
   1366 				}
   1367 				case ';': /* Switch params in cursor def */
   1368 					vs.state = VSS_EPARAM;
   1369 					break;
   1370 				case 'r':
   1371 					vs.so_at = (vs.cx & FG_MASK) |
   1372 					    ((vs.cy << 4) & BG_MASK);
   1373 					vs.state = 0;
   1374 					break;
   1375 				case 's': /* save cursor pos */
   1376 					vs.offset = crtat - Crtat;
   1377 					vs.state = 0;
   1378 					break;
   1379 				case 'u': /* restore cursor pos */
   1380 					crtat = Crtat + vs.offset;
   1381 					vs.row = vs.offset / vs.ncol;
   1382 					vs.col = vs.offset % vs.ncol;
   1383 					vs.state = 0;
   1384 					break;
   1385 				case 'x': /* set attributes */
   1386 					switch (vs.cx) {
   1387 					case 0:
   1388 						vs.at = FG_LIGHTGREY | BG_BLACK;
   1389 						break;
   1390 					case 1:
   1391 						/* ansi background */
   1392 						if (!vs.color)
   1393 							break;
   1394 						vs.at &= FG_MASK;
   1395 						vs.at |= bgansitopc[vs.cy & 7];
   1396 						break;
   1397 					case 2:
   1398 						/* ansi foreground */
   1399 						if (!vs.color)
   1400 							break;
   1401 						vs.at &= BG_MASK;
   1402 						vs.at |= fgansitopc[vs.cy & 7];
   1403 						break;
   1404 					case 3:
   1405 						/* pc text attribute */
   1406 						if (vs.state >= VSS_EPARAM)
   1407 							vs.at = vs.cy;
   1408 						break;
   1409 					}
   1410 					vs.state = 0;
   1411 					break;
   1412 
   1413 				default: /* Only numbers valid here */
   1414 					if ((c >= '0') && (c <= '9')) {
   1415 						if (vs.state >= VSS_EPARAM) {
   1416 							vs.cy *= 10;
   1417 							vs.cy += c - '0';
   1418 						} else {
   1419 							vs.cx *= 10;
   1420 							vs.cx += c - '0';
   1421 						}
   1422 					} else
   1423 						vs.state = 0;
   1424 					break;
   1425 				}
   1426 				break;
   1427 			}
   1428 		}
   1429 		if (scroll) {
   1430 			scroll = 0;
   1431 			/* scroll check */
   1432 			if (crtat >= Crtat + vs.nchr) {
   1433 				if (!kernel) {
   1434 					int s = spltty();
   1435 					if (lock_state & KB_SCROLL)
   1436 						tsleep(&lock_state,
   1437 						    PUSER, "pcputc", 0);
   1438 					splx(s);
   1439 				}
   1440 #if PCCONS_FORCE_WORD
   1441 				wcopy(Crtat + vs.ncol, Crtat,
   1442 				    (vs.nchr - vs.ncol) * CHR);
   1443 #else
   1444 				memmove(Crtat, Crtat + vs.ncol,
   1445 				    (vs.nchr - vs.ncol) * CHR);
   1446 #endif
   1447 				fillw((vs.at << 8) | ' ',
   1448 				    Crtat + vs.nchr - vs.ncol,
   1449 				    vs.ncol);
   1450 				crtat -= vs.ncol;
   1451 			}
   1452 		}
   1453 	}
   1454 	async_update();
   1455 }
   1456 
   1457 /* the unshifted code for KB_SHIFT keys is used by X to distinguish between
   1458    left and right shift when reading the keyboard map */
   1459 static pccons_keymap_t	scan_codes[KB_NUM_KEYS] = {
   1460 /*  type       unshift   shift     control   altgr     shift_altgr scancode */
   1461   { KB_NONE,   "",       "",       "",       "",       ""}, /* 0 unused */
   1462   { KB_ASCII,  "\033",   "\033",   "\033",   "",       ""}, /* 1 ESCape */
   1463   { KB_ASCII,  "1",      "!",      "!",      "",       ""}, /* 2 1 */
   1464   { KB_ASCII,  "2",      "@",      "\000",   "",       ""}, /* 3 2 */
   1465   { KB_ASCII,  "3",      "#",      "#",      "",       ""}, /* 4 3 */
   1466   { KB_ASCII,  "4",      "$",      "$",      "",       ""}, /* 5 4 */
   1467   { KB_ASCII,  "5",      "%",      "%",      "",       ""}, /* 6 5 */
   1468   { KB_ASCII,  "6",      "^",      "\036",   "",       ""}, /* 7 6 */
   1469   { KB_ASCII,  "7",      "&",      "&",      "",       ""}, /* 8 7 */
   1470   { KB_ASCII,  "8",      "*",      "\010",   "",       ""}, /* 9 8 */
   1471   { KB_ASCII,  "9",      "(",      "(",      "",       ""}, /* 10 9 */
   1472   { KB_ASCII,  "0",      ")",      ")",      "",       ""}, /* 11 0 */
   1473   { KB_ASCII,  "-",      "_",      "\037",   "",       ""}, /* 12 - */
   1474   { KB_ASCII,  "=",      "+",      "+",      "",       ""}, /* 13 = */
   1475   { KB_ASCII,  "\177",   "\177",   "\010",   "",       ""}, /* 14 backspace */
   1476   { KB_ASCII,  "\t",     "\t",     "\t",     "",       ""}, /* 15 tab */
   1477   { KB_ASCII,  "q",      "Q",      "\021",   "",       ""}, /* 16 q */
   1478   { KB_ASCII,  "w",      "W",      "\027",   "",       ""}, /* 17 w */
   1479   { KB_ASCII,  "e",      "E",      "\005",   "",       ""}, /* 18 e */
   1480   { KB_ASCII,  "r",      "R",      "\022",   "",       ""}, /* 19 r */
   1481   { KB_ASCII,  "t",      "T",      "\024",   "",       ""}, /* 20 t */
   1482   { KB_ASCII,  "y",      "Y",      "\031",   "",       ""}, /* 21 y */
   1483   { KB_ASCII,  "u",      "U",      "\025",   "",       ""}, /* 22 u */
   1484   { KB_ASCII,  "i",      "I",      "\011",   "",       ""}, /* 23 i */
   1485   { KB_ASCII,  "o",      "O",      "\017",   "",       ""}, /* 24 o */
   1486   { KB_ASCII,  "p",      "P",      "\020",   "",       ""}, /* 25 p */
   1487   { KB_ASCII,  "[",      "{",      "\033",   "",       ""}, /* 26 [ */
   1488   { KB_ASCII,  "]",      "}",      "\035",   "",       ""}, /* 27 ] */
   1489   { KB_ASCII,  "\r",     "\r",     "\n",     "",       ""}, /* 28 return */
   1490   { KB_CTL,    "",       "",       "",       "",       ""}, /* 29 control */
   1491   { KB_ASCII,  "a",      "A",      "\001",   "",       ""}, /* 30 a */
   1492   { KB_ASCII,  "s",      "S",      "\023",   "",       ""}, /* 31 s */
   1493   { KB_ASCII,  "d",      "D",      "\004",   "",       ""}, /* 32 d */
   1494   { KB_ASCII,  "f",      "F",      "\006",   "",       ""}, /* 33 f */
   1495   { KB_ASCII,  "g",      "G",      "\007",   "",       ""}, /* 34 g */
   1496   { KB_ASCII,  "h",      "H",      "\010",   "",       ""}, /* 35 h */
   1497   { KB_ASCII,  "j",      "J",      "\n",     "",       ""}, /* 36 j */
   1498   { KB_ASCII,  "k",      "K",      "\013",   "",       ""}, /* 37 k */
   1499   { KB_ASCII,  "l",      "L",      "\014",   "",       ""}, /* 38 l */
   1500   { KB_ASCII,  ";",      ":",      ";",      "",       ""}, /* 39 ; */
   1501   { KB_ASCII,  "'",      "\"",     "'",      "",       ""}, /* 40 ' */
   1502   { KB_ASCII,  "`",      "~",      "`",      "",       ""}, /* 41 ` */
   1503   { KB_SHIFT,  "\001",   "",       "",       "",       ""}, /* 42 shift */
   1504   { KB_ASCII,  "\\",     "|",      "\034",   "",       ""}, /* 43 \ */
   1505   { KB_ASCII,  "z",      "Z",      "\032",   "",       ""}, /* 44 z */
   1506   { KB_ASCII,  "x",      "X",      "\030",   "",       ""}, /* 45 x */
   1507   { KB_ASCII,  "c",      "C",      "\003",   "",       ""}, /* 46 c */
   1508   { KB_ASCII,  "v",      "V",      "\026",   "",       ""}, /* 47 v */
   1509   { KB_ASCII,  "b",      "B",      "\002",   "",       ""}, /* 48 b */
   1510   { KB_ASCII,  "n",      "N",      "\016",   "",       ""}, /* 49 n */
   1511   { KB_ASCII,  "m",      "M",      "\r",     "",       ""}, /* 50 m */
   1512   { KB_ASCII,  ",",      "<",      "<",      "",       ""}, /* 51 , */
   1513   { KB_ASCII,  ".",      ">",      ">",      "",       ""}, /* 52 . */
   1514   { KB_ASCII,  "/",      "?",      "\037",   "",       ""}, /* 53 / */
   1515   { KB_SHIFT,  "\002",   "",       "",       "",       ""}, /* 54 shift */
   1516   { KB_KP,     "*",      "*",      "*",      "",       ""}, /* 55 kp * */
   1517   { KB_ALT,    "",       "",       "",       "",       ""}, /* 56 alt */
   1518   { KB_ASCII,  " ",      " ",      "\000",   "",       ""}, /* 57 space */
   1519   { KB_CAPS,   "",       "",       "",       "",       ""}, /* 58 caps */
   1520   { KB_FUNC,   "\033[M", "\033[Y", "\033[k", "",       ""}, /* 59 f1 */
   1521   { KB_FUNC,   "\033[N", "\033[Z", "\033[l", "",       ""}, /* 60 f2 */
   1522   { KB_FUNC,   "\033[O", "\033[a", "\033[m", "",       ""}, /* 61 f3 */
   1523   { KB_FUNC,   "\033[P", "\033[b", "\033[n", "",       ""}, /* 62 f4 */
   1524   { KB_FUNC,   "\033[Q", "\033[c", "\033[o", "",       ""}, /* 63 f5 */
   1525   { KB_FUNC,   "\033[R", "\033[d", "\033[p", "",       ""}, /* 64 f6 */
   1526   { KB_FUNC,   "\033[S", "\033[e", "\033[q", "",       ""}, /* 65 f7 */
   1527   { KB_FUNC,   "\033[T", "\033[f", "\033[r", "",       ""}, /* 66 f8 */
   1528   { KB_FUNC,   "\033[U", "\033[g", "\033[s", "",       ""}, /* 67 f9 */
   1529   { KB_FUNC,   "\033[V", "\033[h", "\033[t", "",       ""}, /* 68 f10 */
   1530   { KB_NUM,    "",       "",       "",       "",       ""}, /* 69 num lock */
   1531   { KB_SCROLL, "",       "",       "",       "",       ""}, /* 70 scroll lock */
   1532   { KB_KP,     "7",      "\033[H", "7",      "",       ""}, /* 71 kp 7 */
   1533   { KB_KP,     "8",      "\033[A", "8",      "",       ""}, /* 72 kp 8 */
   1534   { KB_KP,     "9",      "\033[I", "9",      "",       ""}, /* 73 kp 9 */
   1535   { KB_KP,     "-",      "-",      "-",      "",       ""}, /* 74 kp - */
   1536   { KB_KP,     "4",      "\033[D", "4",      "",       ""}, /* 75 kp 4 */
   1537   { KB_KP,     "5",      "\033[E", "5",      "",       ""}, /* 76 kp 5 */
   1538   { KB_KP,     "6",      "\033[C", "6",      "",       ""}, /* 77 kp 6 */
   1539   { KB_KP,     "+",      "+",      "+",      "",       ""}, /* 78 kp + */
   1540   { KB_KP,     "1",      "\033[F", "1",      "",       ""}, /* 79 kp 1 */
   1541   { KB_KP,     "2",      "\033[B", "2",      "",       ""}, /* 80 kp 2 */
   1542   { KB_KP,     "3",      "\033[G", "3",      "",       ""}, /* 81 kp 3 */
   1543   { KB_KP,     "0",      "\033[L", "0",      "",       ""}, /* 82 kp 0 */
   1544   { KB_KP,     ",",      "\177",   ",",      "",       ""}, /* 83 kp , */
   1545   { KB_NONE,   "",       "",       "",       "",       ""}, /* 84 0 */
   1546   { KB_NONE,   "",       "",       "",       "",       ""}, /* 85 0 */
   1547   { KB_NONE,   "",       "",       "",       "",       ""}, /* 86 0 */
   1548   { KB_FUNC,   "\033[W", "\033[i", "\033[u", "",       ""}, /* 87 f11 */
   1549   { KB_FUNC,   "\033[X", "\033[j", "\033[v", "",       ""}, /* 88 f12 */
   1550   { KB_NONE,   "",       "",       "",       "",       ""}, /* 89 0 */
   1551   { KB_NONE,   "",       "",       "",       "",       ""}, /* 90 0 */
   1552   { KB_NONE,   "",       "",       "",       "",       ""}, /* 91 0 */
   1553   { KB_NONE,   "",       "",       "",       "",       ""}, /* 92 0 */
   1554   { KB_NONE,   "",       "",       "",       "",       ""}, /* 93 0 */
   1555   { KB_NONE,   "",       "",       "",       "",       ""}, /* 94 0 */
   1556   { KB_NONE,   "",       "",       "",       "",       ""}, /* 95 0 */
   1557   { KB_NONE,   "",       "",       "",       "",       ""}, /* 96 0 */
   1558   { KB_NONE,   "",       "",       "",       "",       ""}, /* 97 0 */
   1559   { KB_NONE,   "",       "",       "",       "",       ""}, /* 98 0 */
   1560   { KB_NONE,   "",       "",       "",       "",       ""}, /* 99 0 */
   1561   { KB_NONE,   "",       "",       "",       "",       ""}, /* 100 */
   1562   { KB_NONE,   "",       "",       "",       "",       ""}, /* 101 */
   1563   { KB_NONE,   "",       "",       "",       "",       ""}, /* 102 */
   1564   { KB_NONE,   "",       "",       "",       "",       ""}, /* 103 */
   1565   { KB_NONE,   "",       "",       "",       "",       ""}, /* 104 */
   1566   { KB_NONE,   "",       "",       "",       "",       ""}, /* 105 */
   1567   { KB_NONE,   "",       "",       "",       "",       ""}, /* 106 */
   1568   { KB_NONE,   "",       "",       "",       "",       ""}, /* 107 */
   1569   { KB_NONE,   "",       "",       "",       "",       ""}, /* 108 */
   1570   { KB_NONE,   "",       "",       "",       "",       ""}, /* 109 */
   1571   { KB_NONE,   "",       "",       "",       "",       ""}, /* 110 */
   1572   { KB_NONE,   "",       "",       "",       "",       ""}, /* 111 */
   1573   { KB_NONE,   "",       "",       "",       "",       ""}, /* 112 */
   1574   { KB_NONE,   "",       "",       "",       "",       ""}, /* 113 */
   1575   { KB_NONE,   "",       "",       "",       "",       ""}, /* 114 */
   1576   { KB_NONE,   "",       "",       "",       "",       ""}, /* 115 */
   1577   { KB_NONE,   "",       "",       "",       "",       ""}, /* 116 */
   1578   { KB_NONE,   "",       "",       "",       "",       ""}, /* 117 */
   1579   { KB_NONE,   "",       "",       "",       "",       ""}, /* 118 */
   1580   { KB_NONE,   "",       "",       "",       "",       ""}, /* 119 */
   1581   { KB_NONE,   "",       "",       "",       "",       ""}, /* 120 */
   1582   { KB_NONE,   "",       "",       "",       "",       ""}, /* 121 */
   1583   { KB_NONE,   "",       "",       "",       "",       ""}, /* 122 */
   1584   { KB_NONE,   "",       "",       "",       "",       ""}, /* 123 */
   1585   { KB_NONE,   "",       "",       "",       "",       ""}, /* 124 */
   1586   { KB_NONE,   "",       "",       "",       "",       ""}, /* 125 */
   1587   { KB_NONE,   "",       "",       "",       "",       ""}, /* 126 */
   1588   { KB_NONE,   "",       "",       "",       "",       ""}  /* 127 */
   1589 };
   1590 
   1591 /*
   1592  * Get characters from the keyboard.  If none are present, return NULL.
   1593  */
   1594 char *
   1595 sget(void)
   1596 {
   1597 	u_char dt;
   1598 	static u_char extended = 0, shift_state = 0;
   1599 	static u_char capchar[2];
   1600 
   1601 top:
   1602 	KBD_DELAY;
   1603 	dt = kbd_data_read_1();
   1604 
   1605 	switch (dt) {
   1606 	case KBR_ACK: case KBR_ECHO:
   1607 		kb_oq_get = (kb_oq_get + 1) & 7;
   1608 		if(kb_oq_get != kb_oq_put) {
   1609 			kbd_data_write_1(kb_oq[kb_oq_get]);
   1610 		}
   1611 		goto loop;
   1612 	case KBR_RESEND:
   1613 		kbd_data_write_1(kb_oq[kb_oq_get]);
   1614 		goto loop;
   1615 	}
   1616 
   1617 	if (pc_xmode > 0) {
   1618 #if defined(DDB) && defined(XSERVER_DDB)
   1619 		/* F12 enters the debugger while in X mode */
   1620 		if (dt == 88)
   1621 			Debugger();
   1622 #endif
   1623 		capchar[0] = dt;
   1624 		capchar[1] = 0;
   1625 		/*
   1626 		 * Check for locking keys.
   1627 		 *
   1628 		 * XXX Setting the LEDs this way is a bit bogus.  What if the
   1629 		 * keyboard has been remapped in X?
   1630 		 */
   1631 		switch (scan_codes[dt & 0x7f].type) {
   1632 		case KB_NUM:
   1633 			if (dt & 0x80) {
   1634 				shift_state &= ~KB_NUM;
   1635 				break;
   1636 			}
   1637 			if (shift_state & KB_NUM)
   1638 				break;
   1639 			shift_state |= KB_NUM;
   1640 			lock_state ^= KB_NUM;
   1641 			async_update();
   1642 			break;
   1643 		case KB_CAPS:
   1644 			if (dt & 0x80) {
   1645 				shift_state &= ~KB_CAPS;
   1646 				break;
   1647 			}
   1648 			if (shift_state & KB_CAPS)
   1649 				break;
   1650 			shift_state |= KB_CAPS;
   1651 			lock_state ^= KB_CAPS;
   1652 			async_update();
   1653 			break;
   1654 		case KB_SCROLL:
   1655 			if (dt & 0x80) {
   1656 				shift_state &= ~KB_SCROLL;
   1657 				break;
   1658 			}
   1659 			if (shift_state & KB_SCROLL)
   1660 				break;
   1661 			shift_state |= KB_SCROLL;
   1662 			lock_state ^= KB_SCROLL;
   1663 			if ((lock_state & KB_SCROLL) == 0)
   1664 				wakeup((void *)&lock_state);
   1665 			async_update();
   1666 			break;
   1667 		}
   1668 		return capchar;
   1669 	}
   1670 
   1671 	switch (dt) {
   1672 	case KBR_EXTENDED:
   1673 		extended = 1;
   1674 		goto loop;
   1675 	}
   1676 
   1677 #ifdef DDB
   1678 	/*
   1679 	 * Check for cntl-alt-esc.
   1680 	 */
   1681 	if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
   1682 		/* XXX - check pccons_is_console */
   1683 		Debugger();
   1684 		dt |= 0x80;	/* discard esc (ddb discarded ctl-alt) */
   1685 	}
   1686 #endif
   1687 
   1688 	/*
   1689 	 * Check for make/break.
   1690 	 */
   1691 	if (dt & 0x80) {
   1692 		/*
   1693 		 * break
   1694 		 */
   1695 		dt &= 0x7f;
   1696 		switch (scan_codes[dt].type) {
   1697 		case KB_NUM:
   1698 			shift_state &= ~KB_NUM;
   1699 			break;
   1700 		case KB_CAPS:
   1701 			shift_state &= ~KB_CAPS;
   1702 			break;
   1703 		case KB_SCROLL:
   1704 			shift_state &= ~KB_SCROLL;
   1705 			break;
   1706 		case KB_SHIFT:
   1707 			shift_state &= ~KB_SHIFT;
   1708 			break;
   1709 		case KB_ALT:
   1710 			if (extended)
   1711 				shift_state &= ~KB_ALTGR;
   1712 			else
   1713 				shift_state &= ~KB_ALT;
   1714 			break;
   1715 		case KB_CTL:
   1716 			shift_state &= ~KB_CTL;
   1717 			break;
   1718 		}
   1719 	} else {
   1720 		/*
   1721 		 * make
   1722 		 */
   1723 		switch (scan_codes[dt].type) {
   1724 		/*
   1725 		 * locking keys
   1726 		 */
   1727 		case KB_NUM:
   1728 			if (shift_state & KB_NUM)
   1729 				break;
   1730 			shift_state |= KB_NUM;
   1731 			lock_state ^= KB_NUM;
   1732 			async_update();
   1733 			break;
   1734 		case KB_CAPS:
   1735 			if (shift_state & KB_CAPS)
   1736 				break;
   1737 			shift_state |= KB_CAPS;
   1738 			lock_state ^= KB_CAPS;
   1739 			async_update();
   1740 			break;
   1741 		case KB_SCROLL:
   1742 			if (shift_state & KB_SCROLL)
   1743 				break;
   1744 			shift_state |= KB_SCROLL;
   1745 			lock_state ^= KB_SCROLL;
   1746 			if ((lock_state & KB_SCROLL) == 0)
   1747 				wakeup((void *)&lock_state);
   1748 			async_update();
   1749 			break;
   1750 		/*
   1751 		 * non-locking keys
   1752 		 */
   1753 		case KB_SHIFT:
   1754 			shift_state |= KB_SHIFT;
   1755 			break;
   1756 		case KB_ALT:
   1757 			if (extended)
   1758 				shift_state |= KB_ALTGR;
   1759 			else
   1760 				shift_state |= KB_ALT;
   1761 			break;
   1762 		case KB_CTL:
   1763 			shift_state |= KB_CTL;
   1764 			break;
   1765 		case KB_ASCII:
   1766 			/* control has highest priority */
   1767 			if (shift_state & KB_CTL)
   1768 				capchar[0] = scan_codes[dt].ctl[0];
   1769 			else if (shift_state & KB_ALTGR) {
   1770 				if (shift_state & KB_SHIFT)
   1771 					capchar[0] = scan_codes[dt].shift_altgr[0];
   1772 				else
   1773 					capchar[0] = scan_codes[dt].altgr[0];
   1774 			}
   1775 			else {
   1776 				if (shift_state & KB_SHIFT)
   1777 					capchar[0] = scan_codes[dt].shift[0];
   1778 				else
   1779 					capchar[0] = scan_codes[dt].unshift[0];
   1780 			}
   1781 			if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
   1782 			    capchar[0] <= 'z') {
   1783 				capchar[0] -= ('a' - 'A');
   1784 			}
   1785 			capchar[0] |= (shift_state & KB_ALT);
   1786 			extended = 0;
   1787 			return capchar;
   1788 		case KB_NONE:
   1789 printf("keycode %d\n",dt);
   1790 			break;
   1791 		case KB_FUNC: {
   1792 			char *more_chars;
   1793 			if (shift_state & KB_SHIFT)
   1794 				more_chars = scan_codes[dt].shift;
   1795 			else if (shift_state & KB_CTL)
   1796 				more_chars = scan_codes[dt].ctl;
   1797 			else
   1798 				more_chars = scan_codes[dt].unshift;
   1799 			extended = 0;
   1800 			return more_chars;
   1801 		}
   1802 		case KB_KP: {
   1803 			char *more_chars;
   1804 			if (shift_state & (KB_SHIFT | KB_CTL) ||
   1805 			    (lock_state & KB_NUM) == 0 || extended)
   1806 				more_chars = scan_codes[dt].shift;
   1807 			else
   1808 				more_chars = scan_codes[dt].unshift;
   1809 			extended = 0;
   1810 			return more_chars;
   1811 		}
   1812 		}
   1813 	}
   1814 
   1815 	extended = 0;
   1816 loop:
   1817 	if ((kbd_cmd_read_1() & KBS_DIB) == 0)
   1818 		return 0;
   1819 	goto top;
   1820 }
   1821 
   1822 paddr_t
   1823 pcmmap(dev_t dev, off_t offset, int nprot)
   1824 {
   1825 	struct pccons_context *pc = &pccons_console_context;
   1826 	paddr_t pa;
   1827 
   1828 	if (offset >= 0xa0000 && offset < 0xc0000) {
   1829 		if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
   1830 			return -1;
   1831 		pa += offset - pc->pc_config->pc_mono_memaddr;
   1832 		return mips_btop(pa);
   1833 	}
   1834 	if (offset >= 0x0000 && offset < 0x10000) {
   1835 		if (bus_space_paddr(pc->pc_crt_iot, pc->pc_mono_ioh, &pa))
   1836 			return -1;
   1837 		pa += offset - pc->pc_config->pc_mono_iobase;
   1838 		return mips_btop(pa);
   1839 	}
   1840 	if (offset >= 0x40000000 && offset < 0x40800000) {
   1841 		if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
   1842 			return (-1);
   1843 		pa += offset - 0x40000000 - pc->pc_config->pc_mono_memaddr;
   1844 		return mips_btop(pa);
   1845 	}
   1846 	return -1;
   1847 }
   1848 
   1849 void
   1850 pc_xmode_on(void)
   1851 {
   1852 	if (pc_xmode)
   1853 		return;
   1854 	pc_xmode = 1;
   1855 
   1856 #ifdef XFREE86_BUG_COMPAT
   1857 	/* If still unchanged, get current shape. */
   1858 	if (cursor_shape == 0xffff)
   1859 		get_cursor_shape();
   1860 #endif
   1861 }
   1862 
   1863 void
   1864 pc_xmode_off(void)
   1865 {
   1866 	if (pc_xmode == 0)
   1867 		return;
   1868 	pc_xmode = 0;
   1869 
   1870 #ifdef XFREE86_BUG_COMPAT
   1871 	/* XXX It would be hard to justify why the X server doesn't do this. */
   1872 	set_cursor_shape();
   1873 #endif
   1874 	async_update();
   1875 }
   1876