Home | History | Annotate | Line # | Download | only in dev
pccons.c revision 1.15
      1 /*	$NetBSD: pccons.c,v 1.15 2000/03/03 12:35:40 soda 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 /*	NetBSD: pms.c,v 1.21 1995/04/18 02:25:18 mycroft Exp	*/
      5 
      6 /*-
      7  * Copyright (c) 1993, 1994, 1995 Charles M. Hannum.  All rights reserved.
      8  * Copyright (c) 1990 The Regents of the University of California.
      9  * All rights reserved.
     10  *
     11  * This code is derived from software contributed to Berkeley by
     12  * William Jolitz and Don Ahn.
     13  *
     14  * Copyright (c) 1994 Charles M. Hannum.
     15  * Copyright (c) 1992, 1993 Erik Forsberg.
     16  *
     17  * Redistribution and use in source and binary forms, with or without
     18  * modification, are permitted provided that the following conditions
     19  * are met:
     20  * 1. Redistributions of source code must retain the above copyright
     21  *    notice, this list of conditions and the following disclaimer.
     22  * 2. Redistributions in binary form must reproduce the above copyright
     23  *    notice, this list of conditions and the following disclaimer in the
     24  *    documentation and/or other materials provided with the distribution.
     25  * 3. All advertising materials mentioning features or use of this software
     26  *    must display the following acknowledgement:
     27  *	This product includes software developed by the University of
     28  *	California, Berkeley and its contributors.
     29  * 4. Neither the name of the University nor the names of its contributors
     30  *    may be used to endorse or promote products derived from this software
     31  *    without specific prior written permission.
     32  *
     33  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     34  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     35  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     36  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     37  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     38  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     39  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     41  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     42  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     43  * SUCH DAMAGE.
     44  *
     45  *	@(#)pccons.c	5.11 (Berkeley) 5/21/91
     46  */
     47 
     48 /*
     49  * code to work keyboard & display for PC-style console
     50  */
     51 
     52 #include "opt_ddb.h"
     53 
     54 #include <sys/param.h>
     55 #include <sys/systm.h>
     56 #include <sys/ioctl.h>
     57 #include <sys/proc.h>
     58 #include <sys/user.h>
     59 #include <sys/select.h>
     60 #include <sys/tty.h>
     61 #include <sys/uio.h>
     62 #include <sys/callout.h>
     63 #include <sys/syslog.h>
     64 #include <sys/device.h>
     65 #include <sys/poll.h>
     66 #include <sys/conf.h>
     67 #include <sys/vnode.h>
     68 #include <sys/fcntl.h>
     69 #include <sys/kernel.h>
     70 #include <sys/kcore.h>
     71 
     72 #include <dev/cons.h>
     73 
     74 #include <machine/cpu.h>
     75 #include <machine/pio.h>
     76 #include <machine/autoconf.h>
     77 #include <machine/bus.h>
     78 #include <machine/display.h>
     79 #include <machine/pccons.h>
     80 #include <arc/arc/arctype.h>
     81 #include <arc/arc/arcbios.h>
     82 #include <arc/pica/pica.h>
     83 #include <arc/dti/desktech.h>
     84 
     85 #include <dev/isa/isavar.h>
     86 #include <machine/isa_machdep.h>
     87 #include <machine/kbdreg.h>
     88 
     89 #include <dev/cons.h>
     90 
     91 #define	XFREE86_BUG_COMPAT
     92 
     93 #ifndef BEEP_FREQ
     94 #define BEEP_FREQ 1600
     95 #endif
     96 #ifndef BEEP_TIME
     97 #define BEEP_TIME (hz/5)
     98 #endif
     99 
    100 #define PCBURST 128
    101 
    102 static u_short *Crtat;			/* pointer to backing store */
    103 static u_short *crtat;			/* pointer to current char */
    104 static u_char async, kernel, polling;	/* Really, you don't want to know. */
    105 static u_char lock_state = 0x00,	/* all off */
    106 	      old_lock_state = 0xff,
    107 	      typematic_rate = 0xff,	/* don't update until set by user */
    108 	      old_typematic_rate = 0xff;
    109 static u_short cursor_shape = 0xffff,	/* don't update until set by user */
    110 	       old_cursor_shape = 0xffff;
    111 static pccons_keymap_t scan_codes[KB_NUM_KEYS];/* keyboard translation table */
    112 int pc_xmode = 0;
    113 
    114 cdev_decl(pc);
    115 
    116 /*
    117  *  Keyboard output queue.
    118  */
    119 int	kb_oq_put = 0;
    120 int	kb_oq_get = 0;
    121 u_char	kb_oq[8];
    122 
    123 #define	PCUNIT(x)	(minor(x))
    124 
    125 static struct video_state {
    126 	int 	cx, cy;		/* escape parameters */
    127 	int 	row, col;	/* current cursor position */
    128 	int 	nrow, ncol, nchr;	/* current screen geometry */
    129 	int	offset;		/* Saved cursor pos */
    130 	u_char	state;		/* parser state */
    131 #define	VSS_ESCAPE	1
    132 #define	VSS_EBRACE	2
    133 #define	VSS_EPARAM	3
    134 	char	so;		/* in standout mode? */
    135 	char	color;		/* color or mono display */
    136 	char	at;		/* normal attributes */
    137 	char	so_at;		/* standout attributes */
    138 } vs;
    139 
    140 struct pc_softc {
    141 	struct	device sc_dev;
    142 	struct	tty *sc_tty;
    143 };
    144 
    145 struct opms_softc {		/* driver status information */
    146 	struct device sc_dev;
    147 
    148 	struct clist sc_q;
    149 	struct selinfo sc_rsel;
    150 	u_char sc_state;	/* mouse driver state */
    151 #define	PMS_OPEN	0x01	/* device is open */
    152 #define	PMS_ASLP	0x02	/* waiting for mouse data */
    153 	u_char sc_status;	/* mouse button status */
    154 	int sc_x, sc_y;		/* accumulated motion in the X,Y axis */
    155 };
    156 
    157 int pcprobe __P((struct device *, struct cfdata *, void *));
    158 void pcattach __P((struct device *, struct device *, void *));
    159 int pcintr __P((void *));
    160 void pc_xmode_on __P((void));
    161 void pc_xmode_off __P((void));
    162 static u_char kbc_get8042cmd __P((void));
    163 static int kbc_put8042cmd __P((u_char));
    164 int kbc_8042sysreset __P((void));
    165 int kbd_cmd __P((u_char, u_char));
    166 static __inline int kbd_wait_output __P((void));
    167 static __inline int kbd_wait_input __P((void));
    168 static __inline void kbd_flush_input __P((void));
    169 void set_cursor_shape __P((void));
    170 void get_cursor_shape __P((void));
    171 void async_update __P((void));
    172 void do_async_update __P((u_char));;
    173 
    174 void pccnattach __P((void));
    175 void pccnputc __P((dev_t, int c));
    176 int pccngetc __P((dev_t));
    177 void pccnpollc __P((dev_t, int));
    178 
    179 extern struct cfdriver pc_cd;
    180 
    181 struct cfattach pc_pica_ca = {
    182 	 sizeof(struct pc_softc), pcprobe, pcattach
    183 };
    184 
    185 struct cfattach pc_isa_ca = {
    186 	 sizeof(struct pc_softc), pcprobe, pcattach
    187 };
    188 int opmsprobe __P((struct device *, struct cfdata *, void *));
    189 void opmsattach __P((struct device *, struct device *, void *));
    190 int opmsintr __P((void *));
    191 
    192 struct cfattach opms_ca = {
    193 	sizeof(struct opms_softc), opmsprobe, opmsattach
    194 };
    195 
    196 extern struct cfdriver opms_cd;
    197 
    198 #define	PMSUNIT(dev)	(minor(dev))
    199 
    200 #define	CHR		2
    201 
    202 static unsigned int addr_6845;
    203 static unsigned int mono_base = 0x3b4;
    204 static unsigned int mono_buf = 0xb0000;
    205 static unsigned int cga_base = 0x3d4;
    206 static unsigned int cga_buf = 0xb8000;
    207 static unsigned int kbd_cmdp = 0x64;
    208 static unsigned int kbd_datap = 0x60;
    209 
    210 char *sget __P((void));
    211 void sput __P((u_char *, int));
    212 
    213 void	pcstart __P((struct tty *));
    214 int	pcparam __P((struct tty *, struct termios *));
    215 static __inline void wcopy __P((void *, void *, u_int));
    216 
    217 extern void fillw __P((int, u_int16_t *, int));
    218 
    219 #define	KBD_DELAY \
    220 		DELAY(10);
    221 
    222 /*
    223  * bcopy variant that only moves word-aligned 16-bit entities,
    224  * for stupid VGA cards.  cnt is required to be an even vale.
    225  */
    226 static __inline void
    227 wcopy(src, tgt, cnt)
    228 	void *src, *tgt;
    229 	u_int cnt;
    230 {
    231 	u_int16_t *from = src;
    232 	u_int16_t *to = tgt;
    233 
    234 	cnt >>= 1;
    235 	if (to < from || to >= from + cnt)
    236 		while(cnt--)
    237 			*to++ = *from++;
    238 	else {
    239 		to += cnt;
    240 		from += cnt;
    241 		while(cnt--)
    242 			*--to = *--from;
    243 	}
    244 }
    245 
    246 static __inline int
    247 kbd_wait_output()
    248 {
    249 	u_int i;
    250 
    251 	for (i = 100000; i; i--)
    252 		if ((inb(kbd_cmdp) & KBS_IBF) == 0) {
    253 			KBD_DELAY;
    254 			return 1;
    255 		}
    256 	return 0;
    257 }
    258 
    259 static __inline int
    260 kbd_wait_input()
    261 {
    262 	u_int i;
    263 
    264 	for (i = 100000; i; i--)
    265 		if ((inb(kbd_cmdp) & KBS_DIB) != 0) {
    266 			KBD_DELAY;
    267 			return 1;
    268 		}
    269 	return 0;
    270 }
    271 
    272 static __inline void
    273 kbd_flush_input()
    274 {
    275 	u_char c;
    276 
    277 	while ((c = inb(kbd_cmdp)) & 0x03)
    278 		if ((c & KBS_DIB) == KBS_DIB) {
    279 			/* XXX - delay is needed to prevent some keyboards from
    280 			   wedging when the system boots */
    281 			delay(6);
    282 			(void) inb(kbd_datap);
    283 		}
    284 }
    285 
    286 
    287 
    288 /*
    289  * Pass system reset command  to keyboard controller (8042).
    290  */
    291 int
    292 kbc_8042sysreset()
    293 {
    294 
    295 	if (!kbd_wait_output())
    296 		return 0;
    297 	outb(kbd_cmdp, 0xd1);
    298 	if (!kbd_wait_output())
    299 		return 0;
    300 	outb(kbd_datap, 0);		/* ZAP */
    301 	return 1;
    302 }
    303 
    304 #if 1
    305 /*
    306  * Get the current command byte.
    307  */
    308 static u_char
    309 kbc_get8042cmd()
    310 {
    311 
    312 	if (!kbd_wait_output())
    313 		return -1;
    314 	outb(kbd_cmdp, K_RDCMDBYTE);
    315 	if (!kbd_wait_input())
    316 		return -1;
    317 	return inb(kbd_datap);
    318 }
    319 #endif
    320 
    321 /*
    322  * Pass command byte to keyboard controller (8042).
    323  */
    324 static int
    325 kbc_put8042cmd(val)
    326 	u_char val;
    327 {
    328 
    329 	if (!kbd_wait_output())
    330 		return 0;
    331 	outb(kbd_cmdp, K_LDCMDBYTE);
    332 	if (!kbd_wait_output())
    333 		return 0;
    334 	outb(kbd_datap, val);
    335 	return 1;
    336 }
    337 
    338 /*
    339  * Pass command to keyboard itself
    340  */
    341 int
    342 kbd_cmd(val, polling)
    343 	u_char val;
    344 	u_char polling;
    345 {
    346 	u_int retries = 3;
    347 	register u_int i;
    348 
    349 	if(!polling) {
    350 		i = spltty();
    351 		if(kb_oq_get == kb_oq_put) {
    352 			outb(kbd_datap, val);
    353 		}
    354 		kb_oq[kb_oq_put] = val;
    355 		kb_oq_put = (kb_oq_put + 1) & 7;
    356 		splx(i);
    357 		return(1);
    358 	}
    359 	else do {
    360 		if (!kbd_wait_output())
    361 			return 0;
    362 		outb(kbd_datap, val);
    363 		for (i = 100000; i; i--) {
    364 			if (inb(kbd_cmdp) & KBS_DIB) {
    365 				register u_char c;
    366 
    367 				KBD_DELAY;
    368 				c = inb(kbd_datap);
    369 				if (c == KBR_ACK || c == KBR_ECHO) {
    370 					return 1;
    371 				}
    372 				if (c == KBR_RESEND) {
    373 					break;
    374 				}
    375 #ifdef DIAGNOSTIC
    376 				printf("kbd_cmd: input char %x lost\n", c);
    377 #endif
    378 			}
    379 		}
    380 	} while (--retries);
    381 	return 0;
    382 }
    383 
    384 void
    385 set_cursor_shape()
    386 {
    387 	register int iobase = addr_6845;
    388 
    389 	outb(iobase, 10);
    390 	outb(iobase+1, cursor_shape >> 8);
    391 	outb(iobase, 11);
    392 	outb(iobase+1, cursor_shape);
    393 	old_cursor_shape = cursor_shape;
    394 }
    395 
    396 void
    397 get_cursor_shape()
    398 {
    399 	register int iobase = addr_6845;
    400 
    401 	outb(iobase, 10);
    402 	cursor_shape = inb(iobase+1) << 8;
    403 	outb(iobase, 11);
    404 	cursor_shape |= inb(iobase+1);
    405 
    406 	/*
    407 	 * real 6845's, as found on, MDA, Hercules or CGA cards, do
    408 	 * not support reading the cursor shape registers. the 6845
    409 	 * tri-states it's data bus. This is _normally_ read by the
    410 	 * cpu as either 0x00 or 0xff.. in which case we just use
    411 	 * a line cursor.
    412 	 */
    413 	if (cursor_shape == 0x0000 || cursor_shape == 0xffff)
    414 		cursor_shape = 0x0b10;
    415 	else
    416 		cursor_shape &= 0x1f1f;
    417 }
    418 
    419 void
    420 do_async_update(poll)
    421 	u_char poll;
    422 {
    423 	int pos;
    424 	static int old_pos = -1;
    425 
    426 	async = 0;
    427 
    428 	if (lock_state != old_lock_state) {
    429 		old_lock_state = lock_state;
    430 		if (!kbd_cmd(KBC_MODEIND, poll) ||
    431 		    !kbd_cmd(lock_state, poll)) {
    432 			printf("pc: timeout updating leds\n");
    433 			(void) kbd_cmd(KBC_ENABLE, poll);
    434 		}
    435 	}
    436 	if (typematic_rate != old_typematic_rate) {
    437 		old_typematic_rate = typematic_rate;
    438 		if (!kbd_cmd(KBC_TYPEMATIC, poll) ||
    439 		    !kbd_cmd(typematic_rate, poll)) {
    440 			printf("pc: timeout updating typematic rate\n");
    441 			(void) kbd_cmd(KBC_ENABLE, poll);
    442 		}
    443 	}
    444 
    445 	if (pc_xmode > 0)
    446 		return;
    447 
    448 	pos = crtat - Crtat;
    449 	if (pos != old_pos) {
    450 		register int iobase = addr_6845;
    451 		outb(iobase, 14);
    452 		outb(iobase+1, pos >> 8);
    453 		outb(iobase, 15);
    454 		outb(iobase+1, pos);
    455 		old_pos = pos;
    456 	}
    457 	if (cursor_shape != old_cursor_shape)
    458 		set_cursor_shape();
    459 }
    460 
    461 void
    462 async_update()
    463 {
    464 
    465 	if (kernel || polling) {
    466 		if (async)
    467 			untimeout((void(*)(void *))do_async_update, NULL);
    468 		do_async_update(1);
    469 	} else {
    470 		if (async)
    471 			return;
    472 		async = 1;
    473 		timeout((void(*)(void *))do_async_update, NULL, 1);
    474 	}
    475 }
    476 
    477 /*
    478  * these are both bad jokes
    479  */
    480 int
    481 pcprobe(parent, match, aux)
    482 	struct device *parent;
    483 	struct cfdata *match;
    484 	void *aux;
    485 {
    486 	struct confargs *ca = aux;
    487 	u_int i;
    488 
    489 	/* Make shure we're looking for this type of device */
    490 	if(!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pica")) {
    491 		if(!BUS_MATCHNAME(ca, "pc"))
    492 			return(0);
    493 	}
    494 
    495 	/* Enable interrupts and keyboard, etc. */
    496 	if (!kbc_put8042cmd(CMDBYTE)) {
    497 		printf("pcprobe: command error\n");
    498 		return 0;
    499 	}
    500 
    501 #if 1
    502 	/* Flush any garbage. */
    503 	kbd_flush_input();
    504 	/* Reset the keyboard. */
    505 	if (!kbd_cmd(KBC_RESET, 1)) {
    506 		printf("pcprobe: reset error %d\n", 1);
    507 		goto lose;
    508 	}
    509 	for (i = 600000; i; i--)
    510 		if ((inb(kbd_cmdp) & KBS_DIB) != 0) {
    511 			KBD_DELAY;
    512 			break;
    513 		}
    514 	if (i == 0 || inb(kbd_datap) != KBR_RSTDONE) {
    515 		printf("pcprobe: reset error %d\n", 2);
    516 		goto lose;
    517 	}
    518 	/*
    519 	 * Some keyboards seem to leave a second ack byte after the reset.
    520 	 * This is kind of stupid, but we account for them anyway by just
    521 	 * flushing the buffer.
    522 	 */
    523 	kbd_flush_input();
    524 	/* Just to be sure. */
    525 	if (!kbd_cmd(KBC_ENABLE, 1)) {
    526 		printf("pcprobe: reset error %d\n", 3);
    527 		goto lose;
    528 	}
    529 
    530 	/*
    531 	 * Some keyboard/8042 combinations do not seem to work if the keyboard
    532 	 * is set to table 1; in fact, it would appear that some keyboards just
    533 	 * ignore the command altogether.  So by default, we use the AT scan
    534 	 * codes and have the 8042 translate them.  Unfortunately, this is
    535 	 * known to not work on some PS/2 machines.  We try desparately to deal
    536 	 * with this by checking the (lack of a) translate bit in the 8042 and
    537 	 * attempting to set the keyboard to XT mode.  If this all fails, well,
    538 	 * tough luck.
    539 	 *
    540 	 * XXX It would perhaps be a better choice to just use AT scan codes
    541 	 * and not bother with this.
    542 	 */
    543 	if (kbc_get8042cmd() & KC8_TRANS) {
    544 		/* The 8042 is translating for us; use AT codes. */
    545 		if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(2, 1)) {
    546 			printf("pcprobe: reset error %d\n", 4);
    547 			goto lose;
    548 		}
    549 	} else {
    550 		/* Stupid 8042; set keyboard to XT codes. */
    551 		if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(1, 1)) {
    552 			printf("pcprobe: reset error %d\n", 5);
    553 			goto lose;
    554 		}
    555 	}
    556 
    557 lose:
    558 	/*
    559 	 * Technically, we should probably fail the probe.  But we'll be nice
    560 	 * and allow keyboard-less machines to boot with the console.
    561 	 */
    562 #endif
    563 
    564 	return 1;
    565 }
    566 
    567 void
    568 pcattach(parent, self, aux)
    569 	struct device *parent, *self;
    570 	void *aux;
    571 {
    572 	struct confargs *ca = aux;
    573 	struct isa_attach_args *ia = aux;
    574 	struct pc_softc *sc = (void *)self;
    575 
    576 	printf(": %s\n", vs.color ? "color" : "mono");
    577 	do_async_update(1);
    578 
    579 	switch(cputype) {
    580 	case ACER_PICA_61:
    581 		BUS_INTR_ESTABLISH(ca, pcintr, (void *)(long)sc);
    582 		break;
    583 	case DESKSTATION_RPC44:                     /* XXX ick */
    584 	case DESKSTATION_TYNE:
    585 		isa_intr_establish(ia->ia_ic, ia->ia_irq, 1,
    586 			2, pcintr, sc);			/*XXX ick */
    587 		break;
    588 	}
    589 }
    590 
    591 int
    592 pcopen(dev, flag, mode, p)
    593 	dev_t dev;
    594 	int flag, mode;
    595 	struct proc *p;
    596 {
    597 	struct pc_softc *sc;
    598 	int unit = PCUNIT(dev);
    599 	struct tty *tp;
    600 
    601 	if (unit >= pc_cd.cd_ndevs)
    602 		return ENXIO;
    603 	sc = pc_cd.cd_devs[unit];
    604 	if (sc == 0)
    605 		return ENXIO;
    606 
    607 	if (!sc->sc_tty) {
    608 		tp = sc->sc_tty = ttymalloc();
    609 	}
    610 	else {
    611 		tp = sc->sc_tty;
    612 	}
    613 
    614 	tp->t_oproc = pcstart;
    615 	tp->t_param = pcparam;
    616 	tp->t_dev = dev;
    617 	if ((tp->t_state & TS_ISOPEN) == 0) {
    618 		ttychars(tp);
    619 		tp->t_iflag = TTYDEF_IFLAG;
    620 		tp->t_oflag = TTYDEF_OFLAG;
    621 		tp->t_cflag = TTYDEF_CFLAG;
    622 		tp->t_lflag = TTYDEF_LFLAG;
    623 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
    624 		pcparam(tp, &tp->t_termios);
    625 		ttsetwater(tp);
    626 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
    627 		return EBUSY;
    628 	tp->t_state |= TS_CARR_ON;
    629 
    630 	return ((*linesw[tp->t_line].l_open)(dev, tp));
    631 }
    632 
    633 int
    634 pcclose(dev, flag, mode, p)
    635 	dev_t dev;
    636 	int flag, mode;
    637 	struct proc *p;
    638 {
    639 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    640 	struct tty *tp = sc->sc_tty;
    641 
    642 	(*linesw[tp->t_line].l_close)(tp, flag);
    643 	ttyclose(tp);
    644 #ifdef notyet /* XXX */
    645 	ttyfree(tp);
    646 #endif
    647 	return(0);
    648 }
    649 
    650 int
    651 pcread(dev, uio, flag)
    652 	dev_t dev;
    653 	struct uio *uio;
    654 	int flag;
    655 {
    656 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    657 	struct tty *tp = sc->sc_tty;
    658 
    659 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
    660 }
    661 
    662 int
    663 pcwrite(dev, uio, flag)
    664 	dev_t dev;
    665 	struct uio *uio;
    666 	int flag;
    667 {
    668 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    669 	struct tty *tp = sc->sc_tty;
    670 
    671 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
    672 }
    673 
    674 struct tty *
    675 pctty(dev)
    676 	dev_t dev;
    677 {
    678 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    679 	struct tty *tp = sc->sc_tty;
    680 
    681 	return (tp);
    682 }
    683 
    684 /*
    685  * Got a console receive interrupt -
    686  * the console processor wants to give us a character.
    687  * Catch the character, and see who it goes to.
    688  */
    689 int
    690 pcintr(arg)
    691 	void *arg;
    692 {
    693 	struct pc_softc *sc = arg;
    694 	register struct tty *tp = sc->sc_tty;
    695 	u_char *cp;
    696 
    697 	if ((inb(kbd_cmdp) & 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 				(*linesw[tp->t_line].l_rint)(*cp++, tp);
    708 			while (*cp);
    709 	} while (inb(kbd_cmdp) & KBS_DIB);
    710 	return 1;
    711 }
    712 
    713 int
    714 pcioctl(dev, cmd, data, flag, p)
    715 	dev_t dev;
    716 	u_long cmd;
    717 	caddr_t data;
    718 	int flag;
    719 	struct proc *p;
    720 {
    721 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
    722 	struct tty *tp = sc->sc_tty;
    723 	int error;
    724 
    725 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
    726 	if (error >= 0)
    727 		return error;
    728 	error = ttioctl(tp, cmd, data, flag, p);
    729 	if (error >= 0)
    730 		return error;
    731 
    732 	switch (cmd) {
    733 	case CONSOLE_X_MODE_ON:
    734 		pc_xmode_on();
    735 		return 0;
    736 	case CONSOLE_X_MODE_OFF:
    737 		pc_xmode_off();
    738 		return 0;
    739 	case CONSOLE_X_BELL:
    740 		/*
    741 		 * If set, data is a pointer to a length 2 array of
    742 		 * integers.  data[0] is the pitch in Hz and data[1]
    743 		 * is the duration in msec.
    744 		 */
    745 		if (data)
    746 			sysbeep(((int*)data)[0],
    747 				(((int*)data)[1] * hz) / 1000);
    748 		else
    749 			sysbeep(BEEP_FREQ, BEEP_TIME);
    750 		return 0;
    751 	case CONSOLE_SET_TYPEMATIC_RATE: {
    752  		u_char	rate;
    753 
    754  		if (!data)
    755 			return EINVAL;
    756 		rate = *((u_char *)data);
    757 		/*
    758 		 * Check that it isn't too big (which would cause it to be
    759 		 * confused with a command).
    760 		 */
    761 		if (rate & 0x80)
    762 			return EINVAL;
    763 		typematic_rate = rate;
    764 		async_update();
    765 		return 0;
    766  	}
    767 	case CONSOLE_SET_KEYMAP: {
    768 		pccons_keymap_t *map = (pccons_keymap_t *) data;
    769 		int i;
    770 
    771 		if (!data)
    772 			return EINVAL;
    773 		for (i = 0; i < KB_NUM_KEYS; i++)
    774 			if (map[i].unshift[KB_CODE_SIZE-1] ||
    775 			    map[i].shift[KB_CODE_SIZE-1] ||
    776 			    map[i].ctl[KB_CODE_SIZE-1] ||
    777 			    map[i].altgr[KB_CODE_SIZE-1] ||
    778 			    map[i].shift_altgr[KB_CODE_SIZE-1])
    779 				return EINVAL;
    780 
    781 		bcopy(data, scan_codes, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
    782 		return 0;
    783 	}
    784 	case CONSOLE_GET_KEYMAP:
    785 		if (!data)
    786 			return EINVAL;
    787 		bcopy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
    788 		return 0;
    789 
    790 	default:
    791 		return ENOTTY;
    792 	}
    793 
    794 #ifdef DIAGNOSTIC
    795 	panic("pcioctl: impossible");
    796 #endif
    797 }
    798 
    799 void
    800 pcstart(tp)
    801 	struct tty *tp;
    802 {
    803 	struct clist *cl;
    804 	int s, len;
    805 	u_char buf[PCBURST];
    806 
    807 	s = spltty();
    808 	if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
    809 		goto out;
    810 	tp->t_state |= TS_BUSY;
    811 	splx(s);
    812 	/*
    813 	 * We need to do this outside spl since it could be fairly
    814 	 * expensive and we don't want our serial ports to overflow.
    815 	 */
    816 	cl = &tp->t_outq;
    817 	len = q_to_b(cl, buf, PCBURST);
    818 	sput(buf, len);
    819 	s = spltty();
    820 	tp->t_state &= ~TS_BUSY;
    821 	if (cl->c_cc) {
    822 		tp->t_state |= TS_TIMEOUT;
    823 		timeout(ttrstrt, tp, 1);
    824 	}
    825 	if (cl->c_cc <= tp->t_lowat) {
    826 		if (tp->t_state & TS_ASLEEP) {
    827 			tp->t_state &= ~TS_ASLEEP;
    828 			wakeup(cl);
    829 		}
    830 		selwakeup(&tp->t_wsel);
    831 	}
    832 out:
    833 	splx(s);
    834 }
    835 
    836 void
    837 pcstop(tp, flag)
    838 	struct tty *tp;
    839 	int flag;
    840 {
    841 }
    842 
    843 /* ARGSUSED */
    844 void
    845 pccnattach()
    846 {
    847 	int maj;
    848 	static struct consdev pccons = {
    849 		NULL, NULL, pccngetc, pccnputc, pccnpollc, NODEV, CN_NORMAL
    850 	};
    851 
    852 	/*
    853 	 * For now, don't screw with it.
    854 	 */
    855 	/* crtat = 0; */
    856 	switch(cputype) {
    857 
    858 	case ACER_PICA_61:
    859 		mono_base += PICA_V_LOCAL_VIDEO_CTRL;
    860 		mono_buf += PICA_V_LOCAL_VIDEO;
    861 		cga_base += PICA_V_LOCAL_VIDEO_CTRL;
    862 		cga_buf += PICA_V_LOCAL_VIDEO;
    863 		kbd_cmdp = PICA_SYS_KBD + 0x61;
    864 		kbd_datap = PICA_SYS_KBD + 0x60;
    865 		break;
    866 
    867 	case DESKSTATION_TYNE:
    868 		mono_base += arc_bus_io.bus_base;
    869 		mono_buf += arc_bus_mem.bus_base;
    870 		cga_base += arc_bus_io.bus_base;
    871 		cga_buf += arc_bus_mem.bus_base;
    872 		kbd_cmdp = arc_bus_io.bus_base + 0x64;
    873 		kbd_datap = arc_bus_io.bus_base + 0x60;
    874 		outb(arc_bus_io.bus_base + 0x3ce, 6);	/* Correct video mode */
    875 		outb(arc_bus_io.bus_base + 0x3cf,
    876 			inb(arc_bus_io.bus_base + 0x3cf) | 0xc);
    877 		kbc_put8042cmd(CMDBYTE);		/* Want XT codes.. */
    878 		break;
    879 
    880 	case DESKSTATION_RPC44:
    881 		mono_base += arc_bus_io.bus_base;
    882 		mono_buf += arc_bus_mem.bus_base;
    883 		cga_base += arc_bus_io.bus_base;
    884 		cga_buf = arc_bus_mem.bus_base + 0xa0000;
    885 		kbd_cmdp = arc_bus_io.bus_base + 0x64;
    886 		kbd_datap = arc_bus_io.bus_base + 0x60;
    887 		kbc_put8042cmd(CMDBYTE);		/* Want XT codes.. */
    888 		break;
    889 
    890 	case SNI_RM200:
    891 		mono_base += arc_bus_io.bus_base;
    892 		mono_buf += arc_bus_mem.bus_base;
    893 		cga_base += arc_bus_io.bus_base;
    894 		cga_buf += arc_bus_mem.bus_base;
    895 		kbd_cmdp = arc_bus_io.bus_base + 0x64;
    896 		kbd_datap = arc_bus_io.bus_base + 0x60;
    897 		break;
    898 	}
    899 
    900 	/* locate the major number */
    901 	for (maj = 0; maj < nchrdev; maj++)
    902 		if (cdevsw[maj].d_open == pcopen)
    903 			break;
    904 	pccons.cn_dev = makedev(maj, 0);
    905 
    906 	cn_tab = &pccons;
    907 }
    908 
    909 /* ARGSUSED */
    910 void
    911 pccnputc(dev, c)
    912 	dev_t dev;
    913 	int c;
    914 {
    915 	u_char cc, oldkernel = kernel;
    916 
    917 	kernel = 1;
    918 	if (c == '\n') {
    919 		sput("\r\n", 2);
    920 	} else {
    921 		cc = c;
    922 		sput(&cc, 1);
    923 	}
    924 	kernel = oldkernel;
    925 }
    926 
    927 /* ARGSUSED */
    928 int
    929 pccngetc(dev)
    930 	dev_t dev;
    931 {
    932 	register char *cp;
    933 
    934 	if (pc_xmode > 0)
    935 		return 0;
    936 
    937 	do {
    938 		/* wait for byte */
    939 		while ((inb(kbd_cmdp) & KBS_DIB) == 0);
    940 		/* see if it's worthwhile */
    941 		cp = sget();
    942 	} while (!cp);
    943 	if (*cp == '\r')
    944 		return '\n';
    945 	return *cp;
    946 }
    947 
    948 void
    949 pccnpollc(dev, on)
    950 	dev_t dev;
    951 	int on;
    952 {
    953 
    954 	polling = on;
    955 	if (!on) {
    956 		int unit;
    957 		struct pc_softc *sc;
    958 		int s;
    959 
    960 		/*
    961 		 * If disabling polling on a device that's been configured,
    962 		 * make sure there are no bytes left in the FIFO, holding up
    963 		 * the interrupt line.  Otherwise we won't get any further
    964 		 * interrupts.
    965 		 */
    966 		unit = PCUNIT(dev);
    967 		if (pc_cd.cd_ndevs > unit) {
    968 			sc = pc_cd.cd_devs[unit];
    969 			if (sc != 0) {
    970 				s = spltty();
    971 				pcintr(sc);
    972 				splx(s);
    973 			}
    974 		}
    975 	}
    976 }
    977 
    978 /*
    979  * Set line parameters.
    980  */
    981 int
    982 pcparam(tp, t)
    983 	struct tty *tp;
    984 	struct termios *t;
    985 {
    986 
    987 	tp->t_ispeed = t->c_ispeed;
    988 	tp->t_ospeed = t->c_ospeed;
    989 	tp->t_cflag = t->c_cflag;
    990 	return 0;
    991 }
    992 
    993 #define	wrtchar(c, at) do {\
    994 	char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; \
    995 } while (0)
    996 
    997 /* translate ANSI color codes to standard pc ones */
    998 static char fgansitopc[] = {
    999 	FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
   1000 	FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
   1001 };
   1002 
   1003 static char bgansitopc[] = {
   1004 	BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
   1005 	BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
   1006 };
   1007 
   1008 static u_char iso2ibm437[] =
   1009 {
   1010             0,     0,     0,     0,     0,     0,     0,     0,
   1011             0,     0,     0,     0,     0,     0,     0,     0,
   1012             0,     0,     0,     0,     0,     0,     0,     0,
   1013             0,     0,     0,     0,     0,     0,     0,     0,
   1014          0xff,  0xad,  0x9b,  0x9c,     0,  0x9d,     0,  0x40,
   1015          0x6f,  0x63,  0x61,  0xae,     0,     0,     0,     0,
   1016          0xf8,  0xf1,  0xfd,  0x33,     0,  0xe6,     0,  0xfa,
   1017             0,  0x31,  0x6f,  0xaf,  0xac,  0xab,     0,  0xa8,
   1018          0x41,  0x41,  0x41,  0x41,  0x8e,  0x8f,  0x92,  0x80,
   1019          0x45,  0x90,  0x45,  0x45,  0x49,  0x49,  0x49,  0x49,
   1020          0x81,  0xa5,  0x4f,  0x4f,  0x4f,  0x4f,  0x99,  0x4f,
   1021          0x4f,  0x55,  0x55,  0x55,  0x9a,  0x59,     0,  0xe1,
   1022          0x85,  0xa0,  0x83,  0x61,  0x84,  0x86,  0x91,  0x87,
   1023          0x8a,  0x82,  0x88,  0x89,  0x8d,  0xa1,  0x8c,  0x8b,
   1024             0,  0xa4,  0x95,  0xa2,  0x93,  0x6f,  0x94,  0x6f,
   1025          0x6f,  0x97,  0xa3,  0x96,  0x81,  0x98,     0,     0
   1026 };
   1027 
   1028 /*
   1029  * `pc3' termcap emulation.
   1030  */
   1031 void
   1032 sput(cp, n)
   1033 	u_char *cp;
   1034 	int n;
   1035 {
   1036 	u_char c, scroll = 0;
   1037 
   1038 	if (pc_xmode > 0)
   1039 		return;
   1040 
   1041 	if (crtat == 0) {
   1042 		volatile u_short *cp;
   1043 		u_short was;
   1044 		unsigned cursorat;
   1045 
   1046 		cp = (volatile u_short *)cga_buf;
   1047 		was = *cp;
   1048 		*cp = (volatile u_short) 0xA55A;
   1049 		if (*cp != 0xA55A) {
   1050 			cp = (volatile u_short *)mono_buf;
   1051 			addr_6845 = mono_base;
   1052 			vs.color = 0;
   1053 		} else {
   1054 			*cp = was;
   1055 			addr_6845 = cga_base;
   1056 			vs.color = 1;
   1057 		}
   1058 
   1059 #ifdef FAT_CURSOR
   1060 		cursor_shape = 0x0012;
   1061 #else
   1062 		get_cursor_shape();
   1063 #endif
   1064 
   1065 		bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow);
   1066 		vs.nchr = vs.ncol * vs.nrow;
   1067 		vs.col--;
   1068 		vs.row--;
   1069 		cursorat = vs.ncol * vs.row + vs.col;
   1070 		vs.at = FG_LIGHTGREY | BG_BLACK;
   1071 
   1072 		Crtat = (u_short *)cp;
   1073 		crtat = Crtat + cursorat;
   1074 
   1075 		if (vs.color == 0)
   1076 			vs.so_at = FG_BLACK | BG_LIGHTGREY;
   1077 		else
   1078 			vs.so_at = FG_YELLOW | BG_BLACK;
   1079 
   1080 		fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
   1081 	}
   1082 
   1083 	while (n--) {
   1084 		if (!(c = *cp++))
   1085 			continue;
   1086 
   1087 		switch (c) {
   1088 		case 0x1B:
   1089 			if (vs.state >= VSS_ESCAPE) {
   1090 				wrtchar(c, vs.so_at);
   1091 				vs.state = 0;
   1092 				goto maybe_scroll;
   1093 			} else
   1094 				vs.state = VSS_ESCAPE;
   1095 			break;
   1096 
   1097 		case 0x9B:	/* CSI */
   1098 			vs.cx = vs.cy = 0;
   1099 			vs.state = VSS_EBRACE;
   1100 			break;
   1101 
   1102 		case '\t': {
   1103 			int inccol = 8 - (vs.col & 7);
   1104 			crtat += inccol;
   1105 			vs.col += inccol;
   1106 		}
   1107 		maybe_scroll:
   1108 			if (vs.col >= vs.ncol) {
   1109 				vs.col -= vs.ncol;
   1110 				scroll = 1;
   1111 			}
   1112 			break;
   1113 
   1114 		case '\b':
   1115 			if (crtat <= Crtat)
   1116 				break;
   1117 			--crtat;
   1118 			if (--vs.col < 0)
   1119 				vs.col += vs.ncol;	/* non-destructive backspace */
   1120 			break;
   1121 
   1122 		case '\r':
   1123 			crtat -= vs.col;
   1124 			vs.col = 0;
   1125 			break;
   1126 
   1127 		case '\n':
   1128 			crtat += vs.ncol;
   1129 			scroll = 1;
   1130 			break;
   1131 
   1132 		default:
   1133 			switch (vs.state) {
   1134 			case 0:
   1135 				if (c == '\a')
   1136 					sysbeep(BEEP_FREQ, BEEP_TIME);
   1137 				else {
   1138 					/*
   1139 					 * If we're outputting multiple printed
   1140 					 * characters, just blast them to the
   1141 					 * screen until we reach the end of the
   1142 					 * buffer or a control character.  This
   1143 					 * saves time by short-circuiting the
   1144 					 * switch.
   1145 					 * If we reach the end of the line, we
   1146 					 * break to do a scroll check.
   1147 					 */
   1148 					for (;;) {
   1149 						if (c & 0x80)
   1150 							c = iso2ibm437[c&0x7f];
   1151 
   1152 						if (vs.so)
   1153 							wrtchar(c, vs.so_at);
   1154 						else
   1155 							wrtchar(c, vs.at);
   1156 						if (vs.col >= vs.ncol) {
   1157 							vs.col = 0;
   1158 							scroll = 1;
   1159 							break;
   1160 						}
   1161 						if (!n || (c = *cp) < ' ')
   1162 							break;
   1163 						n--, cp++;
   1164 					}
   1165 				}
   1166 				break;
   1167 			case VSS_ESCAPE:
   1168 				switch (c) {
   1169 					case '[': /* Start ESC [ sequence */
   1170 						vs.cx = vs.cy = 0;
   1171 						vs.state = VSS_EBRACE;
   1172 						break;
   1173 					case 'c': /* Create screen & home */
   1174 						fillw((vs.at << 8) | ' ',
   1175 						    Crtat, vs.nchr);
   1176 						crtat = Crtat;
   1177 						vs.col = 0;
   1178 						vs.state = 0;
   1179 						break;
   1180 					case '7': /* save cursor pos */
   1181 						vs.offset = crtat - Crtat;
   1182 						vs.state = 0;
   1183 						break;
   1184 					case '8': /* restore cursor pos */
   1185 						crtat = Crtat + vs.offset;
   1186 						vs.row = vs.offset / vs.ncol;
   1187 						vs.col = vs.offset % vs.ncol;
   1188 						vs.state = 0;
   1189 						break;
   1190 					default: /* Invalid, clear state */
   1191 						wrtchar(c, vs.so_at);
   1192 						vs.state = 0;
   1193 						goto maybe_scroll;
   1194 				}
   1195 				break;
   1196 
   1197 			default: /* VSS_EBRACE or VSS_EPARAM */
   1198 				switch (c) {
   1199 					int pos;
   1200 				case 'm':
   1201 					if (!vs.cx)
   1202 						vs.so = 0;
   1203 					else
   1204 						vs.so = 1;
   1205 					vs.state = 0;
   1206 					break;
   1207 				case 'A': { /* back cx rows */
   1208 					int cx = vs.cx;
   1209 					if (cx <= 0)
   1210 						cx = 1;
   1211 					else
   1212 						cx %= vs.nrow;
   1213 					pos = crtat - Crtat;
   1214 					pos -= vs.ncol * cx;
   1215 					if (pos < 0)
   1216 						pos += vs.nchr;
   1217 					crtat = Crtat + pos;
   1218 					vs.state = 0;
   1219 					break;
   1220 				}
   1221 				case 'B': { /* down cx rows */
   1222 					int cx = vs.cx;
   1223 					if (cx <= 0)
   1224 						cx = 1;
   1225 					else
   1226 						cx %= vs.nrow;
   1227 					pos = crtat - Crtat;
   1228 					pos += vs.ncol * cx;
   1229 					if (pos >= vs.nchr)
   1230 						pos -= vs.nchr;
   1231 					crtat = Crtat + pos;
   1232 					vs.state = 0;
   1233 					break;
   1234 				}
   1235 				case 'C': { /* right cursor */
   1236 					int cx = vs.cx,
   1237 					    col = vs.col;
   1238 					if (cx <= 0)
   1239 						cx = 1;
   1240 					else
   1241 						cx %= vs.ncol;
   1242 					pos = crtat - Crtat;
   1243 					pos += cx;
   1244 					col += cx;
   1245 					if (col >= vs.ncol) {
   1246 						pos -= vs.ncol;
   1247 						col -= vs.ncol;
   1248 					}
   1249 					vs.col = col;
   1250 					crtat = Crtat + pos;
   1251 					vs.state = 0;
   1252 					break;
   1253 				}
   1254 				case 'D': { /* left cursor */
   1255 					int cx = vs.cx,
   1256 					    col = vs.col;
   1257 					if (cx <= 0)
   1258 						cx = 1;
   1259 					else
   1260 						cx %= vs.ncol;
   1261 					pos = crtat - Crtat;
   1262 					pos -= cx;
   1263 					col -= cx;
   1264 					if (col < 0) {
   1265 						pos += vs.ncol;
   1266 						col += vs.ncol;
   1267 					}
   1268 					vs.col = col;
   1269 					crtat = Crtat + pos;
   1270 					vs.state = 0;
   1271 					break;
   1272 				}
   1273 				case 'J': /* Clear ... */
   1274 					switch (vs.cx) {
   1275 					case 0:
   1276 						/* ... to end of display */
   1277 						fillw((vs.at << 8) | ' ',
   1278 						    crtat,
   1279 						    Crtat + vs.nchr - crtat);
   1280 						break;
   1281 					case 1:
   1282 						/* ... to next location */
   1283 						fillw((vs.at << 8) | ' ',
   1284 						    Crtat,
   1285 						    crtat - Crtat + 1);
   1286 						break;
   1287 					case 2:
   1288 						/* ... whole display */
   1289 						fillw((vs.at << 8) | ' ',
   1290 						    Crtat,
   1291 						    vs.nchr);
   1292 						break;
   1293 					}
   1294 					vs.state = 0;
   1295 					break;
   1296 				case 'K': /* Clear line ... */
   1297 					switch (vs.cx) {
   1298 					case 0:
   1299 						/* ... current to EOL */
   1300 						fillw((vs.at << 8) | ' ',
   1301 						    crtat,
   1302 						    vs.ncol - vs.col);
   1303 						break;
   1304 					case 1:
   1305 						/* ... beginning to next */
   1306 						fillw((vs.at << 8) | ' ',
   1307 						    crtat - vs.col,
   1308 						    vs.col + 1);
   1309 						break;
   1310 					case 2:
   1311 						/* ... entire line */
   1312 						fillw((vs.at << 8) | ' ',
   1313 						    crtat - vs.col, vs.ncol);
   1314 						break;
   1315 					}
   1316 					vs.state = 0;
   1317 					break;
   1318 				case 'f': /* in system V consoles */
   1319 				case 'H': { /* Cursor move */
   1320 					int cx = vs.cx,
   1321 					    cy = vs.cy;
   1322 					if (!cx || !cy) {
   1323 						crtat = Crtat;
   1324 						vs.col = 0;
   1325 					} else {
   1326 						if (cx > vs.nrow)
   1327 							cx = vs.nrow;
   1328 						if (cy > vs.ncol)
   1329 							cy = vs.ncol;
   1330 						crtat = Crtat +
   1331 						    (cx - 1) * vs.ncol + cy - 1;
   1332 						vs.col = cy - 1;
   1333 					}
   1334 					vs.state = 0;
   1335 					break;
   1336 				}
   1337 				case 'M': { /* delete cx rows */
   1338 					u_short *crtAt = crtat - vs.col;
   1339 					int cx = vs.cx,
   1340 					    row = (crtAt - Crtat) / vs.ncol,
   1341 					    nrow = vs.nrow - row;
   1342 					if (cx <= 0)
   1343 						cx = 1;
   1344 					else if (cx > nrow)
   1345 						cx = nrow;
   1346 					if (cx < nrow)
   1347 #ifdef PCCONS_FORCE_WORD
   1348 						wcopy(crtAt + vs.ncol * cx,
   1349 						    crtAt, vs.ncol * (nrow -
   1350 						    cx) * CHR);
   1351 #else
   1352 						bcopy(crtAt + vs.ncol * cx,
   1353 						    crtAt, vs.ncol * (nrow -
   1354 						    cx) * CHR);
   1355 #endif
   1356 					fillw((vs.at << 8) | ' ',
   1357 					    crtAt + vs.ncol * (nrow - cx),
   1358 					    vs.ncol * cx);
   1359 					vs.state = 0;
   1360 					break;
   1361 				}
   1362 				case 'S': { /* scroll up cx lines */
   1363 					int cx = vs.cx;
   1364 					if (cx <= 0)
   1365 						cx = 1;
   1366 					else if (cx > vs.nrow)
   1367 						cx = vs.nrow;
   1368 					if (cx < vs.nrow)
   1369 #ifdef PCCONS_FORCE_WORD
   1370 						wcopy(Crtat + vs.ncol * cx,
   1371 						    Crtat, vs.ncol * (vs.nrow -
   1372 						    cx) * CHR);
   1373 #else
   1374 						bcopy(Crtat + vs.ncol * cx,
   1375 						    Crtat, vs.ncol * (vs.nrow -
   1376 						    cx) * CHR);
   1377 #endif
   1378 					fillw((vs.at << 8) | ' ',
   1379 					    Crtat + vs.ncol * (vs.nrow - cx),
   1380 					    vs.ncol * cx);
   1381 					/* crtat -= vs.ncol * cx; XXX */
   1382 					vs.state = 0;
   1383 					break;
   1384 				}
   1385 				case 'L': { /* insert cx rows */
   1386 					u_short *crtAt = crtat - vs.col;
   1387 					int cx = vs.cx,
   1388 					    row = (crtAt - Crtat) / vs.ncol,
   1389 					    nrow = vs.nrow - row;
   1390 					if (cx <= 0)
   1391 						cx = 1;
   1392 					else if (cx > nrow)
   1393 						cx = nrow;
   1394 					if (cx < nrow)
   1395 #ifdef PCCONS_FORCE_WORD
   1396 						wcopy(crtAt,
   1397 						    crtAt + vs.ncol * cx,
   1398 						    vs.ncol * (nrow - cx) *
   1399 						    CHR);
   1400 #else
   1401 						bcopy(crtAt,
   1402 						    crtAt + vs.ncol * cx,
   1403 						    vs.ncol * (nrow - cx) *
   1404 						    CHR);
   1405 #endif
   1406 					fillw((vs.at << 8) | ' ', crtAt,
   1407 					    vs.ncol * cx);
   1408 					vs.state = 0;
   1409 					break;
   1410 				}
   1411 				case 'T': { /* scroll down cx lines */
   1412 					int cx = vs.cx;
   1413 					if (cx <= 0)
   1414 						cx = 1;
   1415 					else if (cx > vs.nrow)
   1416 						cx = vs.nrow;
   1417 					if (cx < vs.nrow)
   1418 #ifdef PCCONS_FORCE_WORD
   1419 						wcopy(Crtat,
   1420 						    Crtat + vs.ncol * cx,
   1421 						    vs.ncol * (vs.nrow - cx) *
   1422 						    CHR);
   1423 #else
   1424 						bcopy(Crtat,
   1425 						    Crtat + vs.ncol * cx,
   1426 						    vs.ncol * (vs.nrow - cx) *
   1427 						    CHR);
   1428 #endif
   1429 					fillw((vs.at << 8) | ' ', Crtat,
   1430 					    vs.ncol * cx);
   1431 					/* crtat += vs.ncol * cx; XXX */
   1432 					vs.state = 0;
   1433 					break;
   1434 				}
   1435 				case ';': /* Switch params in cursor def */
   1436 					vs.state = VSS_EPARAM;
   1437 					break;
   1438 				case 'r':
   1439 					vs.so_at = (vs.cx & FG_MASK) |
   1440 					    ((vs.cy << 4) & BG_MASK);
   1441 					vs.state = 0;
   1442 					break;
   1443 				case 's': /* save cursor pos */
   1444 					vs.offset = crtat - Crtat;
   1445 					vs.state = 0;
   1446 					break;
   1447 				case 'u': /* restore cursor pos */
   1448 					crtat = Crtat + vs.offset;
   1449 					vs.row = vs.offset / vs.ncol;
   1450 					vs.col = vs.offset % vs.ncol;
   1451 					vs.state = 0;
   1452 					break;
   1453 				case 'x': /* set attributes */
   1454 					switch (vs.cx) {
   1455 					case 0:
   1456 						vs.at = FG_LIGHTGREY | BG_BLACK;
   1457 						break;
   1458 					case 1:
   1459 						/* ansi background */
   1460 						if (!vs.color)
   1461 							break;
   1462 						vs.at &= FG_MASK;
   1463 						vs.at |= bgansitopc[vs.cy & 7];
   1464 						break;
   1465 					case 2:
   1466 						/* ansi foreground */
   1467 						if (!vs.color)
   1468 							break;
   1469 						vs.at &= BG_MASK;
   1470 						vs.at |= fgansitopc[vs.cy & 7];
   1471 						break;
   1472 					case 3:
   1473 						/* pc text attribute */
   1474 						if (vs.state >= VSS_EPARAM)
   1475 							vs.at = vs.cy;
   1476 						break;
   1477 					}
   1478 					vs.state = 0;
   1479 					break;
   1480 
   1481 				default: /* Only numbers valid here */
   1482 					if ((c >= '0') && (c <= '9')) {
   1483 						if (vs.state >= VSS_EPARAM) {
   1484 							vs.cy *= 10;
   1485 							vs.cy += c - '0';
   1486 						} else {
   1487 							vs.cx *= 10;
   1488 							vs.cx += c - '0';
   1489 						}
   1490 					} else
   1491 						vs.state = 0;
   1492 					break;
   1493 				}
   1494 				break;
   1495 			}
   1496 		}
   1497 		if (scroll) {
   1498 			scroll = 0;
   1499 			/* scroll check */
   1500 			if (crtat >= Crtat + vs.nchr) {
   1501 				if (!kernel) {
   1502 					int s = spltty();
   1503 					if (lock_state & KB_SCROLL)
   1504 						tsleep(&lock_state,
   1505 						    PUSER, "pcputc", 0);
   1506 					splx(s);
   1507 				}
   1508 #if PCCONS_FORCE_WORD
   1509 				wcopy(Crtat + vs.ncol, Crtat,
   1510 				    (vs.nchr - vs.ncol) * CHR);
   1511 #else
   1512 				bcopy(Crtat + vs.ncol, Crtat,
   1513 				    (vs.nchr - vs.ncol) * CHR);
   1514 #endif
   1515 				fillw((vs.at << 8) | ' ',
   1516 				    Crtat + vs.nchr - vs.ncol,
   1517 				    vs.ncol);
   1518 				crtat -= vs.ncol;
   1519 			}
   1520 		}
   1521 	}
   1522 	async_update();
   1523 }
   1524 
   1525 /* the unshifted code for KB_SHIFT keys is used by X to distinguish between
   1526    left and right shift when reading the keyboard map */
   1527 static pccons_keymap_t	scan_codes[KB_NUM_KEYS] = {
   1528 /*  type       unshift   shift     control   altgr     shift_altgr scancode */
   1529   { KB_NONE,   "",       "",       "",       "",       ""}, /* 0 unused */
   1530   { KB_ASCII,  "\033",   "\033",   "\033",   "",       ""}, /* 1 ESCape */
   1531   { KB_ASCII,  "1",      "!",      "!",      "",       ""}, /* 2 1 */
   1532   { KB_ASCII,  "2",      "@",      "\000",   "",       ""}, /* 3 2 */
   1533   { KB_ASCII,  "3",      "#",      "#",      "",       ""}, /* 4 3 */
   1534   { KB_ASCII,  "4",      "$",      "$",      "",       ""}, /* 5 4 */
   1535   { KB_ASCII,  "5",      "%",      "%",      "",       ""}, /* 6 5 */
   1536   { KB_ASCII,  "6",      "^",      "\036",   "",       ""}, /* 7 6 */
   1537   { KB_ASCII,  "7",      "&",      "&",      "",       ""}, /* 8 7 */
   1538   { KB_ASCII,  "8",      "*",      "\010",   "",       ""}, /* 9 8 */
   1539   { KB_ASCII,  "9",      "(",      "(",      "",       ""}, /* 10 9 */
   1540   { KB_ASCII,  "0",      ")",      ")",      "",       ""}, /* 11 0 */
   1541   { KB_ASCII,  "-",      "_",      "\037",   "",       ""}, /* 12 - */
   1542   { KB_ASCII,  "=",      "+",      "+",      "",       ""}, /* 13 = */
   1543   { KB_ASCII,  "\177",   "\177",   "\010",   "",       ""}, /* 14 backspace */
   1544   { KB_ASCII,  "\t",     "\t",     "\t",     "",       ""}, /* 15 tab */
   1545   { KB_ASCII,  "q",      "Q",      "\021",   "",       ""}, /* 16 q */
   1546   { KB_ASCII,  "w",      "W",      "\027",   "",       ""}, /* 17 w */
   1547   { KB_ASCII,  "e",      "E",      "\005",   "",       ""}, /* 18 e */
   1548   { KB_ASCII,  "r",      "R",      "\022",   "",       ""}, /* 19 r */
   1549   { KB_ASCII,  "t",      "T",      "\024",   "",       ""}, /* 20 t */
   1550   { KB_ASCII,  "y",      "Y",      "\031",   "",       ""}, /* 21 y */
   1551   { KB_ASCII,  "u",      "U",      "\025",   "",       ""}, /* 22 u */
   1552   { KB_ASCII,  "i",      "I",      "\011",   "",       ""}, /* 23 i */
   1553   { KB_ASCII,  "o",      "O",      "\017",   "",       ""}, /* 24 o */
   1554   { KB_ASCII,  "p",      "P",      "\020",   "",       ""}, /* 25 p */
   1555   { KB_ASCII,  "[",      "{",      "\033",   "",       ""}, /* 26 [ */
   1556   { KB_ASCII,  "]",      "}",      "\035",   "",       ""}, /* 27 ] */
   1557   { KB_ASCII,  "\r",     "\r",     "\n",     "",       ""}, /* 28 return */
   1558   { KB_CTL,    "",       "",       "",       "",       ""}, /* 29 control */
   1559   { KB_ASCII,  "a",      "A",      "\001",   "",       ""}, /* 30 a */
   1560   { KB_ASCII,  "s",      "S",      "\023",   "",       ""}, /* 31 s */
   1561   { KB_ASCII,  "d",      "D",      "\004",   "",       ""}, /* 32 d */
   1562   { KB_ASCII,  "f",      "F",      "\006",   "",       ""}, /* 33 f */
   1563   { KB_ASCII,  "g",      "G",      "\007",   "",       ""}, /* 34 g */
   1564   { KB_ASCII,  "h",      "H",      "\010",   "",       ""}, /* 35 h */
   1565   { KB_ASCII,  "j",      "J",      "\n",     "",       ""}, /* 36 j */
   1566   { KB_ASCII,  "k",      "K",      "\013",   "",       ""}, /* 37 k */
   1567   { KB_ASCII,  "l",      "L",      "\014",   "",       ""}, /* 38 l */
   1568   { KB_ASCII,  ";",      ":",      ";",      "",       ""}, /* 39 ; */
   1569   { KB_ASCII,  "'",      "\"",     "'",      "",       ""}, /* 40 ' */
   1570   { KB_ASCII,  "`",      "~",      "`",      "",       ""}, /* 41 ` */
   1571   { KB_SHIFT,  "\001",   "",       "",       "",       ""}, /* 42 shift */
   1572   { KB_ASCII,  "\\",     "|",      "\034",   "",       ""}, /* 43 \ */
   1573   { KB_ASCII,  "z",      "Z",      "\032",   "",       ""}, /* 44 z */
   1574   { KB_ASCII,  "x",      "X",      "\030",   "",       ""}, /* 45 x */
   1575   { KB_ASCII,  "c",      "C",      "\003",   "",       ""}, /* 46 c */
   1576   { KB_ASCII,  "v",      "V",      "\026",   "",       ""}, /* 47 v */
   1577   { KB_ASCII,  "b",      "B",      "\002",   "",       ""}, /* 48 b */
   1578   { KB_ASCII,  "n",      "N",      "\016",   "",       ""}, /* 49 n */
   1579   { KB_ASCII,  "m",      "M",      "\r",     "",       ""}, /* 50 m */
   1580   { KB_ASCII,  ",",      "<",      "<",      "",       ""}, /* 51 , */
   1581   { KB_ASCII,  ".",      ">",      ">",      "",       ""}, /* 52 . */
   1582   { KB_ASCII,  "/",      "?",      "\037",   "",       ""}, /* 53 / */
   1583   { KB_SHIFT,  "\002",   "",       "",       "",       ""}, /* 54 shift */
   1584   { KB_KP,     "*",      "*",      "*",      "",       ""}, /* 55 kp * */
   1585   { KB_ALT,    "",       "",       "",       "",       ""}, /* 56 alt */
   1586   { KB_ASCII,  " ",      " ",      "\000",   "",       ""}, /* 57 space */
   1587   { KB_CAPS,   "",       "",       "",       "",       ""}, /* 58 caps */
   1588   { KB_FUNC,   "\033[M", "\033[Y", "\033[k", "",       ""}, /* 59 f1 */
   1589   { KB_FUNC,   "\033[N", "\033[Z", "\033[l", "",       ""}, /* 60 f2 */
   1590   { KB_FUNC,   "\033[O", "\033[a", "\033[m", "",       ""}, /* 61 f3 */
   1591   { KB_FUNC,   "\033[P", "\033[b", "\033[n", "",       ""}, /* 62 f4 */
   1592   { KB_FUNC,   "\033[Q", "\033[c", "\033[o", "",       ""}, /* 63 f5 */
   1593   { KB_FUNC,   "\033[R", "\033[d", "\033[p", "",       ""}, /* 64 f6 */
   1594   { KB_FUNC,   "\033[S", "\033[e", "\033[q", "",       ""}, /* 65 f7 */
   1595   { KB_FUNC,   "\033[T", "\033[f", "\033[r", "",       ""}, /* 66 f8 */
   1596   { KB_FUNC,   "\033[U", "\033[g", "\033[s", "",       ""}, /* 67 f9 */
   1597   { KB_FUNC,   "\033[V", "\033[h", "\033[t", "",       ""}, /* 68 f10 */
   1598   { KB_NUM,    "",       "",       "",       "",       ""}, /* 69 num lock */
   1599   { KB_SCROLL, "",       "",       "",       "",       ""}, /* 70 scroll lock */
   1600   { KB_KP,     "7",      "\033[H", "7",      "",       ""}, /* 71 kp 7 */
   1601   { KB_KP,     "8",      "\033[A", "8",      "",       ""}, /* 72 kp 8 */
   1602   { KB_KP,     "9",      "\033[I", "9",      "",       ""}, /* 73 kp 9 */
   1603   { KB_KP,     "-",      "-",      "-",      "",       ""}, /* 74 kp - */
   1604   { KB_KP,     "4",      "\033[D", "4",      "",       ""}, /* 75 kp 4 */
   1605   { KB_KP,     "5",      "\033[E", "5",      "",       ""}, /* 76 kp 5 */
   1606   { KB_KP,     "6",      "\033[C", "6",      "",       ""}, /* 77 kp 6 */
   1607   { KB_KP,     "+",      "+",      "+",      "",       ""}, /* 78 kp + */
   1608   { KB_KP,     "1",      "\033[F", "1",      "",       ""}, /* 79 kp 1 */
   1609   { KB_KP,     "2",      "\033[B", "2",      "",       ""}, /* 80 kp 2 */
   1610   { KB_KP,     "3",      "\033[G", "3",      "",       ""}, /* 81 kp 3 */
   1611   { KB_KP,     "0",      "\033[L", "0",      "",       ""}, /* 82 kp 0 */
   1612   { KB_KP,     ",",      "\177",   ",",      "",       ""}, /* 83 kp , */
   1613   { KB_NONE,   "",       "",       "",       "",       ""}, /* 84 0 */
   1614   { KB_NONE,   "",       "",       "",       "",       ""}, /* 85 0 */
   1615   { KB_NONE,   "",       "",       "",       "",       ""}, /* 86 0 */
   1616   { KB_FUNC,   "\033[W", "\033[i", "\033[u", "",       ""}, /* 87 f11 */
   1617   { KB_FUNC,   "\033[X", "\033[j", "\033[v", "",       ""}, /* 88 f12 */
   1618   { KB_NONE,   "",       "",       "",       "",       ""}, /* 89 0 */
   1619   { KB_NONE,   "",       "",       "",       "",       ""}, /* 90 0 */
   1620   { KB_NONE,   "",       "",       "",       "",       ""}, /* 91 0 */
   1621   { KB_NONE,   "",       "",       "",       "",       ""}, /* 92 0 */
   1622   { KB_NONE,   "",       "",       "",       "",       ""}, /* 93 0 */
   1623   { KB_NONE,   "",       "",       "",       "",       ""}, /* 94 0 */
   1624   { KB_NONE,   "",       "",       "",       "",       ""}, /* 95 0 */
   1625   { KB_NONE,   "",       "",       "",       "",       ""}, /* 96 0 */
   1626   { KB_NONE,   "",       "",       "",       "",       ""}, /* 97 0 */
   1627   { KB_NONE,   "",       "",       "",       "",       ""}, /* 98 0 */
   1628   { KB_NONE,   "",       "",       "",       "",       ""}, /* 99 0 */
   1629   { KB_NONE,   "",       "",       "",       "",       ""}, /* 100 */
   1630   { KB_NONE,   "",       "",       "",       "",       ""}, /* 101 */
   1631   { KB_NONE,   "",       "",       "",       "",       ""}, /* 102 */
   1632   { KB_NONE,   "",       "",       "",       "",       ""}, /* 103 */
   1633   { KB_NONE,   "",       "",       "",       "",       ""}, /* 104 */
   1634   { KB_NONE,   "",       "",       "",       "",       ""}, /* 105 */
   1635   { KB_NONE,   "",       "",       "",       "",       ""}, /* 106 */
   1636   { KB_NONE,   "",       "",       "",       "",       ""}, /* 107 */
   1637   { KB_NONE,   "",       "",       "",       "",       ""}, /* 108 */
   1638   { KB_NONE,   "",       "",       "",       "",       ""}, /* 109 */
   1639   { KB_NONE,   "",       "",       "",       "",       ""}, /* 110 */
   1640   { KB_NONE,   "",       "",       "",       "",       ""}, /* 111 */
   1641   { KB_NONE,   "",       "",       "",       "",       ""}, /* 112 */
   1642   { KB_NONE,   "",       "",       "",       "",       ""}, /* 113 */
   1643   { KB_NONE,   "",       "",       "",       "",       ""}, /* 114 */
   1644   { KB_NONE,   "",       "",       "",       "",       ""}, /* 115 */
   1645   { KB_NONE,   "",       "",       "",       "",       ""}, /* 116 */
   1646   { KB_NONE,   "",       "",       "",       "",       ""}, /* 117 */
   1647   { KB_NONE,   "",       "",       "",       "",       ""}, /* 118 */
   1648   { KB_NONE,   "",       "",       "",       "",       ""}, /* 119 */
   1649   { KB_NONE,   "",       "",       "",       "",       ""}, /* 120 */
   1650   { KB_NONE,   "",       "",       "",       "",       ""}, /* 121 */
   1651   { KB_NONE,   "",       "",       "",       "",       ""}, /* 122 */
   1652   { KB_NONE,   "",       "",       "",       "",       ""}, /* 123 */
   1653   { KB_NONE,   "",       "",       "",       "",       ""}, /* 124 */
   1654   { KB_NONE,   "",       "",       "",       "",       ""}, /* 125 */
   1655   { KB_NONE,   "",       "",       "",       "",       ""}, /* 126 */
   1656   { KB_NONE,   "",       "",       "",       "",       ""}  /* 127 */
   1657 };
   1658 
   1659 /*
   1660  * Get characters from the keyboard.  If none are present, return NULL.
   1661  */
   1662 char *
   1663 sget()
   1664 {
   1665 	u_char dt;
   1666 	static u_char extended = 0, shift_state = 0;
   1667 	static u_char capchar[2];
   1668 
   1669 top:
   1670 	KBD_DELAY;
   1671 	dt = inb(kbd_datap);
   1672 
   1673 	switch (dt) {
   1674 	case KBR_ACK: case KBR_ECHO:
   1675 		kb_oq_get = (kb_oq_get + 1) & 7;
   1676 		if(kb_oq_get != kb_oq_put) {
   1677 			outb(kbd_datap, kb_oq[kb_oq_get]);
   1678 		}
   1679 		goto loop;
   1680 	case KBR_RESEND:
   1681 		outb(kbd_datap, kb_oq[kb_oq_get]);
   1682 		goto loop;
   1683 	}
   1684 
   1685 	if (pc_xmode > 0) {
   1686 #if defined(DDB) && defined(XSERVER_DDB)
   1687 		/* F12 enters the debugger while in X mode */
   1688 		if (dt == 88)
   1689 			Debugger();
   1690 #endif
   1691 		capchar[0] = dt;
   1692 		capchar[1] = 0;
   1693 		/*
   1694 		 * Check for locking keys.
   1695 		 *
   1696 		 * XXX Setting the LEDs this way is a bit bogus.  What if the
   1697 		 * keyboard has been remapped in X?
   1698 		 */
   1699 		switch (scan_codes[dt & 0x7f].type) {
   1700 		case KB_NUM:
   1701 			if (dt & 0x80) {
   1702 				shift_state &= ~KB_NUM;
   1703 				break;
   1704 			}
   1705 			if (shift_state & KB_NUM)
   1706 				break;
   1707 			shift_state |= KB_NUM;
   1708 			lock_state ^= KB_NUM;
   1709 			async_update();
   1710 			break;
   1711 		case KB_CAPS:
   1712 			if (dt & 0x80) {
   1713 				shift_state &= ~KB_CAPS;
   1714 				break;
   1715 			}
   1716 			if (shift_state & KB_CAPS)
   1717 				break;
   1718 			shift_state |= KB_CAPS;
   1719 			lock_state ^= KB_CAPS;
   1720 			async_update();
   1721 			break;
   1722 		case KB_SCROLL:
   1723 			if (dt & 0x80) {
   1724 				shift_state &= ~KB_SCROLL;
   1725 				break;
   1726 			}
   1727 			if (shift_state & KB_SCROLL)
   1728 				break;
   1729 			shift_state |= KB_SCROLL;
   1730 			lock_state ^= KB_SCROLL;
   1731 			if ((lock_state & KB_SCROLL) == 0)
   1732 				wakeup((caddr_t)&lock_state);
   1733 			async_update();
   1734 			break;
   1735 		}
   1736 		return capchar;
   1737 	}
   1738 
   1739 	switch (dt) {
   1740 	case KBR_EXTENDED:
   1741 		extended = 1;
   1742 		goto loop;
   1743 	}
   1744 
   1745 #ifdef DDB
   1746 	/*
   1747 	 * Check for cntl-alt-esc.
   1748 	 */
   1749 	if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
   1750 		/* XXX - check pccons_is_console */
   1751 		Debugger();
   1752 		dt |= 0x80;	/* discard esc (ddb discarded ctl-alt) */
   1753 	}
   1754 #endif
   1755 
   1756 	/*
   1757 	 * Check for make/break.
   1758 	 */
   1759 	if (dt & 0x80) {
   1760 		/*
   1761 		 * break
   1762 		 */
   1763 		dt &= 0x7f;
   1764 		switch (scan_codes[dt].type) {
   1765 		case KB_NUM:
   1766 			shift_state &= ~KB_NUM;
   1767 			break;
   1768 		case KB_CAPS:
   1769 			shift_state &= ~KB_CAPS;
   1770 			break;
   1771 		case KB_SCROLL:
   1772 			shift_state &= ~KB_SCROLL;
   1773 			break;
   1774 		case KB_SHIFT:
   1775 			shift_state &= ~KB_SHIFT;
   1776 			break;
   1777 		case KB_ALT:
   1778 			if (extended)
   1779 				shift_state &= ~KB_ALTGR;
   1780 			else
   1781 				shift_state &= ~KB_ALT;
   1782 			break;
   1783 		case KB_CTL:
   1784 			shift_state &= ~KB_CTL;
   1785 			break;
   1786 		}
   1787 	} else {
   1788 		/*
   1789 		 * make
   1790 		 */
   1791 		switch (scan_codes[dt].type) {
   1792 		/*
   1793 		 * locking keys
   1794 		 */
   1795 		case KB_NUM:
   1796 			if (shift_state & KB_NUM)
   1797 				break;
   1798 			shift_state |= KB_NUM;
   1799 			lock_state ^= KB_NUM;
   1800 			async_update();
   1801 			break;
   1802 		case KB_CAPS:
   1803 			if (shift_state & KB_CAPS)
   1804 				break;
   1805 			shift_state |= KB_CAPS;
   1806 			lock_state ^= KB_CAPS;
   1807 			async_update();
   1808 			break;
   1809 		case KB_SCROLL:
   1810 			if (shift_state & KB_SCROLL)
   1811 				break;
   1812 			shift_state |= KB_SCROLL;
   1813 			lock_state ^= KB_SCROLL;
   1814 			if ((lock_state & KB_SCROLL) == 0)
   1815 				wakeup((caddr_t)&lock_state);
   1816 			async_update();
   1817 			break;
   1818 		/*
   1819 		 * non-locking keys
   1820 		 */
   1821 		case KB_SHIFT:
   1822 			shift_state |= KB_SHIFT;
   1823 			break;
   1824 		case KB_ALT:
   1825 			if (extended)
   1826 				shift_state |= KB_ALTGR;
   1827 			else
   1828 				shift_state |= KB_ALT;
   1829 			break;
   1830 		case KB_CTL:
   1831 			shift_state |= KB_CTL;
   1832 			break;
   1833 		case KB_ASCII:
   1834 			/* control has highest priority */
   1835 			if (shift_state & KB_CTL)
   1836 				capchar[0] = scan_codes[dt].ctl[0];
   1837 			else if (shift_state & KB_ALTGR) {
   1838 				if (shift_state & KB_SHIFT)
   1839 					capchar[0] = scan_codes[dt].shift_altgr[0];
   1840 				else
   1841 					capchar[0] = scan_codes[dt].altgr[0];
   1842 			}
   1843 			else {
   1844 				if (shift_state & KB_SHIFT)
   1845 					capchar[0] = scan_codes[dt].shift[0];
   1846 				else
   1847 					capchar[0] = scan_codes[dt].unshift[0];
   1848 			}
   1849 			if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
   1850 			    capchar[0] <= 'z') {
   1851 				capchar[0] -= ('a' - 'A');
   1852 			}
   1853 			capchar[0] |= (shift_state & KB_ALT);
   1854 			extended = 0;
   1855 			return capchar;
   1856 		case KB_NONE:
   1857 printf("keycode %d\n",dt);
   1858 			break;
   1859 		case KB_FUNC: {
   1860 			char *more_chars;
   1861 			if (shift_state & KB_SHIFT)
   1862 				more_chars = scan_codes[dt].shift;
   1863 			else if (shift_state & KB_CTL)
   1864 				more_chars = scan_codes[dt].ctl;
   1865 			else
   1866 				more_chars = scan_codes[dt].unshift;
   1867 			extended = 0;
   1868 			return more_chars;
   1869 		}
   1870 		case KB_KP: {
   1871 			char *more_chars;
   1872 			if (shift_state & (KB_SHIFT | KB_CTL) ||
   1873 			    (lock_state & KB_NUM) == 0 || extended)
   1874 				more_chars = scan_codes[dt].shift;
   1875 			else
   1876 				more_chars = scan_codes[dt].unshift;
   1877 			extended = 0;
   1878 			return more_chars;
   1879 		}
   1880 		}
   1881 	}
   1882 
   1883 	extended = 0;
   1884 loop:
   1885 	if ((inb(kbd_cmdp) & KBS_DIB) == 0)
   1886 		return 0;
   1887 	goto top;
   1888 }
   1889 
   1890 int
   1891 pcmmap(dev, offset, nprot)
   1892 	dev_t dev;
   1893 	int offset;
   1894 	int nprot;
   1895 {
   1896 
   1897 	switch(cputype) {
   1898 
   1899 	case ACER_PICA_61:
   1900 		if (offset >= 0xa0000 && offset < 0xc0000)
   1901 			return mips_btop(PICA_P_LOCAL_VIDEO + offset);
   1902 		if (offset >= 0x0000 && offset < 0x10000)
   1903 			return mips_btop(PICA_P_LOCAL_VIDEO_CTRL + offset);
   1904 		if (offset >= 0x40000000 && offset < 0x40800000)
   1905 			return mips_btop(PICA_P_LOCAL_VIDEO + offset - 0x40000000);
   1906 		return -1;
   1907 
   1908 	case DESKSTATION_RPC44:
   1909 		if (offset >= 0xa0000 && offset < 0xc0000)
   1910 			return mips_btop(RPC44_P_ISA_MEM + offset);
   1911 		if (offset >= 0x0000 && offset < 0x10000)
   1912 			return mips_btop(RPC44_P_ISA_IO + offset);
   1913 		if (offset >= 0x40000000 && offset < 0x40800000)
   1914 			return mips_btop(RPC44_P_ISA_MEM + offset - 0x40000000);
   1915 		return -1;
   1916 
   1917 	case DESKSTATION_TYNE:
   1918 		/* Addresses returned are a fake to be able to handle >32 bit
   1919 		 * physical addresses used by the tyne. The real physical adr
   1920 		 * processing is done in pmap.c. Until we are a real 64 bit
   1921 		 * port this is how it will be done.
   1922 		 */
   1923 		/* XXX - the above is not supported merged pmap, yet */
   1924 		if (offset >= 0xa0000 && offset < 0xc0000)
   1925 			return mips_btop(TYNE_V_ISA_MEM + offset);
   1926 		if (offset >= 0x0000 && offset < 0x10000)
   1927 			return mips_btop(TYNE_V_ISA_IO + offset);
   1928 		if (offset >= 0x40000000 && offset < 0x40800000)
   1929 			return mips_btop(TYNE_V_ISA_MEM + offset - 0x40000000);
   1930 		return -1;
   1931 	}
   1932 	return -1;
   1933 }
   1934 
   1935 void
   1936 pc_xmode_on()
   1937 {
   1938 	if (pc_xmode)
   1939 		return;
   1940 	pc_xmode = 1;
   1941 
   1942 #ifdef XFREE86_BUG_COMPAT
   1943 	/* If still unchanged, get current shape. */
   1944 	if (cursor_shape == 0xffff)
   1945 		get_cursor_shape();
   1946 #endif
   1947 }
   1948 
   1949 void
   1950 pc_xmode_off()
   1951 {
   1952 	if (pc_xmode == 0)
   1953 		return;
   1954 	pc_xmode = 0;
   1955 
   1956 #ifdef XFREE86_BUG_COMPAT
   1957 	/* XXX It would be hard to justify why the X server doesn't do this. */
   1958 	set_cursor_shape();
   1959 #endif
   1960 	async_update();
   1961 }
   1962 
   1963 #include <machine/mouse.h>
   1964 
   1965 /* status bits */
   1966 #define	PMS_OBUF_FULL	0x01
   1967 #define	PMS_IBUF_FULL	0x02
   1968 
   1969 /* controller commands */
   1970 #define	PMS_INT_ENABLE	0x47	/* enable controller interrupts */
   1971 #define	PMS_INT_DISABLE	0x65	/* disable controller interrupts */
   1972 #define	PMS_AUX_ENABLE	0xa7	/* enable auxiliary port */
   1973 #define	PMS_AUX_DISABLE	0xa8	/* disable auxiliary port */
   1974 #define	PMS_MAGIC_1	0xa9	/* XXX */
   1975 
   1976 #define	PMS_8042_CMD	0x65
   1977 
   1978 /* mouse commands */
   1979 #define	PMS_SET_SCALE11	0xe6	/* set scaling 1:1 */
   1980 #define	PMS_SET_SCALE21 0xe7	/* set scaling 2:1 */
   1981 #define	PMS_SET_RES	0xe8	/* set resolution */
   1982 #define	PMS_GET_SCALE	0xe9	/* get scaling factor */
   1983 #define	PMS_SET_STREAM	0xea	/* set streaming mode */
   1984 #define	PMS_SET_SAMPLE	0xf3	/* set sampling rate */
   1985 #define	PMS_DEV_ENABLE	0xf4	/* mouse on */
   1986 #define	PMS_DEV_DISABLE	0xf5	/* mouse off */
   1987 #define	PMS_RESET	0xff	/* reset */
   1988 
   1989 #define	PMS_CHUNK	128	/* chunk size for read */
   1990 #define	PMS_BSIZE	1020	/* buffer size */
   1991 
   1992 #define	FLUSHQ(q) { if((q)->c_cc) ndflush(q, (q)->c_cc); }
   1993 
   1994 int opmsopen __P((dev_t, int));
   1995 int opmsclose __P((dev_t, int));
   1996 int opmsread __P((dev_t, struct uio *, int));
   1997 int opmsioctl __P((dev_t, u_long, caddr_t, int));
   1998 int opmsselect __P((dev_t, int, struct proc *));
   1999 int opmspoll __P((dev_t, int, struct proc *));
   2000 static __inline void pms_dev_cmd __P((u_char));
   2001 static __inline void pms_aux_cmd __P((u_char));
   2002 static __inline void pms_pit_cmd __P((u_char));
   2003 
   2004 static __inline void
   2005 pms_dev_cmd(value)
   2006 	u_char value;
   2007 {
   2008 	kbd_flush_input();
   2009 	outb(kbd_cmdp, 0xd4);
   2010 	kbd_flush_input();
   2011 	outb(kbd_datap, value);
   2012 }
   2013 
   2014 static __inline void
   2015 pms_aux_cmd(value)
   2016 	u_char value;
   2017 {
   2018 	kbd_flush_input();
   2019 	outb(kbd_cmdp, value);
   2020 }
   2021 
   2022 static __inline void
   2023 pms_pit_cmd(value)
   2024 	u_char value;
   2025 {
   2026 	kbd_flush_input();
   2027 	outb(kbd_cmdp, 0x60);
   2028 	kbd_flush_input();
   2029 	outb(kbd_datap, value);
   2030 }
   2031 
   2032 int
   2033 opmsprobe(parent, match, aux)
   2034 	struct device *parent;
   2035 	struct cfdata *match;
   2036 	void *aux;
   2037 {
   2038 	struct confargs *ca = aux;
   2039 	u_char x;
   2040 
   2041 	/* Make shure we're looking for this type of device */
   2042 	if(!BUS_MATCHNAME(ca, "pms"))
   2043 		return(0);
   2044 
   2045 	pms_dev_cmd(KBC_RESET);
   2046 	pms_aux_cmd(PMS_MAGIC_1);
   2047 	delay(10000);
   2048 	x = inb(kbd_datap);
   2049 	pms_pit_cmd(PMS_INT_DISABLE);
   2050 	if (x & 0x04)
   2051 		return 0;
   2052 
   2053 	return 1;
   2054 }
   2055 
   2056 void
   2057 opmsattach(parent, self, aux)
   2058 	struct device *parent, *self;
   2059 	void *aux;
   2060 {
   2061 	struct opms_softc *sc = (void *)self;
   2062 	struct confargs *ca = aux;
   2063 
   2064 	printf("\n");
   2065 
   2066 	/* Other initialization was done by opmsprobe. */
   2067 	sc->sc_state = 0;
   2068 
   2069 	BUS_INTR_ESTABLISH(ca, opmsintr, (void *)(long)sc);
   2070 }
   2071 
   2072 int
   2073 opmsopen(dev, flag)
   2074 	dev_t dev;
   2075 	int flag;
   2076 {
   2077 	int unit = PMSUNIT(dev);
   2078 	struct opms_softc *sc;
   2079 
   2080 	if (unit >= opms_cd.cd_ndevs)
   2081 		return ENXIO;
   2082 	sc = opms_cd.cd_devs[unit];
   2083 	if (!sc)
   2084 		return ENXIO;
   2085 
   2086 	if (sc->sc_state & PMS_OPEN)
   2087 		return EBUSY;
   2088 
   2089 	if (clalloc(&sc->sc_q, PMS_BSIZE, 0) == -1)
   2090 		return ENOMEM;
   2091 
   2092 	sc->sc_state |= PMS_OPEN;
   2093 	sc->sc_status = 0;
   2094 	sc->sc_x = sc->sc_y = 0;
   2095 
   2096 	/* Enable interrupts. */
   2097 	pms_dev_cmd(PMS_DEV_ENABLE);
   2098 	pms_aux_cmd(PMS_AUX_ENABLE);
   2099 	pms_dev_cmd(PMS_SET_RES);
   2100 	pms_dev_cmd(3);		/* 8 counts/mm */
   2101 	pms_dev_cmd(PMS_SET_SCALE21);
   2102 #if 0
   2103 	pms_dev_cmd(PMS_SET_SAMPLE);
   2104 	pms_dev_cmd(100);	/* 100 samples/sec */
   2105 	pms_dev_cmd(PMS_SET_STREAM);
   2106 #endif
   2107 	pms_pit_cmd(PMS_INT_ENABLE);
   2108 
   2109 	return 0;
   2110 }
   2111 
   2112 int
   2113 opmsclose(dev, flag)
   2114 	dev_t dev;
   2115 	int flag;
   2116 {
   2117 	struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
   2118 
   2119 	/* Disable interrupts. */
   2120 	pms_dev_cmd(PMS_DEV_DISABLE);
   2121 	pms_pit_cmd(PMS_INT_DISABLE);
   2122 	pms_aux_cmd(PMS_AUX_DISABLE);
   2123 
   2124 	sc->sc_state &= ~PMS_OPEN;
   2125 
   2126 	clfree(&sc->sc_q);
   2127 
   2128 	return 0;
   2129 }
   2130 
   2131 int
   2132 opmsread(dev, uio, flag)
   2133 	dev_t dev;
   2134 	struct uio *uio;
   2135 	int flag;
   2136 {
   2137 	struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
   2138 	int s;
   2139 	int error = 0;
   2140 	size_t length;
   2141 	u_char buffer[PMS_CHUNK];
   2142 
   2143 	/* Block until mouse activity occured. */
   2144 
   2145 	s = spltty();
   2146 	while (sc->sc_q.c_cc == 0) {
   2147 		if (flag & IO_NDELAY) {
   2148 			splx(s);
   2149 			return EWOULDBLOCK;
   2150 		}
   2151 		sc->sc_state |= PMS_ASLP;
   2152 		error = tsleep((caddr_t)sc, PZERO | PCATCH, "pmsrea", 0);
   2153 		if (error) {
   2154 			sc->sc_state &= ~PMS_ASLP;
   2155 			splx(s);
   2156 			return error;
   2157 		}
   2158 	}
   2159 	splx(s);
   2160 
   2161 	/* Transfer as many chunks as possible. */
   2162 
   2163 	while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
   2164 		length = min(sc->sc_q.c_cc, uio->uio_resid);
   2165 		if (length > sizeof(buffer))
   2166 			length = sizeof(buffer);
   2167 
   2168 		/* Remove a small chunk from the input queue. */
   2169 		(void) q_to_b(&sc->sc_q, buffer, length);
   2170 
   2171 		/* Copy the data to the user process. */
   2172 		error = uiomove(buffer, length, uio);
   2173 		if (error)
   2174 			break;
   2175 	}
   2176 
   2177 	return error;
   2178 }
   2179 
   2180 int
   2181 opmsioctl(dev, cmd, addr, flag)
   2182 	dev_t dev;
   2183 	u_long cmd;
   2184 	caddr_t addr;
   2185 	int flag;
   2186 {
   2187 	struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
   2188 	struct mouseinfo info;
   2189 	int s;
   2190 	int error;
   2191 
   2192 	switch (cmd) {
   2193 	case MOUSEIOCREAD:
   2194 		s = spltty();
   2195 
   2196 		info.status = sc->sc_status;
   2197 		if (sc->sc_x || sc->sc_y)
   2198 			info.status |= MOVEMENT;
   2199 
   2200 		if (sc->sc_x > 127)
   2201 			info.xmotion = 127;
   2202 		else if (sc->sc_x < -127)
   2203 			/* Bounding at -127 avoids a bug in XFree86. */
   2204 			info.xmotion = -127;
   2205 		else
   2206 			info.xmotion = sc->sc_x;
   2207 
   2208 		if (sc->sc_y > 127)
   2209 			info.ymotion = 127;
   2210 		else if (sc->sc_y < -127)
   2211 			info.ymotion = -127;
   2212 		else
   2213 			info.ymotion = sc->sc_y;
   2214 
   2215 		/* Reset historical information. */
   2216 		sc->sc_x = sc->sc_y = 0;
   2217 		sc->sc_status &= ~BUTCHNGMASK;
   2218 		ndflush(&sc->sc_q, sc->sc_q.c_cc);
   2219 
   2220 		splx(s);
   2221 		error = copyout(&info, addr, sizeof(struct mouseinfo));
   2222 		break;
   2223 	default:
   2224 		error = EINVAL;
   2225 		break;
   2226 	}
   2227 
   2228 	return error;
   2229 }
   2230 
   2231 /* Masks for the first byte of a packet */
   2232 #define PS2LBUTMASK 0x01
   2233 #define PS2RBUTMASK 0x02
   2234 #define PS2MBUTMASK 0x04
   2235 
   2236 int
   2237 opmsintr(arg)
   2238 	void *arg;
   2239 {
   2240 	struct opms_softc *sc = arg;
   2241 	static int state = 0;
   2242 	static u_char buttons;
   2243 	u_char changed;
   2244 	static char dx, dy;
   2245 	u_char buffer[5];
   2246 
   2247 	if ((sc->sc_state & PMS_OPEN) == 0) {
   2248 		/* Interrupts are not expected.  Discard the byte. */
   2249 		kbd_flush_input();
   2250 		return 0;
   2251 	}
   2252 
   2253 	switch (state) {
   2254 
   2255 	case 0:
   2256 		buttons = inb(kbd_datap);
   2257 		if ((buttons & 0xc0) == 0)
   2258 			++state;
   2259 		break;
   2260 
   2261 	case 1:
   2262 		dx = inb(kbd_datap);
   2263 		/* Bounding at -127 avoids a bug in XFree86. */
   2264 		dx = (dx == -128) ? -127 : dx;
   2265 		++state;
   2266 		break;
   2267 
   2268 	case 2:
   2269 		dy = inb(kbd_datap);
   2270 		dy = (dy == -128) ? -127 : dy;
   2271 		state = 0;
   2272 
   2273 		buttons = ((buttons & PS2LBUTMASK) << 2) |
   2274 			  ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1);
   2275 		changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3;
   2276 		sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) | changed;
   2277 
   2278 		if (dx || dy || changed) {
   2279 			/* Update accumulated movements. */
   2280 			sc->sc_x += dx;
   2281 			sc->sc_y += dy;
   2282 
   2283 			/* Add this event to the queue. */
   2284 			buffer[0] = 0x80 | (buttons & BUTSTATMASK);
   2285 			if(dx < 0)
   2286 				buffer[0] |= 0x10;
   2287 			buffer[1] = dx & 0x7f;
   2288 			if(dy < 0)
   2289 				buffer[0] |= 0x20;
   2290 			buffer[2] = dy & 0x7f;
   2291 			buffer[3] = buffer[4] = 0;
   2292 			(void) b_to_q(buffer, sizeof buffer, &sc->sc_q);
   2293 
   2294 			if (sc->sc_state & PMS_ASLP) {
   2295 				sc->sc_state &= ~PMS_ASLP;
   2296 				wakeup((caddr_t)sc);
   2297 			}
   2298 			selwakeup(&sc->sc_rsel);
   2299 		}
   2300 
   2301 		break;
   2302 	}
   2303 	return -1;
   2304 }
   2305 
   2306 int
   2307 opmspoll(dev, events, p)
   2308 	dev_t dev;
   2309 	int events;
   2310 	struct proc *p;
   2311 {
   2312 	struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
   2313 	int revents = 0;
   2314 	int s = spltty();
   2315 
   2316 	if (events & (POLLIN | POLLRDNORM))
   2317 		if (sc->sc_q.c_cc > 0)
   2318 			revents |= events & (POLLIN | POLLRDNORM);
   2319 		else
   2320 			selrecord(p, &sc->sc_rsel);
   2321 
   2322 	splx(s);
   2323 	return (revents);
   2324 }
   2325