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