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