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