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