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