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