Home | History | Annotate | Line # | Download | only in dev
pccons.c revision 1.16
      1 /*	$NetBSD: pccons.c,v 1.16 2000/03/06 21:36:06 thorpej 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, NULL,
    850 		    NODEV, CN_NORMAL
    851 	};
    852 
    853 	/*
    854 	 * For now, don't screw with it.
    855 	 */
    856 	/* crtat = 0; */
    857 	switch(cputype) {
    858 
    859 	case ACER_PICA_61:
    860 		mono_base += PICA_V_LOCAL_VIDEO_CTRL;
    861 		mono_buf += PICA_V_LOCAL_VIDEO;
    862 		cga_base += PICA_V_LOCAL_VIDEO_CTRL;
    863 		cga_buf += PICA_V_LOCAL_VIDEO;
    864 		kbd_cmdp = PICA_SYS_KBD + 0x61;
    865 		kbd_datap = PICA_SYS_KBD + 0x60;
    866 		break;
    867 
    868 	case DESKSTATION_TYNE:
    869 		mono_base += arc_bus_io.bus_base;
    870 		mono_buf += arc_bus_mem.bus_base;
    871 		cga_base += arc_bus_io.bus_base;
    872 		cga_buf += arc_bus_mem.bus_base;
    873 		kbd_cmdp = arc_bus_io.bus_base + 0x64;
    874 		kbd_datap = arc_bus_io.bus_base + 0x60;
    875 		outb(arc_bus_io.bus_base + 0x3ce, 6);	/* Correct video mode */
    876 		outb(arc_bus_io.bus_base + 0x3cf,
    877 			inb(arc_bus_io.bus_base + 0x3cf) | 0xc);
    878 		kbc_put8042cmd(CMDBYTE);		/* Want XT codes.. */
    879 		break;
    880 
    881 	case DESKSTATION_RPC44:
    882 		mono_base += arc_bus_io.bus_base;
    883 		mono_buf += arc_bus_mem.bus_base;
    884 		cga_base += arc_bus_io.bus_base;
    885 		cga_buf = arc_bus_mem.bus_base + 0xa0000;
    886 		kbd_cmdp = arc_bus_io.bus_base + 0x64;
    887 		kbd_datap = arc_bus_io.bus_base + 0x60;
    888 		kbc_put8042cmd(CMDBYTE);		/* Want XT codes.. */
    889 		break;
    890 
    891 	case SNI_RM200:
    892 		mono_base += arc_bus_io.bus_base;
    893 		mono_buf += arc_bus_mem.bus_base;
    894 		cga_base += arc_bus_io.bus_base;
    895 		cga_buf += arc_bus_mem.bus_base;
    896 		kbd_cmdp = arc_bus_io.bus_base + 0x64;
    897 		kbd_datap = arc_bus_io.bus_base + 0x60;
    898 		break;
    899 	}
    900 
    901 	/* locate the major number */
    902 	for (maj = 0; maj < nchrdev; maj++)
    903 		if (cdevsw[maj].d_open == pcopen)
    904 			break;
    905 	pccons.cn_dev = makedev(maj, 0);
    906 
    907 	cn_tab = &pccons;
    908 }
    909 
    910 /* ARGSUSED */
    911 void
    912 pccnputc(dev, c)
    913 	dev_t dev;
    914 	int c;
    915 {
    916 	u_char cc, oldkernel = kernel;
    917 
    918 	kernel = 1;
    919 	if (c == '\n') {
    920 		sput("\r\n", 2);
    921 	} else {
    922 		cc = c;
    923 		sput(&cc, 1);
    924 	}
    925 	kernel = oldkernel;
    926 }
    927 
    928 /* ARGSUSED */
    929 int
    930 pccngetc(dev)
    931 	dev_t dev;
    932 {
    933 	register char *cp;
    934 
    935 	if (pc_xmode > 0)
    936 		return 0;
    937 
    938 	do {
    939 		/* wait for byte */
    940 		while ((inb(kbd_cmdp) & KBS_DIB) == 0);
    941 		/* see if it's worthwhile */
    942 		cp = sget();
    943 	} while (!cp);
    944 	if (*cp == '\r')
    945 		return '\n';
    946 	return *cp;
    947 }
    948 
    949 void
    950 pccnpollc(dev, on)
    951 	dev_t dev;
    952 	int on;
    953 {
    954 
    955 	polling = on;
    956 	if (!on) {
    957 		int unit;
    958 		struct pc_softc *sc;
    959 		int s;
    960 
    961 		/*
    962 		 * If disabling polling on a device that's been configured,
    963 		 * make sure there are no bytes left in the FIFO, holding up
    964 		 * the interrupt line.  Otherwise we won't get any further
    965 		 * interrupts.
    966 		 */
    967 		unit = PCUNIT(dev);
    968 		if (pc_cd.cd_ndevs > unit) {
    969 			sc = pc_cd.cd_devs[unit];
    970 			if (sc != 0) {
    971 				s = spltty();
    972 				pcintr(sc);
    973 				splx(s);
    974 			}
    975 		}
    976 	}
    977 }
    978 
    979 /*
    980  * Set line parameters.
    981  */
    982 int
    983 pcparam(tp, t)
    984 	struct tty *tp;
    985 	struct termios *t;
    986 {
    987 
    988 	tp->t_ispeed = t->c_ispeed;
    989 	tp->t_ospeed = t->c_ospeed;
    990 	tp->t_cflag = t->c_cflag;
    991 	return 0;
    992 }
    993 
    994 #define	wrtchar(c, at) do {\
    995 	char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; \
    996 } while (0)
    997 
    998 /* translate ANSI color codes to standard pc ones */
    999 static char fgansitopc[] = {
   1000 	FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
   1001 	FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
   1002 };
   1003 
   1004 static char bgansitopc[] = {
   1005 	BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
   1006 	BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
   1007 };
   1008 
   1009 static u_char iso2ibm437[] =
   1010 {
   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             0,     0,     0,     0,     0,     0,     0,     0,
   1015          0xff,  0xad,  0x9b,  0x9c,     0,  0x9d,     0,  0x40,
   1016          0x6f,  0x63,  0x61,  0xae,     0,     0,     0,     0,
   1017          0xf8,  0xf1,  0xfd,  0x33,     0,  0xe6,     0,  0xfa,
   1018             0,  0x31,  0x6f,  0xaf,  0xac,  0xab,     0,  0xa8,
   1019          0x41,  0x41,  0x41,  0x41,  0x8e,  0x8f,  0x92,  0x80,
   1020          0x45,  0x90,  0x45,  0x45,  0x49,  0x49,  0x49,  0x49,
   1021          0x81,  0xa5,  0x4f,  0x4f,  0x4f,  0x4f,  0x99,  0x4f,
   1022          0x4f,  0x55,  0x55,  0x55,  0x9a,  0x59,     0,  0xe1,
   1023          0x85,  0xa0,  0x83,  0x61,  0x84,  0x86,  0x91,  0x87,
   1024          0x8a,  0x82,  0x88,  0x89,  0x8d,  0xa1,  0x8c,  0x8b,
   1025             0,  0xa4,  0x95,  0xa2,  0x93,  0x6f,  0x94,  0x6f,
   1026          0x6f,  0x97,  0xa3,  0x96,  0x81,  0x98,     0,     0
   1027 };
   1028 
   1029 /*
   1030  * `pc3' termcap emulation.
   1031  */
   1032 void
   1033 sput(cp, n)
   1034 	u_char *cp;
   1035 	int n;
   1036 {
   1037 	u_char c, scroll = 0;
   1038 
   1039 	if (pc_xmode > 0)
   1040 		return;
   1041 
   1042 	if (crtat == 0) {
   1043 		volatile u_short *cp;
   1044 		u_short was;
   1045 		unsigned cursorat;
   1046 
   1047 		cp = (volatile u_short *)cga_buf;
   1048 		was = *cp;
   1049 		*cp = (volatile u_short) 0xA55A;
   1050 		if (*cp != 0xA55A) {
   1051 			cp = (volatile u_short *)mono_buf;
   1052 			addr_6845 = mono_base;
   1053 			vs.color = 0;
   1054 		} else {
   1055 			*cp = was;
   1056 			addr_6845 = cga_base;
   1057 			vs.color = 1;
   1058 		}
   1059 
   1060 #ifdef FAT_CURSOR
   1061 		cursor_shape = 0x0012;
   1062 #else
   1063 		get_cursor_shape();
   1064 #endif
   1065 
   1066 		bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow);
   1067 		vs.nchr = vs.ncol * vs.nrow;
   1068 		vs.col--;
   1069 		vs.row--;
   1070 		cursorat = vs.ncol * vs.row + vs.col;
   1071 		vs.at = FG_LIGHTGREY | BG_BLACK;
   1072 
   1073 		Crtat = (u_short *)cp;
   1074 		crtat = Crtat + cursorat;
   1075 
   1076 		if (vs.color == 0)
   1077 			vs.so_at = FG_BLACK | BG_LIGHTGREY;
   1078 		else
   1079 			vs.so_at = FG_YELLOW | BG_BLACK;
   1080 
   1081 		fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
   1082 	}
   1083 
   1084 	while (n--) {
   1085 		if (!(c = *cp++))
   1086 			continue;
   1087 
   1088 		switch (c) {
   1089 		case 0x1B:
   1090 			if (vs.state >= VSS_ESCAPE) {
   1091 				wrtchar(c, vs.so_at);
   1092 				vs.state = 0;
   1093 				goto maybe_scroll;
   1094 			} else
   1095 				vs.state = VSS_ESCAPE;
   1096 			break;
   1097 
   1098 		case 0x9B:	/* CSI */
   1099 			vs.cx = vs.cy = 0;
   1100 			vs.state = VSS_EBRACE;
   1101 			break;
   1102 
   1103 		case '\t': {
   1104 			int inccol = 8 - (vs.col & 7);
   1105 			crtat += inccol;
   1106 			vs.col += inccol;
   1107 		}
   1108 		maybe_scroll:
   1109 			if (vs.col >= vs.ncol) {
   1110 				vs.col -= vs.ncol;
   1111 				scroll = 1;
   1112 			}
   1113 			break;
   1114 
   1115 		case '\b':
   1116 			if (crtat <= Crtat)
   1117 				break;
   1118 			--crtat;
   1119 			if (--vs.col < 0)
   1120 				vs.col += vs.ncol;	/* non-destructive backspace */
   1121 			break;
   1122 
   1123 		case '\r':
   1124 			crtat -= vs.col;
   1125 			vs.col = 0;
   1126 			break;
   1127 
   1128 		case '\n':
   1129 			crtat += vs.ncol;
   1130 			scroll = 1;
   1131 			break;
   1132 
   1133 		default:
   1134 			switch (vs.state) {
   1135 			case 0:
   1136 				if (c == '\a')
   1137 					sysbeep(BEEP_FREQ, BEEP_TIME);
   1138 				else {
   1139 					/*
   1140 					 * If we're outputting multiple printed
   1141 					 * characters, just blast them to the
   1142 					 * screen until we reach the end of the
   1143 					 * buffer or a control character.  This
   1144 					 * saves time by short-circuiting the
   1145 					 * switch.
   1146 					 * If we reach the end of the line, we
   1147 					 * break to do a scroll check.
   1148 					 */
   1149 					for (;;) {
   1150 						if (c & 0x80)
   1151 							c = iso2ibm437[c&0x7f];
   1152 
   1153 						if (vs.so)
   1154 							wrtchar(c, vs.so_at);
   1155 						else
   1156 							wrtchar(c, vs.at);
   1157 						if (vs.col >= vs.ncol) {
   1158 							vs.col = 0;
   1159 							scroll = 1;
   1160 							break;
   1161 						}
   1162 						if (!n || (c = *cp) < ' ')
   1163 							break;
   1164 						n--, cp++;
   1165 					}
   1166 				}
   1167 				break;
   1168 			case VSS_ESCAPE:
   1169 				switch (c) {
   1170 					case '[': /* Start ESC [ sequence */
   1171 						vs.cx = vs.cy = 0;
   1172 						vs.state = VSS_EBRACE;
   1173 						break;
   1174 					case 'c': /* Create screen & home */
   1175 						fillw((vs.at << 8) | ' ',
   1176 						    Crtat, vs.nchr);
   1177 						crtat = Crtat;
   1178 						vs.col = 0;
   1179 						vs.state = 0;
   1180 						break;
   1181 					case '7': /* save cursor pos */
   1182 						vs.offset = crtat - Crtat;
   1183 						vs.state = 0;
   1184 						break;
   1185 					case '8': /* restore cursor pos */
   1186 						crtat = Crtat + vs.offset;
   1187 						vs.row = vs.offset / vs.ncol;
   1188 						vs.col = vs.offset % vs.ncol;
   1189 						vs.state = 0;
   1190 						break;
   1191 					default: /* Invalid, clear state */
   1192 						wrtchar(c, vs.so_at);
   1193 						vs.state = 0;
   1194 						goto maybe_scroll;
   1195 				}
   1196 				break;
   1197 
   1198 			default: /* VSS_EBRACE or VSS_EPARAM */
   1199 				switch (c) {
   1200 					int pos;
   1201 				case 'm':
   1202 					if (!vs.cx)
   1203 						vs.so = 0;
   1204 					else
   1205 						vs.so = 1;
   1206 					vs.state = 0;
   1207 					break;
   1208 				case 'A': { /* back cx rows */
   1209 					int cx = vs.cx;
   1210 					if (cx <= 0)
   1211 						cx = 1;
   1212 					else
   1213 						cx %= vs.nrow;
   1214 					pos = crtat - Crtat;
   1215 					pos -= vs.ncol * cx;
   1216 					if (pos < 0)
   1217 						pos += vs.nchr;
   1218 					crtat = Crtat + pos;
   1219 					vs.state = 0;
   1220 					break;
   1221 				}
   1222 				case 'B': { /* down cx rows */
   1223 					int cx = vs.cx;
   1224 					if (cx <= 0)
   1225 						cx = 1;
   1226 					else
   1227 						cx %= vs.nrow;
   1228 					pos = crtat - Crtat;
   1229 					pos += vs.ncol * cx;
   1230 					if (pos >= vs.nchr)
   1231 						pos -= vs.nchr;
   1232 					crtat = Crtat + pos;
   1233 					vs.state = 0;
   1234 					break;
   1235 				}
   1236 				case 'C': { /* right cursor */
   1237 					int cx = vs.cx,
   1238 					    col = vs.col;
   1239 					if (cx <= 0)
   1240 						cx = 1;
   1241 					else
   1242 						cx %= vs.ncol;
   1243 					pos = crtat - Crtat;
   1244 					pos += cx;
   1245 					col += cx;
   1246 					if (col >= vs.ncol) {
   1247 						pos -= vs.ncol;
   1248 						col -= vs.ncol;
   1249 					}
   1250 					vs.col = col;
   1251 					crtat = Crtat + pos;
   1252 					vs.state = 0;
   1253 					break;
   1254 				}
   1255 				case 'D': { /* left cursor */
   1256 					int cx = vs.cx,
   1257 					    col = vs.col;
   1258 					if (cx <= 0)
   1259 						cx = 1;
   1260 					else
   1261 						cx %= vs.ncol;
   1262 					pos = crtat - Crtat;
   1263 					pos -= cx;
   1264 					col -= cx;
   1265 					if (col < 0) {
   1266 						pos += vs.ncol;
   1267 						col += vs.ncol;
   1268 					}
   1269 					vs.col = col;
   1270 					crtat = Crtat + pos;
   1271 					vs.state = 0;
   1272 					break;
   1273 				}
   1274 				case 'J': /* Clear ... */
   1275 					switch (vs.cx) {
   1276 					case 0:
   1277 						/* ... to end of display */
   1278 						fillw((vs.at << 8) | ' ',
   1279 						    crtat,
   1280 						    Crtat + vs.nchr - crtat);
   1281 						break;
   1282 					case 1:
   1283 						/* ... to next location */
   1284 						fillw((vs.at << 8) | ' ',
   1285 						    Crtat,
   1286 						    crtat - Crtat + 1);
   1287 						break;
   1288 					case 2:
   1289 						/* ... whole display */
   1290 						fillw((vs.at << 8) | ' ',
   1291 						    Crtat,
   1292 						    vs.nchr);
   1293 						break;
   1294 					}
   1295 					vs.state = 0;
   1296 					break;
   1297 				case 'K': /* Clear line ... */
   1298 					switch (vs.cx) {
   1299 					case 0:
   1300 						/* ... current to EOL */
   1301 						fillw((vs.at << 8) | ' ',
   1302 						    crtat,
   1303 						    vs.ncol - vs.col);
   1304 						break;
   1305 					case 1:
   1306 						/* ... beginning to next */
   1307 						fillw((vs.at << 8) | ' ',
   1308 						    crtat - vs.col,
   1309 						    vs.col + 1);
   1310 						break;
   1311 					case 2:
   1312 						/* ... entire line */
   1313 						fillw((vs.at << 8) | ' ',
   1314 						    crtat - vs.col, vs.ncol);
   1315 						break;
   1316 					}
   1317 					vs.state = 0;
   1318 					break;
   1319 				case 'f': /* in system V consoles */
   1320 				case 'H': { /* Cursor move */
   1321 					int cx = vs.cx,
   1322 					    cy = vs.cy;
   1323 					if (!cx || !cy) {
   1324 						crtat = Crtat;
   1325 						vs.col = 0;
   1326 					} else {
   1327 						if (cx > vs.nrow)
   1328 							cx = vs.nrow;
   1329 						if (cy > vs.ncol)
   1330 							cy = vs.ncol;
   1331 						crtat = Crtat +
   1332 						    (cx - 1) * vs.ncol + cy - 1;
   1333 						vs.col = cy - 1;
   1334 					}
   1335 					vs.state = 0;
   1336 					break;
   1337 				}
   1338 				case 'M': { /* delete cx rows */
   1339 					u_short *crtAt = crtat - vs.col;
   1340 					int cx = vs.cx,
   1341 					    row = (crtAt - Crtat) / vs.ncol,
   1342 					    nrow = vs.nrow - row;
   1343 					if (cx <= 0)
   1344 						cx = 1;
   1345 					else if (cx > nrow)
   1346 						cx = nrow;
   1347 					if (cx < nrow)
   1348 #ifdef PCCONS_FORCE_WORD
   1349 						wcopy(crtAt + vs.ncol * cx,
   1350 						    crtAt, vs.ncol * (nrow -
   1351 						    cx) * CHR);
   1352 #else
   1353 						bcopy(crtAt + vs.ncol * cx,
   1354 						    crtAt, vs.ncol * (nrow -
   1355 						    cx) * CHR);
   1356 #endif
   1357 					fillw((vs.at << 8) | ' ',
   1358 					    crtAt + vs.ncol * (nrow - cx),
   1359 					    vs.ncol * cx);
   1360 					vs.state = 0;
   1361 					break;
   1362 				}
   1363 				case 'S': { /* scroll up cx lines */
   1364 					int cx = vs.cx;
   1365 					if (cx <= 0)
   1366 						cx = 1;
   1367 					else if (cx > vs.nrow)
   1368 						cx = vs.nrow;
   1369 					if (cx < vs.nrow)
   1370 #ifdef PCCONS_FORCE_WORD
   1371 						wcopy(Crtat + vs.ncol * cx,
   1372 						    Crtat, vs.ncol * (vs.nrow -
   1373 						    cx) * CHR);
   1374 #else
   1375 						bcopy(Crtat + vs.ncol * cx,
   1376 						    Crtat, vs.ncol * (vs.nrow -
   1377 						    cx) * CHR);
   1378 #endif
   1379 					fillw((vs.at << 8) | ' ',
   1380 					    Crtat + vs.ncol * (vs.nrow - cx),
   1381 					    vs.ncol * cx);
   1382 					/* crtat -= vs.ncol * cx; XXX */
   1383 					vs.state = 0;
   1384 					break;
   1385 				}
   1386 				case 'L': { /* insert cx rows */
   1387 					u_short *crtAt = crtat - vs.col;
   1388 					int cx = vs.cx,
   1389 					    row = (crtAt - Crtat) / vs.ncol,
   1390 					    nrow = vs.nrow - row;
   1391 					if (cx <= 0)
   1392 						cx = 1;
   1393 					else if (cx > nrow)
   1394 						cx = nrow;
   1395 					if (cx < nrow)
   1396 #ifdef PCCONS_FORCE_WORD
   1397 						wcopy(crtAt,
   1398 						    crtAt + vs.ncol * cx,
   1399 						    vs.ncol * (nrow - cx) *
   1400 						    CHR);
   1401 #else
   1402 						bcopy(crtAt,
   1403 						    crtAt + vs.ncol * cx,
   1404 						    vs.ncol * (nrow - cx) *
   1405 						    CHR);
   1406 #endif
   1407 					fillw((vs.at << 8) | ' ', crtAt,
   1408 					    vs.ncol * cx);
   1409 					vs.state = 0;
   1410 					break;
   1411 				}
   1412 				case 'T': { /* scroll down cx lines */
   1413 					int cx = vs.cx;
   1414 					if (cx <= 0)
   1415 						cx = 1;
   1416 					else if (cx > vs.nrow)
   1417 						cx = vs.nrow;
   1418 					if (cx < vs.nrow)
   1419 #ifdef PCCONS_FORCE_WORD
   1420 						wcopy(Crtat,
   1421 						    Crtat + vs.ncol * cx,
   1422 						    vs.ncol * (vs.nrow - cx) *
   1423 						    CHR);
   1424 #else
   1425 						bcopy(Crtat,
   1426 						    Crtat + vs.ncol * cx,
   1427 						    vs.ncol * (vs.nrow - cx) *
   1428 						    CHR);
   1429 #endif
   1430 					fillw((vs.at << 8) | ' ', Crtat,
   1431 					    vs.ncol * cx);
   1432 					/* crtat += vs.ncol * cx; XXX */
   1433 					vs.state = 0;
   1434 					break;
   1435 				}
   1436 				case ';': /* Switch params in cursor def */
   1437 					vs.state = VSS_EPARAM;
   1438 					break;
   1439 				case 'r':
   1440 					vs.so_at = (vs.cx & FG_MASK) |
   1441 					    ((vs.cy << 4) & BG_MASK);
   1442 					vs.state = 0;
   1443 					break;
   1444 				case 's': /* save cursor pos */
   1445 					vs.offset = crtat - Crtat;
   1446 					vs.state = 0;
   1447 					break;
   1448 				case 'u': /* restore cursor pos */
   1449 					crtat = Crtat + vs.offset;
   1450 					vs.row = vs.offset / vs.ncol;
   1451 					vs.col = vs.offset % vs.ncol;
   1452 					vs.state = 0;
   1453 					break;
   1454 				case 'x': /* set attributes */
   1455 					switch (vs.cx) {
   1456 					case 0:
   1457 						vs.at = FG_LIGHTGREY | BG_BLACK;
   1458 						break;
   1459 					case 1:
   1460 						/* ansi background */
   1461 						if (!vs.color)
   1462 							break;
   1463 						vs.at &= FG_MASK;
   1464 						vs.at |= bgansitopc[vs.cy & 7];
   1465 						break;
   1466 					case 2:
   1467 						/* ansi foreground */
   1468 						if (!vs.color)
   1469 							break;
   1470 						vs.at &= BG_MASK;
   1471 						vs.at |= fgansitopc[vs.cy & 7];
   1472 						break;
   1473 					case 3:
   1474 						/* pc text attribute */
   1475 						if (vs.state >= VSS_EPARAM)
   1476 							vs.at = vs.cy;
   1477 						break;
   1478 					}
   1479 					vs.state = 0;
   1480 					break;
   1481 
   1482 				default: /* Only numbers valid here */
   1483 					if ((c >= '0') && (c <= '9')) {
   1484 						if (vs.state >= VSS_EPARAM) {
   1485 							vs.cy *= 10;
   1486 							vs.cy += c - '0';
   1487 						} else {
   1488 							vs.cx *= 10;
   1489 							vs.cx += c - '0';
   1490 						}
   1491 					} else
   1492 						vs.state = 0;
   1493 					break;
   1494 				}
   1495 				break;
   1496 			}
   1497 		}
   1498 		if (scroll) {
   1499 			scroll = 0;
   1500 			/* scroll check */
   1501 			if (crtat >= Crtat + vs.nchr) {
   1502 				if (!kernel) {
   1503 					int s = spltty();
   1504 					if (lock_state & KB_SCROLL)
   1505 						tsleep(&lock_state,
   1506 						    PUSER, "pcputc", 0);
   1507 					splx(s);
   1508 				}
   1509 #if PCCONS_FORCE_WORD
   1510 				wcopy(Crtat + vs.ncol, Crtat,
   1511 				    (vs.nchr - vs.ncol) * CHR);
   1512 #else
   1513 				bcopy(Crtat + vs.ncol, Crtat,
   1514 				    (vs.nchr - vs.ncol) * CHR);
   1515 #endif
   1516 				fillw((vs.at << 8) | ' ',
   1517 				    Crtat + vs.nchr - vs.ncol,
   1518 				    vs.ncol);
   1519 				crtat -= vs.ncol;
   1520 			}
   1521 		}
   1522 	}
   1523 	async_update();
   1524 }
   1525 
   1526 /* the unshifted code for KB_SHIFT keys is used by X to distinguish between
   1527    left and right shift when reading the keyboard map */
   1528 static pccons_keymap_t	scan_codes[KB_NUM_KEYS] = {
   1529 /*  type       unshift   shift     control   altgr     shift_altgr scancode */
   1530   { KB_NONE,   "",       "",       "",       "",       ""}, /* 0 unused */
   1531   { KB_ASCII,  "\033",   "\033",   "\033",   "",       ""}, /* 1 ESCape */
   1532   { KB_ASCII,  "1",      "!",      "!",      "",       ""}, /* 2 1 */
   1533   { KB_ASCII,  "2",      "@",      "\000",   "",       ""}, /* 3 2 */
   1534   { KB_ASCII,  "3",      "#",      "#",      "",       ""}, /* 4 3 */
   1535   { KB_ASCII,  "4",      "$",      "$",      "",       ""}, /* 5 4 */
   1536   { KB_ASCII,  "5",      "%",      "%",      "",       ""}, /* 6 5 */
   1537   { KB_ASCII,  "6",      "^",      "\036",   "",       ""}, /* 7 6 */
   1538   { KB_ASCII,  "7",      "&",      "&",      "",       ""}, /* 8 7 */
   1539   { KB_ASCII,  "8",      "*",      "\010",   "",       ""}, /* 9 8 */
   1540   { KB_ASCII,  "9",      "(",      "(",      "",       ""}, /* 10 9 */
   1541   { KB_ASCII,  "0",      ")",      ")",      "",       ""}, /* 11 0 */
   1542   { KB_ASCII,  "-",      "_",      "\037",   "",       ""}, /* 12 - */
   1543   { KB_ASCII,  "=",      "+",      "+",      "",       ""}, /* 13 = */
   1544   { KB_ASCII,  "\177",   "\177",   "\010",   "",       ""}, /* 14 backspace */
   1545   { KB_ASCII,  "\t",     "\t",     "\t",     "",       ""}, /* 15 tab */
   1546   { KB_ASCII,  "q",      "Q",      "\021",   "",       ""}, /* 16 q */
   1547   { KB_ASCII,  "w",      "W",      "\027",   "",       ""}, /* 17 w */
   1548   { KB_ASCII,  "e",      "E",      "\005",   "",       ""}, /* 18 e */
   1549   { KB_ASCII,  "r",      "R",      "\022",   "",       ""}, /* 19 r */
   1550   { KB_ASCII,  "t",      "T",      "\024",   "",       ""}, /* 20 t */
   1551   { KB_ASCII,  "y",      "Y",      "\031",   "",       ""}, /* 21 y */
   1552   { KB_ASCII,  "u",      "U",      "\025",   "",       ""}, /* 22 u */
   1553   { KB_ASCII,  "i",      "I",      "\011",   "",       ""}, /* 23 i */
   1554   { KB_ASCII,  "o",      "O",      "\017",   "",       ""}, /* 24 o */
   1555   { KB_ASCII,  "p",      "P",      "\020",   "",       ""}, /* 25 p */
   1556   { KB_ASCII,  "[",      "{",      "\033",   "",       ""}, /* 26 [ */
   1557   { KB_ASCII,  "]",      "}",      "\035",   "",       ""}, /* 27 ] */
   1558   { KB_ASCII,  "\r",     "\r",     "\n",     "",       ""}, /* 28 return */
   1559   { KB_CTL,    "",       "",       "",       "",       ""}, /* 29 control */
   1560   { KB_ASCII,  "a",      "A",      "\001",   "",       ""}, /* 30 a */
   1561   { KB_ASCII,  "s",      "S",      "\023",   "",       ""}, /* 31 s */
   1562   { KB_ASCII,  "d",      "D",      "\004",   "",       ""}, /* 32 d */
   1563   { KB_ASCII,  "f",      "F",      "\006",   "",       ""}, /* 33 f */
   1564   { KB_ASCII,  "g",      "G",      "\007",   "",       ""}, /* 34 g */
   1565   { KB_ASCII,  "h",      "H",      "\010",   "",       ""}, /* 35 h */
   1566   { KB_ASCII,  "j",      "J",      "\n",     "",       ""}, /* 36 j */
   1567   { KB_ASCII,  "k",      "K",      "\013",   "",       ""}, /* 37 k */
   1568   { KB_ASCII,  "l",      "L",      "\014",   "",       ""}, /* 38 l */
   1569   { KB_ASCII,  ";",      ":",      ";",      "",       ""}, /* 39 ; */
   1570   { KB_ASCII,  "'",      "\"",     "'",      "",       ""}, /* 40 ' */
   1571   { KB_ASCII,  "`",      "~",      "`",      "",       ""}, /* 41 ` */
   1572   { KB_SHIFT,  "\001",   "",       "",       "",       ""}, /* 42 shift */
   1573   { KB_ASCII,  "\\",     "|",      "\034",   "",       ""}, /* 43 \ */
   1574   { KB_ASCII,  "z",      "Z",      "\032",   "",       ""}, /* 44 z */
   1575   { KB_ASCII,  "x",      "X",      "\030",   "",       ""}, /* 45 x */
   1576   { KB_ASCII,  "c",      "C",      "\003",   "",       ""}, /* 46 c */
   1577   { KB_ASCII,  "v",      "V",      "\026",   "",       ""}, /* 47 v */
   1578   { KB_ASCII,  "b",      "B",      "\002",   "",       ""}, /* 48 b */
   1579   { KB_ASCII,  "n",      "N",      "\016",   "",       ""}, /* 49 n */
   1580   { KB_ASCII,  "m",      "M",      "\r",     "",       ""}, /* 50 m */
   1581   { KB_ASCII,  ",",      "<",      "<",      "",       ""}, /* 51 , */
   1582   { KB_ASCII,  ".",      ">",      ">",      "",       ""}, /* 52 . */
   1583   { KB_ASCII,  "/",      "?",      "\037",   "",       ""}, /* 53 / */
   1584   { KB_SHIFT,  "\002",   "",       "",       "",       ""}, /* 54 shift */
   1585   { KB_KP,     "*",      "*",      "*",      "",       ""}, /* 55 kp * */
   1586   { KB_ALT,    "",       "",       "",       "",       ""}, /* 56 alt */
   1587   { KB_ASCII,  " ",      " ",      "\000",   "",       ""}, /* 57 space */
   1588   { KB_CAPS,   "",       "",       "",       "",       ""}, /* 58 caps */
   1589   { KB_FUNC,   "\033[M", "\033[Y", "\033[k", "",       ""}, /* 59 f1 */
   1590   { KB_FUNC,   "\033[N", "\033[Z", "\033[l", "",       ""}, /* 60 f2 */
   1591   { KB_FUNC,   "\033[O", "\033[a", "\033[m", "",       ""}, /* 61 f3 */
   1592   { KB_FUNC,   "\033[P", "\033[b", "\033[n", "",       ""}, /* 62 f4 */
   1593   { KB_FUNC,   "\033[Q", "\033[c", "\033[o", "",       ""}, /* 63 f5 */
   1594   { KB_FUNC,   "\033[R", "\033[d", "\033[p", "",       ""}, /* 64 f6 */
   1595   { KB_FUNC,   "\033[S", "\033[e", "\033[q", "",       ""}, /* 65 f7 */
   1596   { KB_FUNC,   "\033[T", "\033[f", "\033[r", "",       ""}, /* 66 f8 */
   1597   { KB_FUNC,   "\033[U", "\033[g", "\033[s", "",       ""}, /* 67 f9 */
   1598   { KB_FUNC,   "\033[V", "\033[h", "\033[t", "",       ""}, /* 68 f10 */
   1599   { KB_NUM,    "",       "",       "",       "",       ""}, /* 69 num lock */
   1600   { KB_SCROLL, "",       "",       "",       "",       ""}, /* 70 scroll lock */
   1601   { KB_KP,     "7",      "\033[H", "7",      "",       ""}, /* 71 kp 7 */
   1602   { KB_KP,     "8",      "\033[A", "8",      "",       ""}, /* 72 kp 8 */
   1603   { KB_KP,     "9",      "\033[I", "9",      "",       ""}, /* 73 kp 9 */
   1604   { KB_KP,     "-",      "-",      "-",      "",       ""}, /* 74 kp - */
   1605   { KB_KP,     "4",      "\033[D", "4",      "",       ""}, /* 75 kp 4 */
   1606   { KB_KP,     "5",      "\033[E", "5",      "",       ""}, /* 76 kp 5 */
   1607   { KB_KP,     "6",      "\033[C", "6",      "",       ""}, /* 77 kp 6 */
   1608   { KB_KP,     "+",      "+",      "+",      "",       ""}, /* 78 kp + */
   1609   { KB_KP,     "1",      "\033[F", "1",      "",       ""}, /* 79 kp 1 */
   1610   { KB_KP,     "2",      "\033[B", "2",      "",       ""}, /* 80 kp 2 */
   1611   { KB_KP,     "3",      "\033[G", "3",      "",       ""}, /* 81 kp 3 */
   1612   { KB_KP,     "0",      "\033[L", "0",      "",       ""}, /* 82 kp 0 */
   1613   { KB_KP,     ",",      "\177",   ",",      "",       ""}, /* 83 kp , */
   1614   { KB_NONE,   "",       "",       "",       "",       ""}, /* 84 0 */
   1615   { KB_NONE,   "",       "",       "",       "",       ""}, /* 85 0 */
   1616   { KB_NONE,   "",       "",       "",       "",       ""}, /* 86 0 */
   1617   { KB_FUNC,   "\033[W", "\033[i", "\033[u", "",       ""}, /* 87 f11 */
   1618   { KB_FUNC,   "\033[X", "\033[j", "\033[v", "",       ""}, /* 88 f12 */
   1619   { KB_NONE,   "",       "",       "",       "",       ""}, /* 89 0 */
   1620   { KB_NONE,   "",       "",       "",       "",       ""}, /* 90 0 */
   1621   { KB_NONE,   "",       "",       "",       "",       ""}, /* 91 0 */
   1622   { KB_NONE,   "",       "",       "",       "",       ""}, /* 92 0 */
   1623   { KB_NONE,   "",       "",       "",       "",       ""}, /* 93 0 */
   1624   { KB_NONE,   "",       "",       "",       "",       ""}, /* 94 0 */
   1625   { KB_NONE,   "",       "",       "",       "",       ""}, /* 95 0 */
   1626   { KB_NONE,   "",       "",       "",       "",       ""}, /* 96 0 */
   1627   { KB_NONE,   "",       "",       "",       "",       ""}, /* 97 0 */
   1628   { KB_NONE,   "",       "",       "",       "",       ""}, /* 98 0 */
   1629   { KB_NONE,   "",       "",       "",       "",       ""}, /* 99 0 */
   1630   { KB_NONE,   "",       "",       "",       "",       ""}, /* 100 */
   1631   { KB_NONE,   "",       "",       "",       "",       ""}, /* 101 */
   1632   { KB_NONE,   "",       "",       "",       "",       ""}, /* 102 */
   1633   { KB_NONE,   "",       "",       "",       "",       ""}, /* 103 */
   1634   { KB_NONE,   "",       "",       "",       "",       ""}, /* 104 */
   1635   { KB_NONE,   "",       "",       "",       "",       ""}, /* 105 */
   1636   { KB_NONE,   "",       "",       "",       "",       ""}, /* 106 */
   1637   { KB_NONE,   "",       "",       "",       "",       ""}, /* 107 */
   1638   { KB_NONE,   "",       "",       "",       "",       ""}, /* 108 */
   1639   { KB_NONE,   "",       "",       "",       "",       ""}, /* 109 */
   1640   { KB_NONE,   "",       "",       "",       "",       ""}, /* 110 */
   1641   { KB_NONE,   "",       "",       "",       "",       ""}, /* 111 */
   1642   { KB_NONE,   "",       "",       "",       "",       ""}, /* 112 */
   1643   { KB_NONE,   "",       "",       "",       "",       ""}, /* 113 */
   1644   { KB_NONE,   "",       "",       "",       "",       ""}, /* 114 */
   1645   { KB_NONE,   "",       "",       "",       "",       ""}, /* 115 */
   1646   { KB_NONE,   "",       "",       "",       "",       ""}, /* 116 */
   1647   { KB_NONE,   "",       "",       "",       "",       ""}, /* 117 */
   1648   { KB_NONE,   "",       "",       "",       "",       ""}, /* 118 */
   1649   { KB_NONE,   "",       "",       "",       "",       ""}, /* 119 */
   1650   { KB_NONE,   "",       "",       "",       "",       ""}, /* 120 */
   1651   { KB_NONE,   "",       "",       "",       "",       ""}, /* 121 */
   1652   { KB_NONE,   "",       "",       "",       "",       ""}, /* 122 */
   1653   { KB_NONE,   "",       "",       "",       "",       ""}, /* 123 */
   1654   { KB_NONE,   "",       "",       "",       "",       ""}, /* 124 */
   1655   { KB_NONE,   "",       "",       "",       "",       ""}, /* 125 */
   1656   { KB_NONE,   "",       "",       "",       "",       ""}, /* 126 */
   1657   { KB_NONE,   "",       "",       "",       "",       ""}  /* 127 */
   1658 };
   1659 
   1660 /*
   1661  * Get characters from the keyboard.  If none are present, return NULL.
   1662  */
   1663 char *
   1664 sget()
   1665 {
   1666 	u_char dt;
   1667 	static u_char extended = 0, shift_state = 0;
   1668 	static u_char capchar[2];
   1669 
   1670 top:
   1671 	KBD_DELAY;
   1672 	dt = inb(kbd_datap);
   1673 
   1674 	switch (dt) {
   1675 	case KBR_ACK: case KBR_ECHO:
   1676 		kb_oq_get = (kb_oq_get + 1) & 7;
   1677 		if(kb_oq_get != kb_oq_put) {
   1678 			outb(kbd_datap, kb_oq[kb_oq_get]);
   1679 		}
   1680 		goto loop;
   1681 	case KBR_RESEND:
   1682 		outb(kbd_datap, kb_oq[kb_oq_get]);
   1683 		goto loop;
   1684 	}
   1685 
   1686 	if (pc_xmode > 0) {
   1687 #if defined(DDB) && defined(XSERVER_DDB)
   1688 		/* F12 enters the debugger while in X mode */
   1689 		if (dt == 88)
   1690 			Debugger();
   1691 #endif
   1692 		capchar[0] = dt;
   1693 		capchar[1] = 0;
   1694 		/*
   1695 		 * Check for locking keys.
   1696 		 *
   1697 		 * XXX Setting the LEDs this way is a bit bogus.  What if the
   1698 		 * keyboard has been remapped in X?
   1699 		 */
   1700 		switch (scan_codes[dt & 0x7f].type) {
   1701 		case KB_NUM:
   1702 			if (dt & 0x80) {
   1703 				shift_state &= ~KB_NUM;
   1704 				break;
   1705 			}
   1706 			if (shift_state & KB_NUM)
   1707 				break;
   1708 			shift_state |= KB_NUM;
   1709 			lock_state ^= KB_NUM;
   1710 			async_update();
   1711 			break;
   1712 		case KB_CAPS:
   1713 			if (dt & 0x80) {
   1714 				shift_state &= ~KB_CAPS;
   1715 				break;
   1716 			}
   1717 			if (shift_state & KB_CAPS)
   1718 				break;
   1719 			shift_state |= KB_CAPS;
   1720 			lock_state ^= KB_CAPS;
   1721 			async_update();
   1722 			break;
   1723 		case KB_SCROLL:
   1724 			if (dt & 0x80) {
   1725 				shift_state &= ~KB_SCROLL;
   1726 				break;
   1727 			}
   1728 			if (shift_state & KB_SCROLL)
   1729 				break;
   1730 			shift_state |= KB_SCROLL;
   1731 			lock_state ^= KB_SCROLL;
   1732 			if ((lock_state & KB_SCROLL) == 0)
   1733 				wakeup((caddr_t)&lock_state);
   1734 			async_update();
   1735 			break;
   1736 		}
   1737 		return capchar;
   1738 	}
   1739 
   1740 	switch (dt) {
   1741 	case KBR_EXTENDED:
   1742 		extended = 1;
   1743 		goto loop;
   1744 	}
   1745 
   1746 #ifdef DDB
   1747 	/*
   1748 	 * Check for cntl-alt-esc.
   1749 	 */
   1750 	if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
   1751 		/* XXX - check pccons_is_console */
   1752 		Debugger();
   1753 		dt |= 0x80;	/* discard esc (ddb discarded ctl-alt) */
   1754 	}
   1755 #endif
   1756 
   1757 	/*
   1758 	 * Check for make/break.
   1759 	 */
   1760 	if (dt & 0x80) {
   1761 		/*
   1762 		 * break
   1763 		 */
   1764 		dt &= 0x7f;
   1765 		switch (scan_codes[dt].type) {
   1766 		case KB_NUM:
   1767 			shift_state &= ~KB_NUM;
   1768 			break;
   1769 		case KB_CAPS:
   1770 			shift_state &= ~KB_CAPS;
   1771 			break;
   1772 		case KB_SCROLL:
   1773 			shift_state &= ~KB_SCROLL;
   1774 			break;
   1775 		case KB_SHIFT:
   1776 			shift_state &= ~KB_SHIFT;
   1777 			break;
   1778 		case KB_ALT:
   1779 			if (extended)
   1780 				shift_state &= ~KB_ALTGR;
   1781 			else
   1782 				shift_state &= ~KB_ALT;
   1783 			break;
   1784 		case KB_CTL:
   1785 			shift_state &= ~KB_CTL;
   1786 			break;
   1787 		}
   1788 	} else {
   1789 		/*
   1790 		 * make
   1791 		 */
   1792 		switch (scan_codes[dt].type) {
   1793 		/*
   1794 		 * locking keys
   1795 		 */
   1796 		case KB_NUM:
   1797 			if (shift_state & KB_NUM)
   1798 				break;
   1799 			shift_state |= KB_NUM;
   1800 			lock_state ^= KB_NUM;
   1801 			async_update();
   1802 			break;
   1803 		case KB_CAPS:
   1804 			if (shift_state & KB_CAPS)
   1805 				break;
   1806 			shift_state |= KB_CAPS;
   1807 			lock_state ^= KB_CAPS;
   1808 			async_update();
   1809 			break;
   1810 		case KB_SCROLL:
   1811 			if (shift_state & KB_SCROLL)
   1812 				break;
   1813 			shift_state |= KB_SCROLL;
   1814 			lock_state ^= KB_SCROLL;
   1815 			if ((lock_state & KB_SCROLL) == 0)
   1816 				wakeup((caddr_t)&lock_state);
   1817 			async_update();
   1818 			break;
   1819 		/*
   1820 		 * non-locking keys
   1821 		 */
   1822 		case KB_SHIFT:
   1823 			shift_state |= KB_SHIFT;
   1824 			break;
   1825 		case KB_ALT:
   1826 			if (extended)
   1827 				shift_state |= KB_ALTGR;
   1828 			else
   1829 				shift_state |= KB_ALT;
   1830 			break;
   1831 		case KB_CTL:
   1832 			shift_state |= KB_CTL;
   1833 			break;
   1834 		case KB_ASCII:
   1835 			/* control has highest priority */
   1836 			if (shift_state & KB_CTL)
   1837 				capchar[0] = scan_codes[dt].ctl[0];
   1838 			else if (shift_state & KB_ALTGR) {
   1839 				if (shift_state & KB_SHIFT)
   1840 					capchar[0] = scan_codes[dt].shift_altgr[0];
   1841 				else
   1842 					capchar[0] = scan_codes[dt].altgr[0];
   1843 			}
   1844 			else {
   1845 				if (shift_state & KB_SHIFT)
   1846 					capchar[0] = scan_codes[dt].shift[0];
   1847 				else
   1848 					capchar[0] = scan_codes[dt].unshift[0];
   1849 			}
   1850 			if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
   1851 			    capchar[0] <= 'z') {
   1852 				capchar[0] -= ('a' - 'A');
   1853 			}
   1854 			capchar[0] |= (shift_state & KB_ALT);
   1855 			extended = 0;
   1856 			return capchar;
   1857 		case KB_NONE:
   1858 printf("keycode %d\n",dt);
   1859 			break;
   1860 		case KB_FUNC: {
   1861 			char *more_chars;
   1862 			if (shift_state & KB_SHIFT)
   1863 				more_chars = scan_codes[dt].shift;
   1864 			else if (shift_state & KB_CTL)
   1865 				more_chars = scan_codes[dt].ctl;
   1866 			else
   1867 				more_chars = scan_codes[dt].unshift;
   1868 			extended = 0;
   1869 			return more_chars;
   1870 		}
   1871 		case KB_KP: {
   1872 			char *more_chars;
   1873 			if (shift_state & (KB_SHIFT | KB_CTL) ||
   1874 			    (lock_state & KB_NUM) == 0 || extended)
   1875 				more_chars = scan_codes[dt].shift;
   1876 			else
   1877 				more_chars = scan_codes[dt].unshift;
   1878 			extended = 0;
   1879 			return more_chars;
   1880 		}
   1881 		}
   1882 	}
   1883 
   1884 	extended = 0;
   1885 loop:
   1886 	if ((inb(kbd_cmdp) & KBS_DIB) == 0)
   1887 		return 0;
   1888 	goto top;
   1889 }
   1890 
   1891 int
   1892 pcmmap(dev, offset, nprot)
   1893 	dev_t dev;
   1894 	int offset;
   1895 	int nprot;
   1896 {
   1897 
   1898 	switch(cputype) {
   1899 
   1900 	case ACER_PICA_61:
   1901 		if (offset >= 0xa0000 && offset < 0xc0000)
   1902 			return mips_btop(PICA_P_LOCAL_VIDEO + offset);
   1903 		if (offset >= 0x0000 && offset < 0x10000)
   1904 			return mips_btop(PICA_P_LOCAL_VIDEO_CTRL + offset);
   1905 		if (offset >= 0x40000000 && offset < 0x40800000)
   1906 			return mips_btop(PICA_P_LOCAL_VIDEO + offset - 0x40000000);
   1907 		return -1;
   1908 
   1909 	case DESKSTATION_RPC44:
   1910 		if (offset >= 0xa0000 && offset < 0xc0000)
   1911 			return mips_btop(RPC44_P_ISA_MEM + offset);
   1912 		if (offset >= 0x0000 && offset < 0x10000)
   1913 			return mips_btop(RPC44_P_ISA_IO + offset);
   1914 		if (offset >= 0x40000000 && offset < 0x40800000)
   1915 			return mips_btop(RPC44_P_ISA_MEM + offset - 0x40000000);
   1916 		return -1;
   1917 
   1918 	case DESKSTATION_TYNE:
   1919 		/* Addresses returned are a fake to be able to handle >32 bit
   1920 		 * physical addresses used by the tyne. The real physical adr
   1921 		 * processing is done in pmap.c. Until we are a real 64 bit
   1922 		 * port this is how it will be done.
   1923 		 */
   1924 		/* XXX - the above is not supported merged pmap, yet */
   1925 		if (offset >= 0xa0000 && offset < 0xc0000)
   1926 			return mips_btop(TYNE_V_ISA_MEM + offset);
   1927 		if (offset >= 0x0000 && offset < 0x10000)
   1928 			return mips_btop(TYNE_V_ISA_IO + offset);
   1929 		if (offset >= 0x40000000 && offset < 0x40800000)
   1930 			return mips_btop(TYNE_V_ISA_MEM + offset - 0x40000000);
   1931 		return -1;
   1932 	}
   1933 	return -1;
   1934 }
   1935 
   1936 void
   1937 pc_xmode_on()
   1938 {
   1939 	if (pc_xmode)
   1940 		return;
   1941 	pc_xmode = 1;
   1942 
   1943 #ifdef XFREE86_BUG_COMPAT
   1944 	/* If still unchanged, get current shape. */
   1945 	if (cursor_shape == 0xffff)
   1946 		get_cursor_shape();
   1947 #endif
   1948 }
   1949 
   1950 void
   1951 pc_xmode_off()
   1952 {
   1953 	if (pc_xmode == 0)
   1954 		return;
   1955 	pc_xmode = 0;
   1956 
   1957 #ifdef XFREE86_BUG_COMPAT
   1958 	/* XXX It would be hard to justify why the X server doesn't do this. */
   1959 	set_cursor_shape();
   1960 #endif
   1961 	async_update();
   1962 }
   1963 
   1964 #include <machine/mouse.h>
   1965 
   1966 /* status bits */
   1967 #define	PMS_OBUF_FULL	0x01
   1968 #define	PMS_IBUF_FULL	0x02
   1969 
   1970 /* controller commands */
   1971 #define	PMS_INT_ENABLE	0x47	/* enable controller interrupts */
   1972 #define	PMS_INT_DISABLE	0x65	/* disable controller interrupts */
   1973 #define	PMS_AUX_ENABLE	0xa7	/* enable auxiliary port */
   1974 #define	PMS_AUX_DISABLE	0xa8	/* disable auxiliary port */
   1975 #define	PMS_MAGIC_1	0xa9	/* XXX */
   1976 
   1977 #define	PMS_8042_CMD	0x65
   1978 
   1979 /* mouse commands */
   1980 #define	PMS_SET_SCALE11	0xe6	/* set scaling 1:1 */
   1981 #define	PMS_SET_SCALE21 0xe7	/* set scaling 2:1 */
   1982 #define	PMS_SET_RES	0xe8	/* set resolution */
   1983 #define	PMS_GET_SCALE	0xe9	/* get scaling factor */
   1984 #define	PMS_SET_STREAM	0xea	/* set streaming mode */
   1985 #define	PMS_SET_SAMPLE	0xf3	/* set sampling rate */
   1986 #define	PMS_DEV_ENABLE	0xf4	/* mouse on */
   1987 #define	PMS_DEV_DISABLE	0xf5	/* mouse off */
   1988 #define	PMS_RESET	0xff	/* reset */
   1989 
   1990 #define	PMS_CHUNK	128	/* chunk size for read */
   1991 #define	PMS_BSIZE	1020	/* buffer size */
   1992 
   1993 #define	FLUSHQ(q) { if((q)->c_cc) ndflush(q, (q)->c_cc); }
   1994 
   1995 int opmsopen __P((dev_t, int));
   1996 int opmsclose __P((dev_t, int));
   1997 int opmsread __P((dev_t, struct uio *, int));
   1998 int opmsioctl __P((dev_t, u_long, caddr_t, int));
   1999 int opmsselect __P((dev_t, int, struct proc *));
   2000 int opmspoll __P((dev_t, int, struct proc *));
   2001 static __inline void pms_dev_cmd __P((u_char));
   2002 static __inline void pms_aux_cmd __P((u_char));
   2003 static __inline void pms_pit_cmd __P((u_char));
   2004 
   2005 static __inline void
   2006 pms_dev_cmd(value)
   2007 	u_char value;
   2008 {
   2009 	kbd_flush_input();
   2010 	outb(kbd_cmdp, 0xd4);
   2011 	kbd_flush_input();
   2012 	outb(kbd_datap, value);
   2013 }
   2014 
   2015 static __inline void
   2016 pms_aux_cmd(value)
   2017 	u_char value;
   2018 {
   2019 	kbd_flush_input();
   2020 	outb(kbd_cmdp, value);
   2021 }
   2022 
   2023 static __inline void
   2024 pms_pit_cmd(value)
   2025 	u_char value;
   2026 {
   2027 	kbd_flush_input();
   2028 	outb(kbd_cmdp, 0x60);
   2029 	kbd_flush_input();
   2030 	outb(kbd_datap, value);
   2031 }
   2032 
   2033 int
   2034 opmsprobe(parent, match, aux)
   2035 	struct device *parent;
   2036 	struct cfdata *match;
   2037 	void *aux;
   2038 {
   2039 	struct confargs *ca = aux;
   2040 	u_char x;
   2041 
   2042 	/* Make shure we're looking for this type of device */
   2043 	if(!BUS_MATCHNAME(ca, "pms"))
   2044 		return(0);
   2045 
   2046 	pms_dev_cmd(KBC_RESET);
   2047 	pms_aux_cmd(PMS_MAGIC_1);
   2048 	delay(10000);
   2049 	x = inb(kbd_datap);
   2050 	pms_pit_cmd(PMS_INT_DISABLE);
   2051 	if (x & 0x04)
   2052 		return 0;
   2053 
   2054 	return 1;
   2055 }
   2056 
   2057 void
   2058 opmsattach(parent, self, aux)
   2059 	struct device *parent, *self;
   2060 	void *aux;
   2061 {
   2062 	struct opms_softc *sc = (void *)self;
   2063 	struct confargs *ca = aux;
   2064 
   2065 	printf("\n");
   2066 
   2067 	/* Other initialization was done by opmsprobe. */
   2068 	sc->sc_state = 0;
   2069 
   2070 	BUS_INTR_ESTABLISH(ca, opmsintr, (void *)(long)sc);
   2071 }
   2072 
   2073 int
   2074 opmsopen(dev, flag)
   2075 	dev_t dev;
   2076 	int flag;
   2077 {
   2078 	int unit = PMSUNIT(dev);
   2079 	struct opms_softc *sc;
   2080 
   2081 	if (unit >= opms_cd.cd_ndevs)
   2082 		return ENXIO;
   2083 	sc = opms_cd.cd_devs[unit];
   2084 	if (!sc)
   2085 		return ENXIO;
   2086 
   2087 	if (sc->sc_state & PMS_OPEN)
   2088 		return EBUSY;
   2089 
   2090 	if (clalloc(&sc->sc_q, PMS_BSIZE, 0) == -1)
   2091 		return ENOMEM;
   2092 
   2093 	sc->sc_state |= PMS_OPEN;
   2094 	sc->sc_status = 0;
   2095 	sc->sc_x = sc->sc_y = 0;
   2096 
   2097 	/* Enable interrupts. */
   2098 	pms_dev_cmd(PMS_DEV_ENABLE);
   2099 	pms_aux_cmd(PMS_AUX_ENABLE);
   2100 	pms_dev_cmd(PMS_SET_RES);
   2101 	pms_dev_cmd(3);		/* 8 counts/mm */
   2102 	pms_dev_cmd(PMS_SET_SCALE21);
   2103 #if 0
   2104 	pms_dev_cmd(PMS_SET_SAMPLE);
   2105 	pms_dev_cmd(100);	/* 100 samples/sec */
   2106 	pms_dev_cmd(PMS_SET_STREAM);
   2107 #endif
   2108 	pms_pit_cmd(PMS_INT_ENABLE);
   2109 
   2110 	return 0;
   2111 }
   2112 
   2113 int
   2114 opmsclose(dev, flag)
   2115 	dev_t dev;
   2116 	int flag;
   2117 {
   2118 	struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
   2119 
   2120 	/* Disable interrupts. */
   2121 	pms_dev_cmd(PMS_DEV_DISABLE);
   2122 	pms_pit_cmd(PMS_INT_DISABLE);
   2123 	pms_aux_cmd(PMS_AUX_DISABLE);
   2124 
   2125 	sc->sc_state &= ~PMS_OPEN;
   2126 
   2127 	clfree(&sc->sc_q);
   2128 
   2129 	return 0;
   2130 }
   2131 
   2132 int
   2133 opmsread(dev, uio, flag)
   2134 	dev_t dev;
   2135 	struct uio *uio;
   2136 	int flag;
   2137 {
   2138 	struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
   2139 	int s;
   2140 	int error = 0;
   2141 	size_t length;
   2142 	u_char buffer[PMS_CHUNK];
   2143 
   2144 	/* Block until mouse activity occured. */
   2145 
   2146 	s = spltty();
   2147 	while (sc->sc_q.c_cc == 0) {
   2148 		if (flag & IO_NDELAY) {
   2149 			splx(s);
   2150 			return EWOULDBLOCK;
   2151 		}
   2152 		sc->sc_state |= PMS_ASLP;
   2153 		error = tsleep((caddr_t)sc, PZERO | PCATCH, "pmsrea", 0);
   2154 		if (error) {
   2155 			sc->sc_state &= ~PMS_ASLP;
   2156 			splx(s);
   2157 			return error;
   2158 		}
   2159 	}
   2160 	splx(s);
   2161 
   2162 	/* Transfer as many chunks as possible. */
   2163 
   2164 	while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
   2165 		length = min(sc->sc_q.c_cc, uio->uio_resid);
   2166 		if (length > sizeof(buffer))
   2167 			length = sizeof(buffer);
   2168 
   2169 		/* Remove a small chunk from the input queue. */
   2170 		(void) q_to_b(&sc->sc_q, buffer, length);
   2171 
   2172 		/* Copy the data to the user process. */
   2173 		error = uiomove(buffer, length, uio);
   2174 		if (error)
   2175 			break;
   2176 	}
   2177 
   2178 	return error;
   2179 }
   2180 
   2181 int
   2182 opmsioctl(dev, cmd, addr, flag)
   2183 	dev_t dev;
   2184 	u_long cmd;
   2185 	caddr_t addr;
   2186 	int flag;
   2187 {
   2188 	struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
   2189 	struct mouseinfo info;
   2190 	int s;
   2191 	int error;
   2192 
   2193 	switch (cmd) {
   2194 	case MOUSEIOCREAD:
   2195 		s = spltty();
   2196 
   2197 		info.status = sc->sc_status;
   2198 		if (sc->sc_x || sc->sc_y)
   2199 			info.status |= MOVEMENT;
   2200 
   2201 		if (sc->sc_x > 127)
   2202 			info.xmotion = 127;
   2203 		else if (sc->sc_x < -127)
   2204 			/* Bounding at -127 avoids a bug in XFree86. */
   2205 			info.xmotion = -127;
   2206 		else
   2207 			info.xmotion = sc->sc_x;
   2208 
   2209 		if (sc->sc_y > 127)
   2210 			info.ymotion = 127;
   2211 		else if (sc->sc_y < -127)
   2212 			info.ymotion = -127;
   2213 		else
   2214 			info.ymotion = sc->sc_y;
   2215 
   2216 		/* Reset historical information. */
   2217 		sc->sc_x = sc->sc_y = 0;
   2218 		sc->sc_status &= ~BUTCHNGMASK;
   2219 		ndflush(&sc->sc_q, sc->sc_q.c_cc);
   2220 
   2221 		splx(s);
   2222 		error = copyout(&info, addr, sizeof(struct mouseinfo));
   2223 		break;
   2224 	default:
   2225 		error = EINVAL;
   2226 		break;
   2227 	}
   2228 
   2229 	return error;
   2230 }
   2231 
   2232 /* Masks for the first byte of a packet */
   2233 #define PS2LBUTMASK 0x01
   2234 #define PS2RBUTMASK 0x02
   2235 #define PS2MBUTMASK 0x04
   2236 
   2237 int
   2238 opmsintr(arg)
   2239 	void *arg;
   2240 {
   2241 	struct opms_softc *sc = arg;
   2242 	static int state = 0;
   2243 	static u_char buttons;
   2244 	u_char changed;
   2245 	static char dx, dy;
   2246 	u_char buffer[5];
   2247 
   2248 	if ((sc->sc_state & PMS_OPEN) == 0) {
   2249 		/* Interrupts are not expected.  Discard the byte. */
   2250 		kbd_flush_input();
   2251 		return 0;
   2252 	}
   2253 
   2254 	switch (state) {
   2255 
   2256 	case 0:
   2257 		buttons = inb(kbd_datap);
   2258 		if ((buttons & 0xc0) == 0)
   2259 			++state;
   2260 		break;
   2261 
   2262 	case 1:
   2263 		dx = inb(kbd_datap);
   2264 		/* Bounding at -127 avoids a bug in XFree86. */
   2265 		dx = (dx == -128) ? -127 : dx;
   2266 		++state;
   2267 		break;
   2268 
   2269 	case 2:
   2270 		dy = inb(kbd_datap);
   2271 		dy = (dy == -128) ? -127 : dy;
   2272 		state = 0;
   2273 
   2274 		buttons = ((buttons & PS2LBUTMASK) << 2) |
   2275 			  ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1);
   2276 		changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3;
   2277 		sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) | changed;
   2278 
   2279 		if (dx || dy || changed) {
   2280 			/* Update accumulated movements. */
   2281 			sc->sc_x += dx;
   2282 			sc->sc_y += dy;
   2283 
   2284 			/* Add this event to the queue. */
   2285 			buffer[0] = 0x80 | (buttons & BUTSTATMASK);
   2286 			if(dx < 0)
   2287 				buffer[0] |= 0x10;
   2288 			buffer[1] = dx & 0x7f;
   2289 			if(dy < 0)
   2290 				buffer[0] |= 0x20;
   2291 			buffer[2] = dy & 0x7f;
   2292 			buffer[3] = buffer[4] = 0;
   2293 			(void) b_to_q(buffer, sizeof buffer, &sc->sc_q);
   2294 
   2295 			if (sc->sc_state & PMS_ASLP) {
   2296 				sc->sc_state &= ~PMS_ASLP;
   2297 				wakeup((caddr_t)sc);
   2298 			}
   2299 			selwakeup(&sc->sc_rsel);
   2300 		}
   2301 
   2302 		break;
   2303 	}
   2304 	return -1;
   2305 }
   2306 
   2307 int
   2308 opmspoll(dev, events, p)
   2309 	dev_t dev;
   2310 	int events;
   2311 	struct proc *p;
   2312 {
   2313 	struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
   2314 	int revents = 0;
   2315 	int s = spltty();
   2316 
   2317 	if (events & (POLLIN | POLLRDNORM))
   2318 		if (sc->sc_q.c_cc > 0)
   2319 			revents |= events & (POLLIN | POLLRDNORM);
   2320 		else
   2321 			selrecord(p, &sc->sc_rsel);
   2322 
   2323 	splx(s);
   2324 	return (revents);
   2325 }
   2326