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