Home | History | Annotate | Line # | Download | only in dev
pccons.c revision 1.49
      1 /*	$NetBSD: pccons.c,v 1.49 2007/03/04 05:59:34 christos Exp $	*/
      2 /*	$OpenBSD: pccons.c,v 1.22 1999/01/30 22:39:37 imp Exp $	*/
      3 /*	NetBSD: pccons.c,v 1.89 1995/05/04 19:35:20 cgd Exp	*/
      4 
      5 /*-
      6  * Copyright (c) 1990 The Regents of the University of California.
      7  * All rights reserved.
      8  *
      9  * This code is derived from software contributed to Berkeley by
     10  * William Jolitz and Don Ahn.
     11  *
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  *	@(#)pccons.c	5.11 (Berkeley) 5/21/91
     36  */
     37 
     38 /*-
     39  * Copyright (c) 1993, 1994, 1995 Charles M. Hannum.  All rights reserved.
     40  *
     41  * This code is derived from software contributed to Berkeley by
     42  * William Jolitz and Don Ahn.
     43  *
     44  * Copyright (c) 1994 Charles M. Hannum.
     45  * Copyright (c) 1992, 1993 Erik Forsberg.
     46  *
     47  * Redistribution and use in source and binary forms, with or without
     48  * modification, are permitted provided that the following conditions
     49  * are met:
     50  * 1. Redistributions of source code must retain the above copyright
     51  *    notice, this list of conditions and the following disclaimer.
     52  * 2. Redistributions in binary form must reproduce the above copyright
     53  *    notice, this list of conditions and the following disclaimer in the
     54  *    documentation and/or other materials provided with the distribution.
     55  * 3. All advertising materials mentioning features or use of this software
     56  *    must display the following acknowledgement:
     57  *	This product includes software developed by the University of
     58  *	California, Berkeley and its contributors.
     59  * 4. Neither the name of the University nor the names of its contributors
     60  *    may be used to endorse or promote products derived from this software
     61  *    without specific prior written permission.
     62  *
     63  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     66  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     73  * SUCH DAMAGE.
     74  *
     75  *	@(#)pccons.c	5.11 (Berkeley) 5/21/91
     76  */
     77 
     78 /*
     79  * code to work keyboard & display for PC-style console
     80  */
     81 
     82 #include <sys/cdefs.h>
     83 __KERNEL_RCSID(0, "$NetBSD: pccons.c,v 1.49 2007/03/04 05:59:34 christos Exp $");
     84 
     85 #include "opt_ddb.h"
     86 
     87 #include <sys/param.h>
     88 #include <sys/systm.h>
     89 #include <sys/tty.h>
     90 #include <sys/callout.h>
     91 #include <sys/poll.h>
     92 #include <sys/conf.h>
     93 #include <sys/vnode.h>
     94 #include <sys/kernel.h>
     95 #include <sys/kcore.h>
     96 #include <sys/device.h>
     97 #include <sys/proc.h>
     98 #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 
    616 	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
    617 		return (EBUSY);
    618 
    619 	if ((tp->t_state & TS_ISOPEN) == 0) {
    620 		ttychars(tp);
    621 		tp->t_iflag = TTYDEF_IFLAG;
    622 		tp->t_oflag = TTYDEF_OFLAG;
    623 		tp->t_cflag = TTYDEF_CFLAG;
    624 		tp->t_lflag = TTYDEF_LFLAG;
    625 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
    626 		pcparam(tp, &tp->t_termios);
    627 		ttsetwater(tp);
    628 	}
    629 
    630 	tp->t_state |= TS_CARR_ON;
    631 
    632 	return (*tp->t_linesw->l_open)(dev, tp);
    633 }
    634 
    635 int
    636 pcclose(dev_t dev, int flag, int mode, struct lwp *l)
    637 {
    638 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    639 	struct tty *tp = sc->sc_tty;
    640 
    641 	(*tp->t_linesw->l_close)(tp, flag);
    642 	ttyclose(tp);
    643 #ifdef notyet /* XXX */
    644 	ttyfree(tp);
    645 #endif
    646 	return 0;
    647 }
    648 
    649 int
    650 pcread(dev_t dev, struct uio *uio, int flag)
    651 {
    652 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    653 	struct tty *tp = sc->sc_tty;
    654 
    655 	return (*tp->t_linesw->l_read)(tp, uio, flag);
    656 }
    657 
    658 int
    659 pcwrite(dev_t dev, struct uio *uio, int flag)
    660 {
    661 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    662 	struct tty *tp = sc->sc_tty;
    663 
    664 	return (*tp->t_linesw->l_write)(tp, uio, flag);
    665 }
    666 
    667 int
    668 pcpoll(dev_t dev, int events, struct lwp *l)
    669 {
    670 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    671 	struct tty *tp = sc->sc_tty;
    672 
    673 	return (*tp->t_linesw->l_poll)(tp, events, l);
    674 }
    675 
    676 struct tty *
    677 pctty(dev_t dev)
    678 {
    679 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    680 	struct tty *tp = sc->sc_tty;
    681 
    682 	return tp;
    683 }
    684 
    685 /*
    686  * Got a console receive interrupt -
    687  * the console processor wants to give us a character.
    688  * Catch the character, and see who it goes to.
    689  */
    690 int
    691 pcintr(void *arg)
    692 {
    693 	struct pc_softc *sc = arg;
    694 	struct tty *tp = sc->sc_tty;
    695 	uint8_t *cp;
    696 
    697 	if ((kbd_cmd_read_1() & KBS_DIB) == 0)
    698 		return 0;
    699 	if (polling)
    700 		return 1;
    701 	do {
    702 		cp = sget();
    703 		if (!tp || (tp->t_state & TS_ISOPEN) == 0)
    704 			return 1;
    705 		if (cp)
    706 			do
    707 				(*tp->t_linesw->l_rint)(*cp++, tp);
    708 			while (*cp);
    709 	} while (kbd_cmd_read_1() & KBS_DIB);
    710 	return 1;
    711 }
    712 
    713 int
    714 pcioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
    715 {
    716 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    717 	struct tty *tp = sc->sc_tty;
    718 	int error;
    719 
    720 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
    721 	if (error != EPASSTHROUGH)
    722 		return error;
    723 	error = ttioctl(tp, cmd, data, flag, l);
    724 	if (error != EPASSTHROUGH)
    725 		return error;
    726 
    727 	switch (cmd) {
    728 	case CONSOLE_X_MODE_ON:
    729 		pc_xmode_on();
    730 		return 0;
    731 	case CONSOLE_X_MODE_OFF:
    732 		pc_xmode_off();
    733 		return 0;
    734 	case CONSOLE_X_BELL:
    735 		/*
    736 		 * If set, data is a pointer to a length 2 array of
    737 		 * integers.  data[0] is the pitch in Hz and data[1]
    738 		 * is the duration in msec.
    739 		 */
    740 		if (data)
    741 			sysbeep(((int*)data)[0],
    742 				(((int*)data)[1] * hz) / 1000);
    743 		else
    744 			sysbeep(BEEP_FREQ, BEEP_TIME);
    745 		return 0;
    746 	case CONSOLE_SET_TYPEMATIC_RATE: {
    747  		u_char	rate;
    748 
    749  		if (!data)
    750 			return EINVAL;
    751 		rate = *((u_char *)data);
    752 		/*
    753 		 * Check that it isn't too big (which would cause it to be
    754 		 * confused with a command).
    755 		 */
    756 		if (rate & 0x80)
    757 			return EINVAL;
    758 		typematic_rate = rate;
    759 		async_update();
    760 		return 0;
    761  	}
    762 	case CONSOLE_SET_KEYMAP: {
    763 		pccons_keymap_t *map = (pccons_keymap_t *) data;
    764 		int i;
    765 
    766 		if (!data)
    767 			return EINVAL;
    768 		for (i = 0; i < KB_NUM_KEYS; i++)
    769 			if (map[i].unshift[KB_CODE_SIZE-1] ||
    770 			    map[i].shift[KB_CODE_SIZE-1] ||
    771 			    map[i].ctl[KB_CODE_SIZE-1] ||
    772 			    map[i].altgr[KB_CODE_SIZE-1] ||
    773 			    map[i].shift_altgr[KB_CODE_SIZE-1])
    774 				return EINVAL;
    775 
    776 		bcopy(data, scan_codes, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
    777 		return 0;
    778 	}
    779 	case CONSOLE_GET_KEYMAP:
    780 		if (!data)
    781 			return EINVAL;
    782 		bcopy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
    783 		return 0;
    784 
    785 	default:
    786 		return EPASSTHROUGH;
    787 	}
    788 
    789 #ifdef DIAGNOSTIC
    790 	panic("pcioctl: impossible");
    791 #endif
    792 }
    793 
    794 void
    795 pcstart(struct tty *tp)
    796 {
    797 	struct clist *cl;
    798 	int s, len;
    799 	u_char buf[PCBURST];
    800 
    801 	s = spltty();
    802 	if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
    803 		goto out;
    804 	tp->t_state |= TS_BUSY;
    805 	splx(s);
    806 	/*
    807 	 * We need to do this outside spl since it could be fairly
    808 	 * expensive and we don't want our serial ports to overflow.
    809 	 */
    810 	cl = &tp->t_outq;
    811 	len = q_to_b(cl, buf, PCBURST);
    812 	sput(buf, len);
    813 	s = spltty();
    814 	tp->t_state &= ~TS_BUSY;
    815 	if (cl->c_cc) {
    816 		tp->t_state |= TS_TIMEOUT;
    817 		callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp);
    818 	}
    819 	if (cl->c_cc <= tp->t_lowat) {
    820 		if (tp->t_state & TS_ASLEEP) {
    821 			tp->t_state &= ~TS_ASLEEP;
    822 			wakeup(cl);
    823 		}
    824 		selwakeup(&tp->t_wsel);
    825 	}
    826 out:
    827 	splx(s);
    828 }
    829 
    830 /* ARGSUSED */
    831 void pccons_common_cnattach(bus_space_tag_t crt_iot, bus_space_tag_t crt_memt,
    832     bus_space_tag_t kbd_iot, struct pccons_config *config)
    833 {
    834 	int maj;
    835 	static struct consdev pccons = {
    836 		NULL, NULL, pccngetc, pccnputc, pccnpollc, NULL, NULL,
    837 		    NULL, NODEV, CN_NORMAL
    838 	};
    839 
    840 	/*
    841 	 * For now, don't screw with it.
    842 	 */
    843 	/* crtat = 0; */
    844 
    845 	pc_context_init(crt_iot, crt_memt, kbd_iot, config);
    846 
    847 	/* locate the major number */
    848 	maj = cdevsw_lookup_major(&pc_cdevsw);
    849 	pccons.cn_dev = makedev(maj, 0);
    850 
    851 	cn_tab = &pccons;
    852 }
    853 
    854 /* ARGSUSED */
    855 void
    856 pccnputc(dev_t dev, int c)
    857 {
    858 	u_char cc, oldkernel = kernel;
    859 
    860 	kernel = 1;
    861 	if (c == '\n') {
    862 		sput("\r\n", 2);
    863 	} else {
    864 		cc = c;
    865 		sput(&cc, 1);
    866 	}
    867 	kernel = oldkernel;
    868 }
    869 
    870 /* ARGSUSED */
    871 int
    872 pccngetc(dev_t dev)
    873 {
    874 	char *cp;
    875 
    876 	if (pc_xmode > 0)
    877 		return 0;
    878 
    879 	do {
    880 		/* wait for byte */
    881 		while ((kbd_cmd_read_1() & KBS_DIB) == 0);
    882 		/* see if it's worthwhile */
    883 		cp = sget();
    884 	} while (!cp);
    885 	if (*cp == '\r')
    886 		return '\n';
    887 	return *cp;
    888 }
    889 
    890 void
    891 pccnpollc(dev_t dev, int on)
    892 {
    893 
    894 	polling = on;
    895 	if (!on) {
    896 		int unit;
    897 		struct pc_softc *sc;
    898 		int s;
    899 
    900 		/*
    901 		 * If disabling polling on a device that's been configured,
    902 		 * make sure there are no bytes left in the FIFO, holding up
    903 		 * the interrupt line.  Otherwise we won't get any further
    904 		 * interrupts.
    905 		 */
    906 		unit = PCUNIT(dev);
    907 		if (pc_cd.cd_ndevs > unit) {
    908 			sc = pc_cd.cd_devs[unit];
    909 			if (sc != 0) {
    910 				s = spltty();
    911 				pcintr(sc);
    912 				splx(s);
    913 			}
    914 		}
    915 	}
    916 }
    917 
    918 /*
    919  * Set line parameters.
    920  */
    921 int
    922 pcparam(struct tty *tp, struct termios *t)
    923 {
    924 
    925 	tp->t_ispeed = t->c_ispeed;
    926 	tp->t_ospeed = t->c_ospeed;
    927 	tp->t_cflag = t->c_cflag;
    928 	return 0;
    929 }
    930 
    931 #define	wrtchar(c, at) do {\
    932 	char *cp0 = (char *)crtat; *cp0++ = (c); *cp0 = (at); crtat++; vs.col++; \
    933 } while (0)
    934 
    935 /* translate ANSI color codes to standard pc ones */
    936 static char fgansitopc[] = {
    937 	FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
    938 	FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
    939 };
    940 
    941 static char bgansitopc[] = {
    942 	BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
    943 	BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
    944 };
    945 
    946 static u_char iso2ibm437[] =
    947 {
    948             0,     0,     0,     0,     0,     0,     0,     0,
    949             0,     0,     0,     0,     0,     0,     0,     0,
    950             0,     0,     0,     0,     0,     0,     0,     0,
    951             0,     0,     0,     0,     0,     0,     0,     0,
    952          0xff,  0xad,  0x9b,  0x9c,     0,  0x9d,     0,  0x40,
    953          0x6f,  0x63,  0x61,  0xae,     0,     0,     0,     0,
    954          0xf8,  0xf1,  0xfd,  0x33,     0,  0xe6,     0,  0xfa,
    955             0,  0x31,  0x6f,  0xaf,  0xac,  0xab,     0,  0xa8,
    956          0x41,  0x41,  0x41,  0x41,  0x8e,  0x8f,  0x92,  0x80,
    957          0x45,  0x90,  0x45,  0x45,  0x49,  0x49,  0x49,  0x49,
    958          0x81,  0xa5,  0x4f,  0x4f,  0x4f,  0x4f,  0x99,  0x4f,
    959          0x4f,  0x55,  0x55,  0x55,  0x9a,  0x59,     0,  0xe1,
    960          0x85,  0xa0,  0x83,  0x61,  0x84,  0x86,  0x91,  0x87,
    961          0x8a,  0x82,  0x88,  0x89,  0x8d,  0xa1,  0x8c,  0x8b,
    962             0,  0xa4,  0x95,  0xa2,  0x93,  0x6f,  0x94,  0x6f,
    963          0x6f,  0x97,  0xa3,  0x96,  0x81,  0x98,     0,     0
    964 };
    965 
    966 /*
    967  * `pc3' termcap emulation.
    968  */
    969 void
    970 sput(const u_char *cp, int n)
    971 {
    972 	struct pccons_context *pc = &pccons_console_context;
    973 	u_char c, scroll = 0;
    974 
    975 	if (pc_xmode > 0)
    976 		return;
    977 
    978 	if (crtat == 0) {
    979 		volatile u_short *dp;
    980 		u_short was;
    981 		unsigned cursorat;
    982 
    983 		dp = bus_space_vaddr(pc->pc_crt_memt, pc->pc_cga_memh);
    984 		was = *dp;
    985 		*dp = 0xA55A;
    986 		if (*dp != 0xA55A) {
    987 			dp = bus_space_vaddr(pc->pc_crt_memt,
    988 			    pc->pc_mono_memh);
    989 			pc->pc_6845_ioh = pc->pc_mono_ioh;
    990 			pc->pc_crt_memh = pc->pc_mono_memh;
    991 			vs.color = 0;
    992 		} else {
    993 			*dp = was;
    994 			pc->pc_6845_ioh = pc->pc_cga_ioh;
    995 			pc->pc_crt_memh = pc->pc_cga_memh;
    996 			vs.color = 1;
    997 		}
    998 
    999 #ifdef FAT_CURSOR
   1000 		cursor_shape = 0x0012;
   1001 #else
   1002 		get_cursor_shape();
   1003 #endif
   1004 
   1005 		bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow);
   1006 		vs.nchr = vs.ncol * vs.nrow;
   1007 		vs.col--;
   1008 		vs.row--;
   1009 		cursorat = vs.ncol * vs.row + vs.col;
   1010 		vs.at = FG_LIGHTGREY | BG_BLACK;
   1011 
   1012 		Crtat = (u_short *)__UNVOLATILE(dp);
   1013 		crtat = Crtat + cursorat;
   1014 
   1015 		if (vs.color == 0)
   1016 			vs.so_at = FG_BLACK | BG_LIGHTGREY;
   1017 		else
   1018 			vs.so_at = FG_YELLOW | BG_BLACK;
   1019 
   1020 		fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
   1021 	}
   1022 
   1023 	while (n--) {
   1024 		if (!(c = *cp++))
   1025 			continue;
   1026 
   1027 		switch (c) {
   1028 		case 0x1B:
   1029 			if (vs.state >= VSS_ESCAPE) {
   1030 				wrtchar(c, vs.so_at);
   1031 				vs.state = 0;
   1032 				goto maybe_scroll;
   1033 			} else
   1034 				vs.state = VSS_ESCAPE;
   1035 			break;
   1036 
   1037 		case 0x9B:	/* CSI */
   1038 			vs.cx = vs.cy = 0;
   1039 			vs.state = VSS_EBRACE;
   1040 			break;
   1041 
   1042 		case '\t': {
   1043 			int inccol = 8 - (vs.col & 7);
   1044 			crtat += inccol;
   1045 			vs.col += inccol;
   1046 		}
   1047 		maybe_scroll:
   1048 			if (vs.col >= vs.ncol) {
   1049 				vs.col -= vs.ncol;
   1050 				scroll = 1;
   1051 			}
   1052 			break;
   1053 
   1054 		case '\b':
   1055 			if (crtat <= Crtat)
   1056 				break;
   1057 			--crtat;
   1058 			if (--vs.col < 0)
   1059 				vs.col += vs.ncol;	/* non-destructive backspace */
   1060 			break;
   1061 
   1062 		case '\r':
   1063 			crtat -= vs.col;
   1064 			vs.col = 0;
   1065 			break;
   1066 
   1067 		case '\n':
   1068 			crtat += vs.ncol;
   1069 			scroll = 1;
   1070 			break;
   1071 
   1072 		default:
   1073 			switch (vs.state) {
   1074 			case 0:
   1075 				if (c == '\a')
   1076 					sysbeep(BEEP_FREQ, BEEP_TIME);
   1077 				else {
   1078 					/*
   1079 					 * If we're outputting multiple printed
   1080 					 * characters, just blast them to the
   1081 					 * screen until we reach the end of the
   1082 					 * buffer or a control character.  This
   1083 					 * saves time by short-circuiting the
   1084 					 * switch.
   1085 					 * If we reach the end of the line, we
   1086 					 * break to do a scroll check.
   1087 					 */
   1088 					for (;;) {
   1089 						if (c & 0x80)
   1090 							c = iso2ibm437[c&0x7f];
   1091 
   1092 						if (vs.so)
   1093 							wrtchar(c, vs.so_at);
   1094 						else
   1095 							wrtchar(c, vs.at);
   1096 						if (vs.col >= vs.ncol) {
   1097 							vs.col = 0;
   1098 							scroll = 1;
   1099 							break;
   1100 						}
   1101 						if (!n || (c = *cp) < ' ')
   1102 							break;
   1103 						n--, cp++;
   1104 					}
   1105 				}
   1106 				break;
   1107 			case VSS_ESCAPE:
   1108 				switch (c) {
   1109 					case '[': /* Start ESC [ sequence */
   1110 						vs.cx = vs.cy = 0;
   1111 						vs.state = VSS_EBRACE;
   1112 						break;
   1113 					case 'c': /* Create screen & home */
   1114 						fillw((vs.at << 8) | ' ',
   1115 						    Crtat, vs.nchr);
   1116 						crtat = Crtat;
   1117 						vs.col = 0;
   1118 						vs.state = 0;
   1119 						break;
   1120 					case '7': /* save cursor pos */
   1121 						vs.offset = crtat - Crtat;
   1122 						vs.state = 0;
   1123 						break;
   1124 					case '8': /* restore cursor pos */
   1125 						crtat = Crtat + vs.offset;
   1126 						vs.row = vs.offset / vs.ncol;
   1127 						vs.col = vs.offset % vs.ncol;
   1128 						vs.state = 0;
   1129 						break;
   1130 					default: /* Invalid, clear state */
   1131 						wrtchar(c, vs.so_at);
   1132 						vs.state = 0;
   1133 						goto maybe_scroll;
   1134 				}
   1135 				break;
   1136 
   1137 			default: /* VSS_EBRACE or VSS_EPARAM */
   1138 				switch (c) {
   1139 					int pos;
   1140 				case 'm':
   1141 					if (!vs.cx)
   1142 						vs.so = 0;
   1143 					else
   1144 						vs.so = 1;
   1145 					vs.state = 0;
   1146 					break;
   1147 				case 'A': { /* back cx rows */
   1148 					int cx = vs.cx;
   1149 					if (cx <= 0)
   1150 						cx = 1;
   1151 					else
   1152 						cx %= vs.nrow;
   1153 					pos = crtat - Crtat;
   1154 					pos -= vs.ncol * cx;
   1155 					if (pos < 0)
   1156 						pos += vs.nchr;
   1157 					crtat = Crtat + pos;
   1158 					vs.state = 0;
   1159 					break;
   1160 				}
   1161 				case 'B': { /* down cx rows */
   1162 					int cx = vs.cx;
   1163 					if (cx <= 0)
   1164 						cx = 1;
   1165 					else
   1166 						cx %= vs.nrow;
   1167 					pos = crtat - Crtat;
   1168 					pos += vs.ncol * cx;
   1169 					if (pos >= vs.nchr)
   1170 						pos -= vs.nchr;
   1171 					crtat = Crtat + pos;
   1172 					vs.state = 0;
   1173 					break;
   1174 				}
   1175 				case 'C': { /* right cursor */
   1176 					int cx = vs.cx,
   1177 					    col = vs.col;
   1178 					if (cx <= 0)
   1179 						cx = 1;
   1180 					else
   1181 						cx %= vs.ncol;
   1182 					pos = crtat - Crtat;
   1183 					pos += cx;
   1184 					col += cx;
   1185 					if (col >= vs.ncol) {
   1186 						pos -= vs.ncol;
   1187 						col -= vs.ncol;
   1188 					}
   1189 					vs.col = col;
   1190 					crtat = Crtat + pos;
   1191 					vs.state = 0;
   1192 					break;
   1193 				}
   1194 				case 'D': { /* left cursor */
   1195 					int cx = vs.cx,
   1196 					    col = vs.col;
   1197 					if (cx <= 0)
   1198 						cx = 1;
   1199 					else
   1200 						cx %= vs.ncol;
   1201 					pos = crtat - Crtat;
   1202 					pos -= cx;
   1203 					col -= cx;
   1204 					if (col < 0) {
   1205 						pos += vs.ncol;
   1206 						col += vs.ncol;
   1207 					}
   1208 					vs.col = col;
   1209 					crtat = Crtat + pos;
   1210 					vs.state = 0;
   1211 					break;
   1212 				}
   1213 				case 'J': /* Clear ... */
   1214 					switch (vs.cx) {
   1215 					case 0:
   1216 						/* ... to end of display */
   1217 						fillw((vs.at << 8) | ' ',
   1218 						    crtat,
   1219 						    Crtat + vs.nchr - crtat);
   1220 						break;
   1221 					case 1:
   1222 						/* ... to next location */
   1223 						fillw((vs.at << 8) | ' ',
   1224 						    Crtat,
   1225 						    crtat - Crtat + 1);
   1226 						break;
   1227 					case 2:
   1228 						/* ... whole display */
   1229 						fillw((vs.at << 8) | ' ',
   1230 						    Crtat,
   1231 						    vs.nchr);
   1232 						break;
   1233 					}
   1234 					vs.state = 0;
   1235 					break;
   1236 				case 'K': /* Clear line ... */
   1237 					switch (vs.cx) {
   1238 					case 0:
   1239 						/* ... current to EOL */
   1240 						fillw((vs.at << 8) | ' ',
   1241 						    crtat,
   1242 						    vs.ncol - vs.col);
   1243 						break;
   1244 					case 1:
   1245 						/* ... beginning to next */
   1246 						fillw((vs.at << 8) | ' ',
   1247 						    crtat - vs.col,
   1248 						    vs.col + 1);
   1249 						break;
   1250 					case 2:
   1251 						/* ... entire line */
   1252 						fillw((vs.at << 8) | ' ',
   1253 						    crtat - vs.col, vs.ncol);
   1254 						break;
   1255 					}
   1256 					vs.state = 0;
   1257 					break;
   1258 				case 'f': /* in system V consoles */
   1259 				case 'H': { /* Cursor move */
   1260 					int cx = vs.cx,
   1261 					    cy = vs.cy;
   1262 					if (!cx || !cy) {
   1263 						crtat = Crtat;
   1264 						vs.col = 0;
   1265 					} else {
   1266 						if (cx > vs.nrow)
   1267 							cx = vs.nrow;
   1268 						if (cy > vs.ncol)
   1269 							cy = vs.ncol;
   1270 						crtat = Crtat +
   1271 						    (cx - 1) * vs.ncol + cy - 1;
   1272 						vs.col = cy - 1;
   1273 					}
   1274 					vs.state = 0;
   1275 					break;
   1276 				}
   1277 				case 'M': { /* delete cx rows */
   1278 					u_short *crtAt = crtat - vs.col;
   1279 					int cx = vs.cx,
   1280 					    row = (crtAt - Crtat) / vs.ncol,
   1281 					    nrow = vs.nrow - row;
   1282 					if (cx <= 0)
   1283 						cx = 1;
   1284 					else if (cx > nrow)
   1285 						cx = nrow;
   1286 					if (cx < nrow)
   1287 #ifdef PCCONS_FORCE_WORD
   1288 						wcopy(crtAt + vs.ncol * cx,
   1289 						    crtAt, vs.ncol * (nrow -
   1290 						    cx) * CHR);
   1291 #else
   1292 						bcopy(crtAt + vs.ncol * cx,
   1293 						    crtAt, vs.ncol * (nrow -
   1294 						    cx) * CHR);
   1295 #endif
   1296 					fillw((vs.at << 8) | ' ',
   1297 					    crtAt + vs.ncol * (nrow - cx),
   1298 					    vs.ncol * cx);
   1299 					vs.state = 0;
   1300 					break;
   1301 				}
   1302 				case 'S': { /* scroll up cx lines */
   1303 					int cx = vs.cx;
   1304 					if (cx <= 0)
   1305 						cx = 1;
   1306 					else if (cx > vs.nrow)
   1307 						cx = vs.nrow;
   1308 					if (cx < vs.nrow)
   1309 #ifdef PCCONS_FORCE_WORD
   1310 						wcopy(Crtat + vs.ncol * cx,
   1311 						    Crtat, vs.ncol * (vs.nrow -
   1312 						    cx) * CHR);
   1313 #else
   1314 						bcopy(Crtat + vs.ncol * cx,
   1315 						    Crtat, vs.ncol * (vs.nrow -
   1316 						    cx) * CHR);
   1317 #endif
   1318 					fillw((vs.at << 8) | ' ',
   1319 					    Crtat + vs.ncol * (vs.nrow - cx),
   1320 					    vs.ncol * cx);
   1321 					/* crtat -= vs.ncol * cx; XXX */
   1322 					vs.state = 0;
   1323 					break;
   1324 				}
   1325 				case 'L': { /* insert cx rows */
   1326 					u_short *crtAt = crtat - vs.col;
   1327 					int cx = vs.cx,
   1328 					    row = (crtAt - Crtat) / vs.ncol,
   1329 					    nrow = vs.nrow - row;
   1330 					if (cx <= 0)
   1331 						cx = 1;
   1332 					else if (cx > nrow)
   1333 						cx = nrow;
   1334 					if (cx < nrow)
   1335 #ifdef PCCONS_FORCE_WORD
   1336 						wcopy(crtAt,
   1337 						    crtAt + vs.ncol * cx,
   1338 						    vs.ncol * (nrow - cx) *
   1339 						    CHR);
   1340 #else
   1341 						bcopy(crtAt,
   1342 						    crtAt + vs.ncol * cx,
   1343 						    vs.ncol * (nrow - cx) *
   1344 						    CHR);
   1345 #endif
   1346 					fillw((vs.at << 8) | ' ', crtAt,
   1347 					    vs.ncol * cx);
   1348 					vs.state = 0;
   1349 					break;
   1350 				}
   1351 				case 'T': { /* scroll down cx lines */
   1352 					int cx = vs.cx;
   1353 					if (cx <= 0)
   1354 						cx = 1;
   1355 					else if (cx > vs.nrow)
   1356 						cx = vs.nrow;
   1357 					if (cx < vs.nrow)
   1358 #ifdef PCCONS_FORCE_WORD
   1359 						wcopy(Crtat,
   1360 						    Crtat + vs.ncol * cx,
   1361 						    vs.ncol * (vs.nrow - cx) *
   1362 						    CHR);
   1363 #else
   1364 						bcopy(Crtat,
   1365 						    Crtat + vs.ncol * cx,
   1366 						    vs.ncol * (vs.nrow - cx) *
   1367 						    CHR);
   1368 #endif
   1369 					fillw((vs.at << 8) | ' ', Crtat,
   1370 					    vs.ncol * cx);
   1371 					/* crtat += vs.ncol * cx; XXX */
   1372 					vs.state = 0;
   1373 					break;
   1374 				}
   1375 				case ';': /* Switch params in cursor def */
   1376 					vs.state = VSS_EPARAM;
   1377 					break;
   1378 				case 'r':
   1379 					vs.so_at = (vs.cx & FG_MASK) |
   1380 					    ((vs.cy << 4) & BG_MASK);
   1381 					vs.state = 0;
   1382 					break;
   1383 				case 's': /* save cursor pos */
   1384 					vs.offset = crtat - Crtat;
   1385 					vs.state = 0;
   1386 					break;
   1387 				case 'u': /* restore cursor pos */
   1388 					crtat = Crtat + vs.offset;
   1389 					vs.row = vs.offset / vs.ncol;
   1390 					vs.col = vs.offset % vs.ncol;
   1391 					vs.state = 0;
   1392 					break;
   1393 				case 'x': /* set attributes */
   1394 					switch (vs.cx) {
   1395 					case 0:
   1396 						vs.at = FG_LIGHTGREY | BG_BLACK;
   1397 						break;
   1398 					case 1:
   1399 						/* ansi background */
   1400 						if (!vs.color)
   1401 							break;
   1402 						vs.at &= FG_MASK;
   1403 						vs.at |= bgansitopc[vs.cy & 7];
   1404 						break;
   1405 					case 2:
   1406 						/* ansi foreground */
   1407 						if (!vs.color)
   1408 							break;
   1409 						vs.at &= BG_MASK;
   1410 						vs.at |= fgansitopc[vs.cy & 7];
   1411 						break;
   1412 					case 3:
   1413 						/* pc text attribute */
   1414 						if (vs.state >= VSS_EPARAM)
   1415 							vs.at = vs.cy;
   1416 						break;
   1417 					}
   1418 					vs.state = 0;
   1419 					break;
   1420 
   1421 				default: /* Only numbers valid here */
   1422 					if ((c >= '0') && (c <= '9')) {
   1423 						if (vs.state >= VSS_EPARAM) {
   1424 							vs.cy *= 10;
   1425 							vs.cy += c - '0';
   1426 						} else {
   1427 							vs.cx *= 10;
   1428 							vs.cx += c - '0';
   1429 						}
   1430 					} else
   1431 						vs.state = 0;
   1432 					break;
   1433 				}
   1434 				break;
   1435 			}
   1436 		}
   1437 		if (scroll) {
   1438 			scroll = 0;
   1439 			/* scroll check */
   1440 			if (crtat >= Crtat + vs.nchr) {
   1441 				if (!kernel) {
   1442 					int s = spltty();
   1443 					if (lock_state & KB_SCROLL)
   1444 						tsleep(&lock_state,
   1445 						    PUSER, "pcputc", 0);
   1446 					splx(s);
   1447 				}
   1448 #if PCCONS_FORCE_WORD
   1449 				wcopy(Crtat + vs.ncol, Crtat,
   1450 				    (vs.nchr - vs.ncol) * CHR);
   1451 #else
   1452 				bcopy(Crtat + vs.ncol, Crtat,
   1453 				    (vs.nchr - vs.ncol) * CHR);
   1454 #endif
   1455 				fillw((vs.at << 8) | ' ',
   1456 				    Crtat + vs.nchr - vs.ncol,
   1457 				    vs.ncol);
   1458 				crtat -= vs.ncol;
   1459 			}
   1460 		}
   1461 	}
   1462 	async_update();
   1463 }
   1464 
   1465 /* the unshifted code for KB_SHIFT keys is used by X to distinguish between
   1466    left and right shift when reading the keyboard map */
   1467 static pccons_keymap_t	scan_codes[KB_NUM_KEYS] = {
   1468 /*  type       unshift   shift     control   altgr     shift_altgr scancode */
   1469   { KB_NONE,   "",       "",       "",       "",       ""}, /* 0 unused */
   1470   { KB_ASCII,  "\033",   "\033",   "\033",   "",       ""}, /* 1 ESCape */
   1471   { KB_ASCII,  "1",      "!",      "!",      "",       ""}, /* 2 1 */
   1472   { KB_ASCII,  "2",      "@",      "\000",   "",       ""}, /* 3 2 */
   1473   { KB_ASCII,  "3",      "#",      "#",      "",       ""}, /* 4 3 */
   1474   { KB_ASCII,  "4",      "$",      "$",      "",       ""}, /* 5 4 */
   1475   { KB_ASCII,  "5",      "%",      "%",      "",       ""}, /* 6 5 */
   1476   { KB_ASCII,  "6",      "^",      "\036",   "",       ""}, /* 7 6 */
   1477   { KB_ASCII,  "7",      "&",      "&",      "",       ""}, /* 8 7 */
   1478   { KB_ASCII,  "8",      "*",      "\010",   "",       ""}, /* 9 8 */
   1479   { KB_ASCII,  "9",      "(",      "(",      "",       ""}, /* 10 9 */
   1480   { KB_ASCII,  "0",      ")",      ")",      "",       ""}, /* 11 0 */
   1481   { KB_ASCII,  "-",      "_",      "\037",   "",       ""}, /* 12 - */
   1482   { KB_ASCII,  "=",      "+",      "+",      "",       ""}, /* 13 = */
   1483   { KB_ASCII,  "\177",   "\177",   "\010",   "",       ""}, /* 14 backspace */
   1484   { KB_ASCII,  "\t",     "\t",     "\t",     "",       ""}, /* 15 tab */
   1485   { KB_ASCII,  "q",      "Q",      "\021",   "",       ""}, /* 16 q */
   1486   { KB_ASCII,  "w",      "W",      "\027",   "",       ""}, /* 17 w */
   1487   { KB_ASCII,  "e",      "E",      "\005",   "",       ""}, /* 18 e */
   1488   { KB_ASCII,  "r",      "R",      "\022",   "",       ""}, /* 19 r */
   1489   { KB_ASCII,  "t",      "T",      "\024",   "",       ""}, /* 20 t */
   1490   { KB_ASCII,  "y",      "Y",      "\031",   "",       ""}, /* 21 y */
   1491   { KB_ASCII,  "u",      "U",      "\025",   "",       ""}, /* 22 u */
   1492   { KB_ASCII,  "i",      "I",      "\011",   "",       ""}, /* 23 i */
   1493   { KB_ASCII,  "o",      "O",      "\017",   "",       ""}, /* 24 o */
   1494   { KB_ASCII,  "p",      "P",      "\020",   "",       ""}, /* 25 p */
   1495   { KB_ASCII,  "[",      "{",      "\033",   "",       ""}, /* 26 [ */
   1496   { KB_ASCII,  "]",      "}",      "\035",   "",       ""}, /* 27 ] */
   1497   { KB_ASCII,  "\r",     "\r",     "\n",     "",       ""}, /* 28 return */
   1498   { KB_CTL,    "",       "",       "",       "",       ""}, /* 29 control */
   1499   { KB_ASCII,  "a",      "A",      "\001",   "",       ""}, /* 30 a */
   1500   { KB_ASCII,  "s",      "S",      "\023",   "",       ""}, /* 31 s */
   1501   { KB_ASCII,  "d",      "D",      "\004",   "",       ""}, /* 32 d */
   1502   { KB_ASCII,  "f",      "F",      "\006",   "",       ""}, /* 33 f */
   1503   { KB_ASCII,  "g",      "G",      "\007",   "",       ""}, /* 34 g */
   1504   { KB_ASCII,  "h",      "H",      "\010",   "",       ""}, /* 35 h */
   1505   { KB_ASCII,  "j",      "J",      "\n",     "",       ""}, /* 36 j */
   1506   { KB_ASCII,  "k",      "K",      "\013",   "",       ""}, /* 37 k */
   1507   { KB_ASCII,  "l",      "L",      "\014",   "",       ""}, /* 38 l */
   1508   { KB_ASCII,  ";",      ":",      ";",      "",       ""}, /* 39 ; */
   1509   { KB_ASCII,  "'",      "\"",     "'",      "",       ""}, /* 40 ' */
   1510   { KB_ASCII,  "`",      "~",      "`",      "",       ""}, /* 41 ` */
   1511   { KB_SHIFT,  "\001",   "",       "",       "",       ""}, /* 42 shift */
   1512   { KB_ASCII,  "\\",     "|",      "\034",   "",       ""}, /* 43 \ */
   1513   { KB_ASCII,  "z",      "Z",      "\032",   "",       ""}, /* 44 z */
   1514   { KB_ASCII,  "x",      "X",      "\030",   "",       ""}, /* 45 x */
   1515   { KB_ASCII,  "c",      "C",      "\003",   "",       ""}, /* 46 c */
   1516   { KB_ASCII,  "v",      "V",      "\026",   "",       ""}, /* 47 v */
   1517   { KB_ASCII,  "b",      "B",      "\002",   "",       ""}, /* 48 b */
   1518   { KB_ASCII,  "n",      "N",      "\016",   "",       ""}, /* 49 n */
   1519   { KB_ASCII,  "m",      "M",      "\r",     "",       ""}, /* 50 m */
   1520   { KB_ASCII,  ",",      "<",      "<",      "",       ""}, /* 51 , */
   1521   { KB_ASCII,  ".",      ">",      ">",      "",       ""}, /* 52 . */
   1522   { KB_ASCII,  "/",      "?",      "\037",   "",       ""}, /* 53 / */
   1523   { KB_SHIFT,  "\002",   "",       "",       "",       ""}, /* 54 shift */
   1524   { KB_KP,     "*",      "*",      "*",      "",       ""}, /* 55 kp * */
   1525   { KB_ALT,    "",       "",       "",       "",       ""}, /* 56 alt */
   1526   { KB_ASCII,  " ",      " ",      "\000",   "",       ""}, /* 57 space */
   1527   { KB_CAPS,   "",       "",       "",       "",       ""}, /* 58 caps */
   1528   { KB_FUNC,   "\033[M", "\033[Y", "\033[k", "",       ""}, /* 59 f1 */
   1529   { KB_FUNC,   "\033[N", "\033[Z", "\033[l", "",       ""}, /* 60 f2 */
   1530   { KB_FUNC,   "\033[O", "\033[a", "\033[m", "",       ""}, /* 61 f3 */
   1531   { KB_FUNC,   "\033[P", "\033[b", "\033[n", "",       ""}, /* 62 f4 */
   1532   { KB_FUNC,   "\033[Q", "\033[c", "\033[o", "",       ""}, /* 63 f5 */
   1533   { KB_FUNC,   "\033[R", "\033[d", "\033[p", "",       ""}, /* 64 f6 */
   1534   { KB_FUNC,   "\033[S", "\033[e", "\033[q", "",       ""}, /* 65 f7 */
   1535   { KB_FUNC,   "\033[T", "\033[f", "\033[r", "",       ""}, /* 66 f8 */
   1536   { KB_FUNC,   "\033[U", "\033[g", "\033[s", "",       ""}, /* 67 f9 */
   1537   { KB_FUNC,   "\033[V", "\033[h", "\033[t", "",       ""}, /* 68 f10 */
   1538   { KB_NUM,    "",       "",       "",       "",       ""}, /* 69 num lock */
   1539   { KB_SCROLL, "",       "",       "",       "",       ""}, /* 70 scroll lock */
   1540   { KB_KP,     "7",      "\033[H", "7",      "",       ""}, /* 71 kp 7 */
   1541   { KB_KP,     "8",      "\033[A", "8",      "",       ""}, /* 72 kp 8 */
   1542   { KB_KP,     "9",      "\033[I", "9",      "",       ""}, /* 73 kp 9 */
   1543   { KB_KP,     "-",      "-",      "-",      "",       ""}, /* 74 kp - */
   1544   { KB_KP,     "4",      "\033[D", "4",      "",       ""}, /* 75 kp 4 */
   1545   { KB_KP,     "5",      "\033[E", "5",      "",       ""}, /* 76 kp 5 */
   1546   { KB_KP,     "6",      "\033[C", "6",      "",       ""}, /* 77 kp 6 */
   1547   { KB_KP,     "+",      "+",      "+",      "",       ""}, /* 78 kp + */
   1548   { KB_KP,     "1",      "\033[F", "1",      "",       ""}, /* 79 kp 1 */
   1549   { KB_KP,     "2",      "\033[B", "2",      "",       ""}, /* 80 kp 2 */
   1550   { KB_KP,     "3",      "\033[G", "3",      "",       ""}, /* 81 kp 3 */
   1551   { KB_KP,     "0",      "\033[L", "0",      "",       ""}, /* 82 kp 0 */
   1552   { KB_KP,     ",",      "\177",   ",",      "",       ""}, /* 83 kp , */
   1553   { KB_NONE,   "",       "",       "",       "",       ""}, /* 84 0 */
   1554   { KB_NONE,   "",       "",       "",       "",       ""}, /* 85 0 */
   1555   { KB_NONE,   "",       "",       "",       "",       ""}, /* 86 0 */
   1556   { KB_FUNC,   "\033[W", "\033[i", "\033[u", "",       ""}, /* 87 f11 */
   1557   { KB_FUNC,   "\033[X", "\033[j", "\033[v", "",       ""}, /* 88 f12 */
   1558   { KB_NONE,   "",       "",       "",       "",       ""}, /* 89 0 */
   1559   { KB_NONE,   "",       "",       "",       "",       ""}, /* 90 0 */
   1560   { KB_NONE,   "",       "",       "",       "",       ""}, /* 91 0 */
   1561   { KB_NONE,   "",       "",       "",       "",       ""}, /* 92 0 */
   1562   { KB_NONE,   "",       "",       "",       "",       ""}, /* 93 0 */
   1563   { KB_NONE,   "",       "",       "",       "",       ""}, /* 94 0 */
   1564   { KB_NONE,   "",       "",       "",       "",       ""}, /* 95 0 */
   1565   { KB_NONE,   "",       "",       "",       "",       ""}, /* 96 0 */
   1566   { KB_NONE,   "",       "",       "",       "",       ""}, /* 97 0 */
   1567   { KB_NONE,   "",       "",       "",       "",       ""}, /* 98 0 */
   1568   { KB_NONE,   "",       "",       "",       "",       ""}, /* 99 0 */
   1569   { KB_NONE,   "",       "",       "",       "",       ""}, /* 100 */
   1570   { KB_NONE,   "",       "",       "",       "",       ""}, /* 101 */
   1571   { KB_NONE,   "",       "",       "",       "",       ""}, /* 102 */
   1572   { KB_NONE,   "",       "",       "",       "",       ""}, /* 103 */
   1573   { KB_NONE,   "",       "",       "",       "",       ""}, /* 104 */
   1574   { KB_NONE,   "",       "",       "",       "",       ""}, /* 105 */
   1575   { KB_NONE,   "",       "",       "",       "",       ""}, /* 106 */
   1576   { KB_NONE,   "",       "",       "",       "",       ""}, /* 107 */
   1577   { KB_NONE,   "",       "",       "",       "",       ""}, /* 108 */
   1578   { KB_NONE,   "",       "",       "",       "",       ""}, /* 109 */
   1579   { KB_NONE,   "",       "",       "",       "",       ""}, /* 110 */
   1580   { KB_NONE,   "",       "",       "",       "",       ""}, /* 111 */
   1581   { KB_NONE,   "",       "",       "",       "",       ""}, /* 112 */
   1582   { KB_NONE,   "",       "",       "",       "",       ""}, /* 113 */
   1583   { KB_NONE,   "",       "",       "",       "",       ""}, /* 114 */
   1584   { KB_NONE,   "",       "",       "",       "",       ""}, /* 115 */
   1585   { KB_NONE,   "",       "",       "",       "",       ""}, /* 116 */
   1586   { KB_NONE,   "",       "",       "",       "",       ""}, /* 117 */
   1587   { KB_NONE,   "",       "",       "",       "",       ""}, /* 118 */
   1588   { KB_NONE,   "",       "",       "",       "",       ""}, /* 119 */
   1589   { KB_NONE,   "",       "",       "",       "",       ""}, /* 120 */
   1590   { KB_NONE,   "",       "",       "",       "",       ""}, /* 121 */
   1591   { KB_NONE,   "",       "",       "",       "",       ""}, /* 122 */
   1592   { KB_NONE,   "",       "",       "",       "",       ""}, /* 123 */
   1593   { KB_NONE,   "",       "",       "",       "",       ""}, /* 124 */
   1594   { KB_NONE,   "",       "",       "",       "",       ""}, /* 125 */
   1595   { KB_NONE,   "",       "",       "",       "",       ""}, /* 126 */
   1596   { KB_NONE,   "",       "",       "",       "",       ""}  /* 127 */
   1597 };
   1598 
   1599 /*
   1600  * Get characters from the keyboard.  If none are present, return NULL.
   1601  */
   1602 char *
   1603 sget(void)
   1604 {
   1605 	u_char dt;
   1606 	static u_char extended = 0, shift_state = 0;
   1607 	static u_char capchar[2];
   1608 
   1609 top:
   1610 	KBD_DELAY;
   1611 	dt = kbd_data_read_1();
   1612 
   1613 	switch (dt) {
   1614 	case KBR_ACK: case KBR_ECHO:
   1615 		kb_oq_get = (kb_oq_get + 1) & 7;
   1616 		if(kb_oq_get != kb_oq_put) {
   1617 			kbd_data_write_1(kb_oq[kb_oq_get]);
   1618 		}
   1619 		goto loop;
   1620 	case KBR_RESEND:
   1621 		kbd_data_write_1(kb_oq[kb_oq_get]);
   1622 		goto loop;
   1623 	}
   1624 
   1625 	if (pc_xmode > 0) {
   1626 #if defined(DDB) && defined(XSERVER_DDB)
   1627 		/* F12 enters the debugger while in X mode */
   1628 		if (dt == 88)
   1629 			Debugger();
   1630 #endif
   1631 		capchar[0] = dt;
   1632 		capchar[1] = 0;
   1633 		/*
   1634 		 * Check for locking keys.
   1635 		 *
   1636 		 * XXX Setting the LEDs this way is a bit bogus.  What if the
   1637 		 * keyboard has been remapped in X?
   1638 		 */
   1639 		switch (scan_codes[dt & 0x7f].type) {
   1640 		case KB_NUM:
   1641 			if (dt & 0x80) {
   1642 				shift_state &= ~KB_NUM;
   1643 				break;
   1644 			}
   1645 			if (shift_state & KB_NUM)
   1646 				break;
   1647 			shift_state |= KB_NUM;
   1648 			lock_state ^= KB_NUM;
   1649 			async_update();
   1650 			break;
   1651 		case KB_CAPS:
   1652 			if (dt & 0x80) {
   1653 				shift_state &= ~KB_CAPS;
   1654 				break;
   1655 			}
   1656 			if (shift_state & KB_CAPS)
   1657 				break;
   1658 			shift_state |= KB_CAPS;
   1659 			lock_state ^= KB_CAPS;
   1660 			async_update();
   1661 			break;
   1662 		case KB_SCROLL:
   1663 			if (dt & 0x80) {
   1664 				shift_state &= ~KB_SCROLL;
   1665 				break;
   1666 			}
   1667 			if (shift_state & KB_SCROLL)
   1668 				break;
   1669 			shift_state |= KB_SCROLL;
   1670 			lock_state ^= KB_SCROLL;
   1671 			if ((lock_state & KB_SCROLL) == 0)
   1672 				wakeup((void *)&lock_state);
   1673 			async_update();
   1674 			break;
   1675 		}
   1676 		return capchar;
   1677 	}
   1678 
   1679 	switch (dt) {
   1680 	case KBR_EXTENDED:
   1681 		extended = 1;
   1682 		goto loop;
   1683 	}
   1684 
   1685 #ifdef DDB
   1686 	/*
   1687 	 * Check for cntl-alt-esc.
   1688 	 */
   1689 	if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
   1690 		/* XXX - check pccons_is_console */
   1691 		Debugger();
   1692 		dt |= 0x80;	/* discard esc (ddb discarded ctl-alt) */
   1693 	}
   1694 #endif
   1695 
   1696 	/*
   1697 	 * Check for make/break.
   1698 	 */
   1699 	if (dt & 0x80) {
   1700 		/*
   1701 		 * break
   1702 		 */
   1703 		dt &= 0x7f;
   1704 		switch (scan_codes[dt].type) {
   1705 		case KB_NUM:
   1706 			shift_state &= ~KB_NUM;
   1707 			break;
   1708 		case KB_CAPS:
   1709 			shift_state &= ~KB_CAPS;
   1710 			break;
   1711 		case KB_SCROLL:
   1712 			shift_state &= ~KB_SCROLL;
   1713 			break;
   1714 		case KB_SHIFT:
   1715 			shift_state &= ~KB_SHIFT;
   1716 			break;
   1717 		case KB_ALT:
   1718 			if (extended)
   1719 				shift_state &= ~KB_ALTGR;
   1720 			else
   1721 				shift_state &= ~KB_ALT;
   1722 			break;
   1723 		case KB_CTL:
   1724 			shift_state &= ~KB_CTL;
   1725 			break;
   1726 		}
   1727 	} else {
   1728 		/*
   1729 		 * make
   1730 		 */
   1731 		switch (scan_codes[dt].type) {
   1732 		/*
   1733 		 * locking keys
   1734 		 */
   1735 		case KB_NUM:
   1736 			if (shift_state & KB_NUM)
   1737 				break;
   1738 			shift_state |= KB_NUM;
   1739 			lock_state ^= KB_NUM;
   1740 			async_update();
   1741 			break;
   1742 		case KB_CAPS:
   1743 			if (shift_state & KB_CAPS)
   1744 				break;
   1745 			shift_state |= KB_CAPS;
   1746 			lock_state ^= KB_CAPS;
   1747 			async_update();
   1748 			break;
   1749 		case KB_SCROLL:
   1750 			if (shift_state & KB_SCROLL)
   1751 				break;
   1752 			shift_state |= KB_SCROLL;
   1753 			lock_state ^= KB_SCROLL;
   1754 			if ((lock_state & KB_SCROLL) == 0)
   1755 				wakeup((void *)&lock_state);
   1756 			async_update();
   1757 			break;
   1758 		/*
   1759 		 * non-locking keys
   1760 		 */
   1761 		case KB_SHIFT:
   1762 			shift_state |= KB_SHIFT;
   1763 			break;
   1764 		case KB_ALT:
   1765 			if (extended)
   1766 				shift_state |= KB_ALTGR;
   1767 			else
   1768 				shift_state |= KB_ALT;
   1769 			break;
   1770 		case KB_CTL:
   1771 			shift_state |= KB_CTL;
   1772 			break;
   1773 		case KB_ASCII:
   1774 			/* control has highest priority */
   1775 			if (shift_state & KB_CTL)
   1776 				capchar[0] = scan_codes[dt].ctl[0];
   1777 			else if (shift_state & KB_ALTGR) {
   1778 				if (shift_state & KB_SHIFT)
   1779 					capchar[0] = scan_codes[dt].shift_altgr[0];
   1780 				else
   1781 					capchar[0] = scan_codes[dt].altgr[0];
   1782 			}
   1783 			else {
   1784 				if (shift_state & KB_SHIFT)
   1785 					capchar[0] = scan_codes[dt].shift[0];
   1786 				else
   1787 					capchar[0] = scan_codes[dt].unshift[0];
   1788 			}
   1789 			if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
   1790 			    capchar[0] <= 'z') {
   1791 				capchar[0] -= ('a' - 'A');
   1792 			}
   1793 			capchar[0] |= (shift_state & KB_ALT);
   1794 			extended = 0;
   1795 			return capchar;
   1796 		case KB_NONE:
   1797 printf("keycode %d\n",dt);
   1798 			break;
   1799 		case KB_FUNC: {
   1800 			char *more_chars;
   1801 			if (shift_state & KB_SHIFT)
   1802 				more_chars = scan_codes[dt].shift;
   1803 			else if (shift_state & KB_CTL)
   1804 				more_chars = scan_codes[dt].ctl;
   1805 			else
   1806 				more_chars = scan_codes[dt].unshift;
   1807 			extended = 0;
   1808 			return more_chars;
   1809 		}
   1810 		case KB_KP: {
   1811 			char *more_chars;
   1812 			if (shift_state & (KB_SHIFT | KB_CTL) ||
   1813 			    (lock_state & KB_NUM) == 0 || extended)
   1814 				more_chars = scan_codes[dt].shift;
   1815 			else
   1816 				more_chars = scan_codes[dt].unshift;
   1817 			extended = 0;
   1818 			return more_chars;
   1819 		}
   1820 		}
   1821 	}
   1822 
   1823 	extended = 0;
   1824 loop:
   1825 	if ((kbd_cmd_read_1() & KBS_DIB) == 0)
   1826 		return 0;
   1827 	goto top;
   1828 }
   1829 
   1830 paddr_t
   1831 pcmmap(dev_t dev, off_t offset, int nprot)
   1832 {
   1833 	struct pccons_context *pc = &pccons_console_context;
   1834 	paddr_t pa;
   1835 
   1836 	if (offset >= 0xa0000 && offset < 0xc0000) {
   1837 		if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
   1838 			return -1;
   1839 		pa += offset - pc->pc_config->pc_mono_memaddr;
   1840 		return mips_btop(pa);
   1841 	}
   1842 	if (offset >= 0x0000 && offset < 0x10000) {
   1843 		if (bus_space_paddr(pc->pc_crt_iot, pc->pc_mono_ioh, &pa))
   1844 			return -1;
   1845 		pa += offset - pc->pc_config->pc_mono_iobase;
   1846 		return mips_btop(pa);
   1847 	}
   1848 	if (offset >= 0x40000000 && offset < 0x40800000) {
   1849 		if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
   1850 			return (-1);
   1851 		pa += offset - 0x40000000 - pc->pc_config->pc_mono_memaddr;
   1852 		return mips_btop(pa);
   1853 	}
   1854 	return -1;
   1855 }
   1856 
   1857 void
   1858 pc_xmode_on(void)
   1859 {
   1860 	if (pc_xmode)
   1861 		return;
   1862 	pc_xmode = 1;
   1863 
   1864 #ifdef XFREE86_BUG_COMPAT
   1865 	/* If still unchanged, get current shape. */
   1866 	if (cursor_shape == 0xffff)
   1867 		get_cursor_shape();
   1868 #endif
   1869 }
   1870 
   1871 void
   1872 pc_xmode_off(void)
   1873 {
   1874 	if (pc_xmode == 0)
   1875 		return;
   1876 	pc_xmode = 0;
   1877 
   1878 #ifdef XFREE86_BUG_COMPAT
   1879 	/* XXX It would be hard to justify why the X server doesn't do this. */
   1880 	set_cursor_shape();
   1881 #endif
   1882 	async_update();
   1883 }
   1884