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