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