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