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