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