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