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