xref: /netbsd-src/sys/arch/arc/dev/pccons.c (revision eb7c1594f145c931049e1fd9eb056a5987e87e59)
1 /*	$NetBSD: pccons.c,v 1.37 2003/08/07 16:26:48 agc 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 
5 /*-
6  * Copyright (c) 1990 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * William Jolitz and Don Ahn.
11  *
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *	@(#)pccons.c	5.11 (Berkeley) 5/21/91
36  */
37 
38 /*-
39  * Copyright (c) 1993, 1994, 1995 Charles M. Hannum.  All rights reserved.
40  *
41  * This code is derived from software contributed to Berkeley by
42  * William Jolitz and Don Ahn.
43  *
44  * Copyright (c) 1994 Charles M. Hannum.
45  * Copyright (c) 1992, 1993 Erik Forsberg.
46  *
47  * Redistribution and use in source and binary forms, with or without
48  * modification, are permitted provided that the following conditions
49  * are met:
50  * 1. Redistributions of source code must retain the above copyright
51  *    notice, this list of conditions and the following disclaimer.
52  * 2. Redistributions in binary form must reproduce the above copyright
53  *    notice, this list of conditions and the following disclaimer in the
54  *    documentation and/or other materials provided with the distribution.
55  * 3. All advertising materials mentioning features or use of this software
56  *    must display the following acknowledgement:
57  *	This product includes software developed by the University of
58  *	California, Berkeley and its contributors.
59  * 4. Neither the name of the University nor the names of its contributors
60  *    may be used to endorse or promote products derived from this software
61  *    without specific prior written permission.
62  *
63  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73  * SUCH DAMAGE.
74  *
75  *	@(#)pccons.c	5.11 (Berkeley) 5/21/91
76  */
77 
78 /*
79  * code to work keyboard & display for PC-style console
80  */
81 
82 #include <sys/cdefs.h>
83 __KERNEL_RCSID(0, "$NetBSD: pccons.c,v 1.37 2003/08/07 16:26:48 agc Exp $");
84 
85 #include "opt_ddb.h"
86 
87 #include <sys/param.h>
88 #include <sys/systm.h>
89 #include <sys/tty.h>
90 #include <sys/callout.h>
91 #include <sys/poll.h>
92 #include <sys/conf.h>
93 #include <sys/vnode.h>
94 #include <sys/kernel.h>
95 #include <sys/kcore.h>
96 #include <sys/device.h>
97 #include <sys/proc.h>
98 
99 #include <machine/bus.h>
100 
101 #include <machine/display.h>
102 #include <machine/pccons.h>
103 #include <machine/kbdreg.h>
104 
105 #include <dev/cons.h>
106 #include <dev/isa/isavar.h>
107 
108 #include <arc/arc/arcbios.h>
109 #include <arc/dev/pcconsvar.h>
110 
111 #define	XFREE86_BUG_COMPAT
112 
113 #ifndef BEEP_FREQ
114 #define BEEP_FREQ 1600
115 #endif
116 #ifndef BEEP_TIME
117 #define BEEP_TIME (hz/5)
118 #endif
119 
120 #define PCBURST 128
121 
122 static u_short *Crtat;			/* pointer to backing store */
123 static u_short *crtat;			/* pointer to current char */
124 static u_char async, kernel, polling;	/* Really, you don't want to know. */
125 static u_char lock_state = 0x00,	/* all off */
126 	      old_lock_state = 0xff,
127 	      typematic_rate = 0xff,	/* don't update until set by user */
128 	      old_typematic_rate = 0xff;
129 static u_short cursor_shape = 0xffff,	/* don't update until set by user */
130 	       old_cursor_shape = 0xffff;
131 static pccons_keymap_t scan_codes[KB_NUM_KEYS];/* keyboard translation table */
132 int pc_xmode = 0;
133 
134 /*
135  *  Keyboard output queue.
136  */
137 int	kb_oq_put = 0;
138 int	kb_oq_get = 0;
139 u_char	kb_oq[8];
140 
141 #define	PCUNIT(x)	(minor(x))
142 
143 static struct video_state {
144 	int 	cx, cy;		/* escape parameters */
145 	int 	row, col;	/* current cursor position */
146 	int 	nrow, ncol, nchr;	/* current screen geometry */
147 	int	offset;		/* Saved cursor pos */
148 	u_char	state;		/* parser state */
149 #define	VSS_ESCAPE	1
150 #define	VSS_EBRACE	2
151 #define	VSS_EPARAM	3
152 	char	so;		/* in standout mode? */
153 	char	color;		/* color or mono display */
154 	char	at;		/* normal attributes */
155 	char	so_at;		/* standout attributes */
156 } vs;
157 
158 static struct callout async_update_ch = CALLOUT_INITIALIZER;
159 
160 void pc_xmode_on __P((void));
161 void pc_xmode_off __P((void));
162 static u_char kbc_get8042cmd __P((void));
163 int kbd_cmd __P((u_char, u_char));
164 static __inline int kbd_wait_output __P((void));
165 static __inline int kbd_wait_input __P((void));
166 void kbd_flush_input __P((void));
167 void set_cursor_shape __P((void));
168 void get_cursor_shape __P((void));
169 void async_update __P((void));
170 void do_async_update __P((u_char));
171 
172 void pccnputc __P((dev_t, int c));
173 int pccngetc __P((dev_t));
174 void pccnpollc __P((dev_t, int));
175 
176 extern struct cfdriver pc_cd;
177 
178 dev_type_open(pcopen);
179 dev_type_close(pcclose);
180 dev_type_read(pcread);
181 dev_type_write(pcwrite);
182 dev_type_ioctl(pcioctl);
183 dev_type_tty(pctty);
184 dev_type_poll(pcpoll);
185 dev_type_mmap(pcmmap);
186 
187 const struct cdevsw pc_cdevsw = {
188 	pcopen, pcclose, pcread, pcwrite, pcioctl,
189 	nostop, pctty, pcpoll, pcmmap, ttykqfilter, D_TTY
190 };
191 
192 #define	CHR		2
193 
194 char *sget __P((void));
195 void sput __P((u_char *, int));
196 
197 void	pcstart __P((struct tty *));
198 int	pcparam __P((struct tty *, struct termios *));
199 static __inline void wcopy __P((void *, void *, u_int));
200 void	pc_context_init __P((bus_space_tag_t, bus_space_tag_t, bus_space_tag_t,
201 	    struct pccons_config *));
202 
203 extern void fillw __P((int, u_int16_t *, int));
204 
205 #define	KBD_DELAY \
206 		DELAY(10);
207 
208 #define crtc_read_1(reg) \
209 	bus_space_read_1(pccons_console_context.pc_crt_iot, \
210 	    pccons_console_context.pc_6845_ioh, reg)
211 #define crtc_write_1(reg, data) \
212 	bus_space_write_1(pccons_console_context.pc_crt_iot, \
213 	    pccons_console_context.pc_6845_ioh, reg, data)
214 
215 struct pccons_context pccons_console_context;
216 
217 void
218 kbd_context_init(kbd_iot, config)
219 	bus_space_tag_t kbd_iot;
220 	struct pccons_config *config;
221 {
222 	struct pccons_kbd_context *pkc = &pccons_console_context.pc_pkc;
223 
224 	if (pkc->pkc_initialized)
225 		return;
226 	pkc->pkc_initialized = 1;
227 
228 	pkc->pkc_iot = kbd_iot;
229 
230 	bus_space_map(kbd_iot, config->pc_kbd_cmdp, 1, 0,
231 	    &pkc->pkc_cmd_ioh);
232 	bus_space_map(kbd_iot, config->pc_kbd_datap, 1, 0,
233 	    &pkc->pkc_data_ioh);
234 }
235 
236 void
237 pc_context_init(crt_iot, crt_memt, kbd_iot, config)
238 	bus_space_tag_t crt_iot, crt_memt, kbd_iot;
239 	struct pccons_config *config;
240 {
241 	struct pccons_context *pc = &pccons_console_context;
242 
243 	if (pc->pc_initialized)
244 		return;
245 	pc->pc_initialized = 1;
246 
247 	kbd_context_init(kbd_iot, config);
248 
249 	pc->pc_crt_iot = crt_iot;
250 	pc->pc_crt_memt = crt_memt;
251 
252 	bus_space_map(crt_iot, config->pc_mono_iobase, 2, 0,
253 	    &pc->pc_mono_ioh);
254 	bus_space_map(crt_memt, config->pc_mono_memaddr, 0x20000, 0,
255 	    &pc->pc_mono_memh);
256 	bus_space_map(crt_iot, config->pc_cga_iobase, 2, 0,
257 	    &pc->pc_cga_ioh);
258 	bus_space_map(crt_memt, config->pc_cga_memaddr, 0x20000, 0,
259 	    &pc->pc_cga_memh);
260 
261 	/*
262 	 * pc->pc_6845_ioh and pc->pc_crt_memh will be initialized later,
263 	 * when `Crtat' is initialized.
264 	 */
265 
266 	pc->pc_config = config;
267 
268 	(*config->pc_init)();
269 }
270 
271 /*
272  * bcopy variant that only moves word-aligned 16-bit entities,
273  * for stupid VGA cards.  cnt is required to be an even vale.
274  */
275 static __inline void
276 wcopy(src, tgt, cnt)
277 	void *src, *tgt;
278 	u_int cnt;
279 {
280 	u_int16_t *from = src;
281 	u_int16_t *to = tgt;
282 
283 	cnt >>= 1;
284 	if (to < from || to >= from + cnt)
285 		while(cnt--)
286 			*to++ = *from++;
287 	else {
288 		to += cnt;
289 		from += cnt;
290 		while(cnt--)
291 			*--to = *--from;
292 	}
293 }
294 
295 static __inline int
296 kbd_wait_output()
297 {
298 	u_int i;
299 
300 	for (i = 100000; i; i--)
301 		if ((kbd_cmd_read_1() & KBS_IBF) == 0) {
302 			KBD_DELAY;
303 			return 1;
304 		}
305 	return 0;
306 }
307 
308 static __inline int
309 kbd_wait_input()
310 {
311 	u_int i;
312 
313 	for (i = 100000; i; i--)
314 		if ((kbd_cmd_read_1() & KBS_DIB) != 0) {
315 			KBD_DELAY;
316 			return 1;
317 		}
318 	return 0;
319 }
320 
321 void
322 kbd_flush_input()
323 {
324 	u_char c;
325 
326 	while ((c = kbd_cmd_read_1()) & 0x03)
327 		if ((c & KBS_DIB) == KBS_DIB) {
328 			/* XXX - delay is needed to prevent some keyboards from
329 			   wedging when the system boots */
330 			delay(6);
331 			(void) kbd_data_read_1();
332 		}
333 }
334 
335 #if 1
336 /*
337  * Get the current command byte.
338  */
339 static u_char
340 kbc_get8042cmd()
341 {
342 
343 	if (!kbd_wait_output())
344 		return -1;
345 	kbd_cmd_write_1(K_RDCMDBYTE);
346 	if (!kbd_wait_input())
347 		return -1;
348 	return kbd_data_read_1();
349 }
350 #endif
351 
352 /*
353  * Pass command byte to keyboard controller (8042).
354  */
355 int
356 kbc_put8042cmd(val)
357 	u_char val;
358 {
359 
360 	if (!kbd_wait_output())
361 		return 0;
362 	kbd_cmd_write_1(K_LDCMDBYTE);
363 	if (!kbd_wait_output())
364 		return 0;
365 	kbd_data_write_1(val);
366 	return 1;
367 }
368 
369 /*
370  * Pass command to keyboard itself
371  */
372 int
373 kbd_cmd(val, polling)
374 	u_char val;
375 	u_char polling;
376 {
377 	u_int retries = 3;
378 	u_int i;
379 
380 	if(!polling) {
381 		i = spltty();
382 		if(kb_oq_get == kb_oq_put) {
383 			kbd_data_write_1(val);
384 		}
385 		kb_oq[kb_oq_put] = val;
386 		kb_oq_put = (kb_oq_put + 1) & 7;
387 		splx(i);
388 		return(1);
389 	}
390 	else do {
391 		if (!kbd_wait_output())
392 			return 0;
393 		kbd_data_write_1(val);
394 		for (i = 100000; i; i--) {
395 			if (kbd_cmd_read_1() & KBS_DIB) {
396 				u_char c;
397 
398 				KBD_DELAY;
399 				c = kbd_data_read_1();
400 				if (c == KBR_ACK || c == KBR_ECHO) {
401 					return 1;
402 				}
403 				if (c == KBR_RESEND) {
404 					break;
405 				}
406 #ifdef DIAGNOSTIC
407 				printf("kbd_cmd: input char %x lost\n", c);
408 #endif
409 			}
410 		}
411 	} while (--retries);
412 	return 0;
413 }
414 
415 void
416 set_cursor_shape()
417 {
418 	crtc_write_1(0, 10);
419 	crtc_write_1(1, cursor_shape >> 8);
420 	crtc_write_1(0, 11);
421 	crtc_write_1(1, cursor_shape);
422 	old_cursor_shape = cursor_shape;
423 }
424 
425 void
426 get_cursor_shape()
427 {
428 	crtc_write_1(0, 10);
429 	cursor_shape = crtc_read_1(1) << 8;
430 	crtc_write_1(0, 11);
431 	cursor_shape |= crtc_read_1(1);
432 
433 	/*
434 	 * real 6845's, as found on, MDA, Hercules or CGA cards, do
435 	 * not support reading the cursor shape registers. the 6845
436 	 * tri-states it's data bus. This is _normally_ read by the
437 	 * cpu as either 0x00 or 0xff.. in which case we just use
438 	 * a line cursor.
439 	 */
440 	if (cursor_shape == 0x0000 || cursor_shape == 0xffff)
441 		cursor_shape = 0x0b10;
442 	else
443 		cursor_shape &= 0x1f1f;
444 }
445 
446 void
447 do_async_update(poll)
448 	u_char poll;
449 {
450 	int pos;
451 	static int old_pos = -1;
452 
453 	async = 0;
454 
455 	if (lock_state != old_lock_state) {
456 		old_lock_state = lock_state;
457 		if (!kbd_cmd(KBC_MODEIND, poll) ||
458 		    !kbd_cmd(lock_state, poll)) {
459 			printf("pc: timeout updating leds\n");
460 			(void) kbd_cmd(KBC_ENABLE, poll);
461 		}
462 	}
463 	if (typematic_rate != old_typematic_rate) {
464 		old_typematic_rate = typematic_rate;
465 		if (!kbd_cmd(KBC_TYPEMATIC, poll) ||
466 		    !kbd_cmd(typematic_rate, poll)) {
467 			printf("pc: timeout updating typematic rate\n");
468 			(void) kbd_cmd(KBC_ENABLE, poll);
469 		}
470 	}
471 
472 	if (pc_xmode > 0)
473 		return;
474 
475 	pos = crtat - Crtat;
476 	if (pos != old_pos) {
477 		crtc_write_1(0, 14);
478 		crtc_write_1(1, pos >> 8);
479 		crtc_write_1(0, 15);
480 		crtc_write_1(1, pos);
481 		old_pos = pos;
482 	}
483 	if (cursor_shape != old_cursor_shape)
484 		set_cursor_shape();
485 }
486 
487 void
488 async_update()
489 {
490 
491 	if (kernel || polling) {
492 		if (async)
493 			callout_stop(&async_update_ch);
494 		do_async_update(1);
495 	} else {
496 		if (async)
497 			return;
498 		async = 1;
499 		callout_reset(&async_update_ch, 1,
500 		    (void(*)(void *))do_async_update, NULL);
501 	}
502 }
503 
504 /*
505  * these are both bad jokes
506  */
507 int
508 pccons_common_match(crt_iot, crt_memt, kbd_iot, config)
509 	bus_space_tag_t crt_iot, crt_memt, kbd_iot;
510 	struct pccons_config *config;
511 {
512 	int i;
513 
514 	pc_context_init(crt_iot, crt_memt, kbd_iot, config);
515 
516 	/* Enable interrupts and keyboard, etc. */
517 	if (!kbc_put8042cmd(CMDBYTE)) {
518 		printf("pcprobe: command error\n");
519 		return 0;
520 	}
521 
522 #if 1
523 	/* Flush any garbage. */
524 	kbd_flush_input();
525 	/* Reset the keyboard. */
526 	if (!kbd_cmd(KBC_RESET, 1)) {
527 		printf("pcprobe: reset error %d\n", 1);
528 		goto lose;
529 	}
530 	for (i = 600000; i; i--)
531 		if ((kbd_cmd_read_1() & KBS_DIB) != 0) {
532 			KBD_DELAY;
533 			break;
534 		}
535 	if (i == 0 || kbd_data_read_1() != KBR_RSTDONE) {
536 		printf("pcprobe: reset error %d\n", 2);
537 		goto lose;
538 	}
539 	/*
540 	 * Some keyboards seem to leave a second ack byte after the reset.
541 	 * This is kind of stupid, but we account for them anyway by just
542 	 * flushing the buffer.
543 	 */
544 	kbd_flush_input();
545 	/* Just to be sure. */
546 	if (!kbd_cmd(KBC_ENABLE, 1)) {
547 		printf("pcprobe: reset error %d\n", 3);
548 		goto lose;
549 	}
550 
551 	/*
552 	 * Some keyboard/8042 combinations do not seem to work if the keyboard
553 	 * is set to table 1; in fact, it would appear that some keyboards just
554 	 * ignore the command altogether.  So by default, we use the AT scan
555 	 * codes and have the 8042 translate them.  Unfortunately, this is
556 	 * known to not work on some PS/2 machines.  We try desparately to deal
557 	 * with this by checking the (lack of a) translate bit in the 8042 and
558 	 * attempting to set the keyboard to XT mode.  If this all fails, well,
559 	 * tough luck.
560 	 *
561 	 * XXX It would perhaps be a better choice to just use AT scan codes
562 	 * and not bother with this.
563 	 */
564 	if (kbc_get8042cmd() & KC8_TRANS) {
565 		/* The 8042 is translating for us; use AT codes. */
566 		if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(2, 1)) {
567 			printf("pcprobe: reset error %d\n", 4);
568 			goto lose;
569 		}
570 	} else {
571 		/* Stupid 8042; set keyboard to XT codes. */
572 		if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(1, 1)) {
573 			printf("pcprobe: reset error %d\n", 5);
574 			goto lose;
575 		}
576 	}
577 
578 lose:
579 	/*
580 	 * Technically, we should probably fail the probe.  But we'll be nice
581 	 * and allow keyboard-less machines to boot with the console.
582 	 */
583 #endif
584 
585 	return 1;
586 }
587 
588 void pccons_common_attach(sc, crt_iot, crt_memt, kbd_iot, config)
589 	struct pc_softc *sc;
590 	bus_space_tag_t crt_iot, crt_memt, kbd_iot;
591 	struct pccons_config *config;
592 {
593 	printf(": %s\n", vs.color ? "color" : "mono");
594 	do_async_update(1);
595 }
596 
597 int
598 pcopen(dev, flag, mode, p)
599 	dev_t dev;
600 	int flag, mode;
601 	struct proc *p;
602 {
603 	struct pc_softc *sc;
604 	int unit = PCUNIT(dev);
605 	struct tty *tp;
606 
607 	if (unit >= pc_cd.cd_ndevs)
608 		return ENXIO;
609 	sc = pc_cd.cd_devs[unit];
610 	if (sc == 0)
611 		return ENXIO;
612 
613 	if (!sc->sc_tty) {
614 		tp = sc->sc_tty = ttymalloc();
615 	}
616 	else {
617 		tp = sc->sc_tty;
618 	}
619 
620 	tp->t_oproc = pcstart;
621 	tp->t_param = pcparam;
622 	tp->t_dev = dev;
623 	if ((tp->t_state & TS_ISOPEN) == 0) {
624 		ttychars(tp);
625 		tp->t_iflag = TTYDEF_IFLAG;
626 		tp->t_oflag = TTYDEF_OFLAG;
627 		tp->t_cflag = TTYDEF_CFLAG;
628 		tp->t_lflag = TTYDEF_LFLAG;
629 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
630 		pcparam(tp, &tp->t_termios);
631 		ttsetwater(tp);
632 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
633 		return EBUSY;
634 	tp->t_state |= TS_CARR_ON;
635 
636 	return ((*tp->t_linesw->l_open)(dev, tp));
637 }
638 
639 int
640 pcclose(dev, flag, mode, p)
641 	dev_t dev;
642 	int flag, mode;
643 	struct proc *p;
644 {
645 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
646 	struct tty *tp = sc->sc_tty;
647 
648 	(*tp->t_linesw->l_close)(tp, flag);
649 	ttyclose(tp);
650 #ifdef notyet /* XXX */
651 	ttyfree(tp);
652 #endif
653 	return(0);
654 }
655 
656 int
657 pcread(dev, uio, flag)
658 	dev_t dev;
659 	struct uio *uio;
660 	int flag;
661 {
662 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
663 	struct tty *tp = sc->sc_tty;
664 
665 	return ((*tp->t_linesw->l_read)(tp, uio, flag));
666 }
667 
668 int
669 pcwrite(dev, uio, flag)
670 	dev_t dev;
671 	struct uio *uio;
672 	int flag;
673 {
674 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
675 	struct tty *tp = sc->sc_tty;
676 
677 	return ((*tp->t_linesw->l_write)(tp, uio, flag));
678 }
679 
680 int
681 pcpoll(dev, events, p)
682 	dev_t dev;
683 	int events;
684 	struct proc *p;
685 {
686 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
687 	struct tty *tp = sc->sc_tty;
688 
689 	return ((*tp->t_linesw->l_poll)(tp, events, p));
690 }
691 
692 struct tty *
693 pctty(dev)
694 	dev_t dev;
695 {
696 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
697 	struct tty *tp = sc->sc_tty;
698 
699 	return (tp);
700 }
701 
702 /*
703  * Got a console receive interrupt -
704  * the console processor wants to give us a character.
705  * Catch the character, and see who it goes to.
706  */
707 int
708 pcintr(arg)
709 	void *arg;
710 {
711 	struct pc_softc *sc = arg;
712 	struct tty *tp = sc->sc_tty;
713 	u_char *cp;
714 
715 	if ((kbd_cmd_read_1() & KBS_DIB) == 0)
716 		return 0;
717 	if (polling)
718 		return 1;
719 	do {
720 		cp = sget();
721 		if (!tp || (tp->t_state & TS_ISOPEN) == 0)
722 			return 1;
723 		if (cp)
724 			do
725 				(*tp->t_linesw->l_rint)(*cp++, tp);
726 			while (*cp);
727 	} while (kbd_cmd_read_1() & KBS_DIB);
728 	return 1;
729 }
730 
731 int
732 pcioctl(dev, cmd, data, flag, p)
733 	dev_t dev;
734 	u_long cmd;
735 	caddr_t data;
736 	int flag;
737 	struct proc *p;
738 {
739 	struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
740 	struct tty *tp = sc->sc_tty;
741 	int error;
742 
743 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
744 	if (error != EPASSTHROUGH)
745 		return error;
746 	error = ttioctl(tp, cmd, data, flag, p);
747 	if (error != EPASSTHROUGH)
748 		return error;
749 
750 	switch (cmd) {
751 	case CONSOLE_X_MODE_ON:
752 		pc_xmode_on();
753 		return 0;
754 	case CONSOLE_X_MODE_OFF:
755 		pc_xmode_off();
756 		return 0;
757 	case CONSOLE_X_BELL:
758 		/*
759 		 * If set, data is a pointer to a length 2 array of
760 		 * integers.  data[0] is the pitch in Hz and data[1]
761 		 * is the duration in msec.
762 		 */
763 		if (data)
764 			sysbeep(((int*)data)[0],
765 				(((int*)data)[1] * hz) / 1000);
766 		else
767 			sysbeep(BEEP_FREQ, BEEP_TIME);
768 		return 0;
769 	case CONSOLE_SET_TYPEMATIC_RATE: {
770  		u_char	rate;
771 
772  		if (!data)
773 			return EINVAL;
774 		rate = *((u_char *)data);
775 		/*
776 		 * Check that it isn't too big (which would cause it to be
777 		 * confused with a command).
778 		 */
779 		if (rate & 0x80)
780 			return EINVAL;
781 		typematic_rate = rate;
782 		async_update();
783 		return 0;
784  	}
785 	case CONSOLE_SET_KEYMAP: {
786 		pccons_keymap_t *map = (pccons_keymap_t *) data;
787 		int i;
788 
789 		if (!data)
790 			return EINVAL;
791 		for (i = 0; i < KB_NUM_KEYS; i++)
792 			if (map[i].unshift[KB_CODE_SIZE-1] ||
793 			    map[i].shift[KB_CODE_SIZE-1] ||
794 			    map[i].ctl[KB_CODE_SIZE-1] ||
795 			    map[i].altgr[KB_CODE_SIZE-1] ||
796 			    map[i].shift_altgr[KB_CODE_SIZE-1])
797 				return EINVAL;
798 
799 		bcopy(data, scan_codes, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
800 		return 0;
801 	}
802 	case CONSOLE_GET_KEYMAP:
803 		if (!data)
804 			return EINVAL;
805 		bcopy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
806 		return 0;
807 
808 	default:
809 		return EPASSTHROUGH;
810 	}
811 
812 #ifdef DIAGNOSTIC
813 	panic("pcioctl: impossible");
814 #endif
815 }
816 
817 void
818 pcstart(tp)
819 	struct tty *tp;
820 {
821 	struct clist *cl;
822 	int s, len;
823 	u_char buf[PCBURST];
824 
825 	s = spltty();
826 	if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
827 		goto out;
828 	tp->t_state |= TS_BUSY;
829 	splx(s);
830 	/*
831 	 * We need to do this outside spl since it could be fairly
832 	 * expensive and we don't want our serial ports to overflow.
833 	 */
834 	cl = &tp->t_outq;
835 	len = q_to_b(cl, buf, PCBURST);
836 	sput(buf, len);
837 	s = spltty();
838 	tp->t_state &= ~TS_BUSY;
839 	if (cl->c_cc) {
840 		tp->t_state |= TS_TIMEOUT;
841 		callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp);
842 	}
843 	if (cl->c_cc <= tp->t_lowat) {
844 		if (tp->t_state & TS_ASLEEP) {
845 			tp->t_state &= ~TS_ASLEEP;
846 			wakeup(cl);
847 		}
848 		selwakeup(&tp->t_wsel);
849 	}
850 out:
851 	splx(s);
852 }
853 
854 /* ARGSUSED */
855 void pccons_common_cnattach(crt_iot, crt_memt, kbd_iot, config)
856 	bus_space_tag_t crt_iot, crt_memt, kbd_iot;
857 	struct pccons_config *config;
858 {
859 	int maj;
860 	static struct consdev pccons = {
861 		NULL, NULL, pccngetc, pccnputc, pccnpollc, NULL, NULL,
862 		    NULL, NODEV, CN_NORMAL
863 	};
864 
865 	/*
866 	 * For now, don't screw with it.
867 	 */
868 	/* crtat = 0; */
869 
870 	pc_context_init(crt_iot, crt_memt, kbd_iot, config);
871 
872 	/* locate the major number */
873 	maj = cdevsw_lookup_major(&pc_cdevsw);
874 	pccons.cn_dev = makedev(maj, 0);
875 
876 	cn_tab = &pccons;
877 }
878 
879 /* ARGSUSED */
880 void
881 pccnputc(dev, c)
882 	dev_t dev;
883 	int c;
884 {
885 	u_char cc, oldkernel = kernel;
886 
887 	kernel = 1;
888 	if (c == '\n') {
889 		sput("\r\n", 2);
890 	} else {
891 		cc = c;
892 		sput(&cc, 1);
893 	}
894 	kernel = oldkernel;
895 }
896 
897 /* ARGSUSED */
898 int
899 pccngetc(dev)
900 	dev_t dev;
901 {
902 	char *cp;
903 
904 	if (pc_xmode > 0)
905 		return 0;
906 
907 	do {
908 		/* wait for byte */
909 		while ((kbd_cmd_read_1() & KBS_DIB) == 0);
910 		/* see if it's worthwhile */
911 		cp = sget();
912 	} while (!cp);
913 	if (*cp == '\r')
914 		return '\n';
915 	return *cp;
916 }
917 
918 void
919 pccnpollc(dev, on)
920 	dev_t dev;
921 	int on;
922 {
923 
924 	polling = on;
925 	if (!on) {
926 		int unit;
927 		struct pc_softc *sc;
928 		int s;
929 
930 		/*
931 		 * If disabling polling on a device that's been configured,
932 		 * make sure there are no bytes left in the FIFO, holding up
933 		 * the interrupt line.  Otherwise we won't get any further
934 		 * interrupts.
935 		 */
936 		unit = PCUNIT(dev);
937 		if (pc_cd.cd_ndevs > unit) {
938 			sc = pc_cd.cd_devs[unit];
939 			if (sc != 0) {
940 				s = spltty();
941 				pcintr(sc);
942 				splx(s);
943 			}
944 		}
945 	}
946 }
947 
948 /*
949  * Set line parameters.
950  */
951 int
952 pcparam(tp, t)
953 	struct tty *tp;
954 	struct termios *t;
955 {
956 
957 	tp->t_ispeed = t->c_ispeed;
958 	tp->t_ospeed = t->c_ospeed;
959 	tp->t_cflag = t->c_cflag;
960 	return 0;
961 }
962 
963 #define	wrtchar(c, at) do {\
964 	char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; \
965 } while (0)
966 
967 /* translate ANSI color codes to standard pc ones */
968 static char fgansitopc[] = {
969 	FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
970 	FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
971 };
972 
973 static char bgansitopc[] = {
974 	BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
975 	BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
976 };
977 
978 static u_char iso2ibm437[] =
979 {
980             0,     0,     0,     0,     0,     0,     0,     0,
981             0,     0,     0,     0,     0,     0,     0,     0,
982             0,     0,     0,     0,     0,     0,     0,     0,
983             0,     0,     0,     0,     0,     0,     0,     0,
984          0xff,  0xad,  0x9b,  0x9c,     0,  0x9d,     0,  0x40,
985          0x6f,  0x63,  0x61,  0xae,     0,     0,     0,     0,
986          0xf8,  0xf1,  0xfd,  0x33,     0,  0xe6,     0,  0xfa,
987             0,  0x31,  0x6f,  0xaf,  0xac,  0xab,     0,  0xa8,
988          0x41,  0x41,  0x41,  0x41,  0x8e,  0x8f,  0x92,  0x80,
989          0x45,  0x90,  0x45,  0x45,  0x49,  0x49,  0x49,  0x49,
990          0x81,  0xa5,  0x4f,  0x4f,  0x4f,  0x4f,  0x99,  0x4f,
991          0x4f,  0x55,  0x55,  0x55,  0x9a,  0x59,     0,  0xe1,
992          0x85,  0xa0,  0x83,  0x61,  0x84,  0x86,  0x91,  0x87,
993          0x8a,  0x82,  0x88,  0x89,  0x8d,  0xa1,  0x8c,  0x8b,
994             0,  0xa4,  0x95,  0xa2,  0x93,  0x6f,  0x94,  0x6f,
995          0x6f,  0x97,  0xa3,  0x96,  0x81,  0x98,     0,     0
996 };
997 
998 /*
999  * `pc3' termcap emulation.
1000  */
1001 void
1002 sput(cp, n)
1003 	u_char *cp;
1004 	int n;
1005 {
1006 	struct pccons_context *pc = &pccons_console_context;
1007 	u_char c, scroll = 0;
1008 
1009 	if (pc_xmode > 0)
1010 		return;
1011 
1012 	if (crtat == 0) {
1013 		volatile u_short *cp;
1014 		u_short was;
1015 		unsigned cursorat;
1016 
1017 		cp = bus_space_vaddr(pc->pc_crt_memt, pc->pc_cga_memh);
1018 		was = *cp;
1019 		*cp = 0xA55A;
1020 		if (*cp != 0xA55A) {
1021 			cp = bus_space_vaddr(pc->pc_crt_memt,
1022 			    pc->pc_mono_memh);
1023 			pc->pc_6845_ioh = pc->pc_mono_ioh;
1024 			pc->pc_crt_memh = pc->pc_mono_memh;
1025 			vs.color = 0;
1026 		} else {
1027 			*cp = was;
1028 			pc->pc_6845_ioh = pc->pc_cga_ioh;
1029 			pc->pc_crt_memh = pc->pc_cga_memh;
1030 			vs.color = 1;
1031 		}
1032 
1033 #ifdef FAT_CURSOR
1034 		cursor_shape = 0x0012;
1035 #else
1036 		get_cursor_shape();
1037 #endif
1038 
1039 		bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow);
1040 		vs.nchr = vs.ncol * vs.nrow;
1041 		vs.col--;
1042 		vs.row--;
1043 		cursorat = vs.ncol * vs.row + vs.col;
1044 		vs.at = FG_LIGHTGREY | BG_BLACK;
1045 
1046 		Crtat = (u_short *)cp;
1047 		crtat = Crtat + cursorat;
1048 
1049 		if (vs.color == 0)
1050 			vs.so_at = FG_BLACK | BG_LIGHTGREY;
1051 		else
1052 			vs.so_at = FG_YELLOW | BG_BLACK;
1053 
1054 		fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
1055 	}
1056 
1057 	while (n--) {
1058 		if (!(c = *cp++))
1059 			continue;
1060 
1061 		switch (c) {
1062 		case 0x1B:
1063 			if (vs.state >= VSS_ESCAPE) {
1064 				wrtchar(c, vs.so_at);
1065 				vs.state = 0;
1066 				goto maybe_scroll;
1067 			} else
1068 				vs.state = VSS_ESCAPE;
1069 			break;
1070 
1071 		case 0x9B:	/* CSI */
1072 			vs.cx = vs.cy = 0;
1073 			vs.state = VSS_EBRACE;
1074 			break;
1075 
1076 		case '\t': {
1077 			int inccol = 8 - (vs.col & 7);
1078 			crtat += inccol;
1079 			vs.col += inccol;
1080 		}
1081 		maybe_scroll:
1082 			if (vs.col >= vs.ncol) {
1083 				vs.col -= vs.ncol;
1084 				scroll = 1;
1085 			}
1086 			break;
1087 
1088 		case '\b':
1089 			if (crtat <= Crtat)
1090 				break;
1091 			--crtat;
1092 			if (--vs.col < 0)
1093 				vs.col += vs.ncol;	/* non-destructive backspace */
1094 			break;
1095 
1096 		case '\r':
1097 			crtat -= vs.col;
1098 			vs.col = 0;
1099 			break;
1100 
1101 		case '\n':
1102 			crtat += vs.ncol;
1103 			scroll = 1;
1104 			break;
1105 
1106 		default:
1107 			switch (vs.state) {
1108 			case 0:
1109 				if (c == '\a')
1110 					sysbeep(BEEP_FREQ, BEEP_TIME);
1111 				else {
1112 					/*
1113 					 * If we're outputting multiple printed
1114 					 * characters, just blast them to the
1115 					 * screen until we reach the end of the
1116 					 * buffer or a control character.  This
1117 					 * saves time by short-circuiting the
1118 					 * switch.
1119 					 * If we reach the end of the line, we
1120 					 * break to do a scroll check.
1121 					 */
1122 					for (;;) {
1123 						if (c & 0x80)
1124 							c = iso2ibm437[c&0x7f];
1125 
1126 						if (vs.so)
1127 							wrtchar(c, vs.so_at);
1128 						else
1129 							wrtchar(c, vs.at);
1130 						if (vs.col >= vs.ncol) {
1131 							vs.col = 0;
1132 							scroll = 1;
1133 							break;
1134 						}
1135 						if (!n || (c = *cp) < ' ')
1136 							break;
1137 						n--, cp++;
1138 					}
1139 				}
1140 				break;
1141 			case VSS_ESCAPE:
1142 				switch (c) {
1143 					case '[': /* Start ESC [ sequence */
1144 						vs.cx = vs.cy = 0;
1145 						vs.state = VSS_EBRACE;
1146 						break;
1147 					case 'c': /* Create screen & home */
1148 						fillw((vs.at << 8) | ' ',
1149 						    Crtat, vs.nchr);
1150 						crtat = Crtat;
1151 						vs.col = 0;
1152 						vs.state = 0;
1153 						break;
1154 					case '7': /* save cursor pos */
1155 						vs.offset = crtat - Crtat;
1156 						vs.state = 0;
1157 						break;
1158 					case '8': /* restore cursor pos */
1159 						crtat = Crtat + vs.offset;
1160 						vs.row = vs.offset / vs.ncol;
1161 						vs.col = vs.offset % vs.ncol;
1162 						vs.state = 0;
1163 						break;
1164 					default: /* Invalid, clear state */
1165 						wrtchar(c, vs.so_at);
1166 						vs.state = 0;
1167 						goto maybe_scroll;
1168 				}
1169 				break;
1170 
1171 			default: /* VSS_EBRACE or VSS_EPARAM */
1172 				switch (c) {
1173 					int pos;
1174 				case 'm':
1175 					if (!vs.cx)
1176 						vs.so = 0;
1177 					else
1178 						vs.so = 1;
1179 					vs.state = 0;
1180 					break;
1181 				case 'A': { /* back cx rows */
1182 					int cx = vs.cx;
1183 					if (cx <= 0)
1184 						cx = 1;
1185 					else
1186 						cx %= vs.nrow;
1187 					pos = crtat - Crtat;
1188 					pos -= vs.ncol * cx;
1189 					if (pos < 0)
1190 						pos += vs.nchr;
1191 					crtat = Crtat + pos;
1192 					vs.state = 0;
1193 					break;
1194 				}
1195 				case 'B': { /* down cx rows */
1196 					int cx = vs.cx;
1197 					if (cx <= 0)
1198 						cx = 1;
1199 					else
1200 						cx %= vs.nrow;
1201 					pos = crtat - Crtat;
1202 					pos += vs.ncol * cx;
1203 					if (pos >= vs.nchr)
1204 						pos -= vs.nchr;
1205 					crtat = Crtat + pos;
1206 					vs.state = 0;
1207 					break;
1208 				}
1209 				case 'C': { /* right cursor */
1210 					int cx = vs.cx,
1211 					    col = vs.col;
1212 					if (cx <= 0)
1213 						cx = 1;
1214 					else
1215 						cx %= vs.ncol;
1216 					pos = crtat - Crtat;
1217 					pos += cx;
1218 					col += cx;
1219 					if (col >= vs.ncol) {
1220 						pos -= vs.ncol;
1221 						col -= vs.ncol;
1222 					}
1223 					vs.col = col;
1224 					crtat = Crtat + pos;
1225 					vs.state = 0;
1226 					break;
1227 				}
1228 				case 'D': { /* left cursor */
1229 					int cx = vs.cx,
1230 					    col = vs.col;
1231 					if (cx <= 0)
1232 						cx = 1;
1233 					else
1234 						cx %= vs.ncol;
1235 					pos = crtat - Crtat;
1236 					pos -= cx;
1237 					col -= cx;
1238 					if (col < 0) {
1239 						pos += vs.ncol;
1240 						col += vs.ncol;
1241 					}
1242 					vs.col = col;
1243 					crtat = Crtat + pos;
1244 					vs.state = 0;
1245 					break;
1246 				}
1247 				case 'J': /* Clear ... */
1248 					switch (vs.cx) {
1249 					case 0:
1250 						/* ... to end of display */
1251 						fillw((vs.at << 8) | ' ',
1252 						    crtat,
1253 						    Crtat + vs.nchr - crtat);
1254 						break;
1255 					case 1:
1256 						/* ... to next location */
1257 						fillw((vs.at << 8) | ' ',
1258 						    Crtat,
1259 						    crtat - Crtat + 1);
1260 						break;
1261 					case 2:
1262 						/* ... whole display */
1263 						fillw((vs.at << 8) | ' ',
1264 						    Crtat,
1265 						    vs.nchr);
1266 						break;
1267 					}
1268 					vs.state = 0;
1269 					break;
1270 				case 'K': /* Clear line ... */
1271 					switch (vs.cx) {
1272 					case 0:
1273 						/* ... current to EOL */
1274 						fillw((vs.at << 8) | ' ',
1275 						    crtat,
1276 						    vs.ncol - vs.col);
1277 						break;
1278 					case 1:
1279 						/* ... beginning to next */
1280 						fillw((vs.at << 8) | ' ',
1281 						    crtat - vs.col,
1282 						    vs.col + 1);
1283 						break;
1284 					case 2:
1285 						/* ... entire line */
1286 						fillw((vs.at << 8) | ' ',
1287 						    crtat - vs.col, vs.ncol);
1288 						break;
1289 					}
1290 					vs.state = 0;
1291 					break;
1292 				case 'f': /* in system V consoles */
1293 				case 'H': { /* Cursor move */
1294 					int cx = vs.cx,
1295 					    cy = vs.cy;
1296 					if (!cx || !cy) {
1297 						crtat = Crtat;
1298 						vs.col = 0;
1299 					} else {
1300 						if (cx > vs.nrow)
1301 							cx = vs.nrow;
1302 						if (cy > vs.ncol)
1303 							cy = vs.ncol;
1304 						crtat = Crtat +
1305 						    (cx - 1) * vs.ncol + cy - 1;
1306 						vs.col = cy - 1;
1307 					}
1308 					vs.state = 0;
1309 					break;
1310 				}
1311 				case 'M': { /* delete cx rows */
1312 					u_short *crtAt = crtat - vs.col;
1313 					int cx = vs.cx,
1314 					    row = (crtAt - Crtat) / vs.ncol,
1315 					    nrow = vs.nrow - row;
1316 					if (cx <= 0)
1317 						cx = 1;
1318 					else if (cx > nrow)
1319 						cx = nrow;
1320 					if (cx < nrow)
1321 #ifdef PCCONS_FORCE_WORD
1322 						wcopy(crtAt + vs.ncol * cx,
1323 						    crtAt, vs.ncol * (nrow -
1324 						    cx) * CHR);
1325 #else
1326 						bcopy(crtAt + vs.ncol * cx,
1327 						    crtAt, vs.ncol * (nrow -
1328 						    cx) * CHR);
1329 #endif
1330 					fillw((vs.at << 8) | ' ',
1331 					    crtAt + vs.ncol * (nrow - cx),
1332 					    vs.ncol * cx);
1333 					vs.state = 0;
1334 					break;
1335 				}
1336 				case 'S': { /* scroll up cx lines */
1337 					int cx = vs.cx;
1338 					if (cx <= 0)
1339 						cx = 1;
1340 					else if (cx > vs.nrow)
1341 						cx = vs.nrow;
1342 					if (cx < vs.nrow)
1343 #ifdef PCCONS_FORCE_WORD
1344 						wcopy(Crtat + vs.ncol * cx,
1345 						    Crtat, vs.ncol * (vs.nrow -
1346 						    cx) * CHR);
1347 #else
1348 						bcopy(Crtat + vs.ncol * cx,
1349 						    Crtat, vs.ncol * (vs.nrow -
1350 						    cx) * CHR);
1351 #endif
1352 					fillw((vs.at << 8) | ' ',
1353 					    Crtat + vs.ncol * (vs.nrow - cx),
1354 					    vs.ncol * cx);
1355 					/* crtat -= vs.ncol * cx; XXX */
1356 					vs.state = 0;
1357 					break;
1358 				}
1359 				case 'L': { /* insert cx rows */
1360 					u_short *crtAt = crtat - vs.col;
1361 					int cx = vs.cx,
1362 					    row = (crtAt - Crtat) / vs.ncol,
1363 					    nrow = vs.nrow - row;
1364 					if (cx <= 0)
1365 						cx = 1;
1366 					else if (cx > nrow)
1367 						cx = nrow;
1368 					if (cx < nrow)
1369 #ifdef PCCONS_FORCE_WORD
1370 						wcopy(crtAt,
1371 						    crtAt + vs.ncol * cx,
1372 						    vs.ncol * (nrow - cx) *
1373 						    CHR);
1374 #else
1375 						bcopy(crtAt,
1376 						    crtAt + vs.ncol * cx,
1377 						    vs.ncol * (nrow - cx) *
1378 						    CHR);
1379 #endif
1380 					fillw((vs.at << 8) | ' ', crtAt,
1381 					    vs.ncol * cx);
1382 					vs.state = 0;
1383 					break;
1384 				}
1385 				case 'T': { /* scroll down cx lines */
1386 					int cx = vs.cx;
1387 					if (cx <= 0)
1388 						cx = 1;
1389 					else if (cx > vs.nrow)
1390 						cx = vs.nrow;
1391 					if (cx < vs.nrow)
1392 #ifdef PCCONS_FORCE_WORD
1393 						wcopy(Crtat,
1394 						    Crtat + vs.ncol * cx,
1395 						    vs.ncol * (vs.nrow - cx) *
1396 						    CHR);
1397 #else
1398 						bcopy(Crtat,
1399 						    Crtat + vs.ncol * cx,
1400 						    vs.ncol * (vs.nrow - cx) *
1401 						    CHR);
1402 #endif
1403 					fillw((vs.at << 8) | ' ', Crtat,
1404 					    vs.ncol * cx);
1405 					/* crtat += vs.ncol * cx; XXX */
1406 					vs.state = 0;
1407 					break;
1408 				}
1409 				case ';': /* Switch params in cursor def */
1410 					vs.state = VSS_EPARAM;
1411 					break;
1412 				case 'r':
1413 					vs.so_at = (vs.cx & FG_MASK) |
1414 					    ((vs.cy << 4) & BG_MASK);
1415 					vs.state = 0;
1416 					break;
1417 				case 's': /* save cursor pos */
1418 					vs.offset = crtat - Crtat;
1419 					vs.state = 0;
1420 					break;
1421 				case 'u': /* restore cursor pos */
1422 					crtat = Crtat + vs.offset;
1423 					vs.row = vs.offset / vs.ncol;
1424 					vs.col = vs.offset % vs.ncol;
1425 					vs.state = 0;
1426 					break;
1427 				case 'x': /* set attributes */
1428 					switch (vs.cx) {
1429 					case 0:
1430 						vs.at = FG_LIGHTGREY | BG_BLACK;
1431 						break;
1432 					case 1:
1433 						/* ansi background */
1434 						if (!vs.color)
1435 							break;
1436 						vs.at &= FG_MASK;
1437 						vs.at |= bgansitopc[vs.cy & 7];
1438 						break;
1439 					case 2:
1440 						/* ansi foreground */
1441 						if (!vs.color)
1442 							break;
1443 						vs.at &= BG_MASK;
1444 						vs.at |= fgansitopc[vs.cy & 7];
1445 						break;
1446 					case 3:
1447 						/* pc text attribute */
1448 						if (vs.state >= VSS_EPARAM)
1449 							vs.at = vs.cy;
1450 						break;
1451 					}
1452 					vs.state = 0;
1453 					break;
1454 
1455 				default: /* Only numbers valid here */
1456 					if ((c >= '0') && (c <= '9')) {
1457 						if (vs.state >= VSS_EPARAM) {
1458 							vs.cy *= 10;
1459 							vs.cy += c - '0';
1460 						} else {
1461 							vs.cx *= 10;
1462 							vs.cx += c - '0';
1463 						}
1464 					} else
1465 						vs.state = 0;
1466 					break;
1467 				}
1468 				break;
1469 			}
1470 		}
1471 		if (scroll) {
1472 			scroll = 0;
1473 			/* scroll check */
1474 			if (crtat >= Crtat + vs.nchr) {
1475 				if (!kernel) {
1476 					int s = spltty();
1477 					if (lock_state & KB_SCROLL)
1478 						tsleep(&lock_state,
1479 						    PUSER, "pcputc", 0);
1480 					splx(s);
1481 				}
1482 #if PCCONS_FORCE_WORD
1483 				wcopy(Crtat + vs.ncol, Crtat,
1484 				    (vs.nchr - vs.ncol) * CHR);
1485 #else
1486 				bcopy(Crtat + vs.ncol, Crtat,
1487 				    (vs.nchr - vs.ncol) * CHR);
1488 #endif
1489 				fillw((vs.at << 8) | ' ',
1490 				    Crtat + vs.nchr - vs.ncol,
1491 				    vs.ncol);
1492 				crtat -= vs.ncol;
1493 			}
1494 		}
1495 	}
1496 	async_update();
1497 }
1498 
1499 /* the unshifted code for KB_SHIFT keys is used by X to distinguish between
1500    left and right shift when reading the keyboard map */
1501 static pccons_keymap_t	scan_codes[KB_NUM_KEYS] = {
1502 /*  type       unshift   shift     control   altgr     shift_altgr scancode */
1503   { KB_NONE,   "",       "",       "",       "",       ""}, /* 0 unused */
1504   { KB_ASCII,  "\033",   "\033",   "\033",   "",       ""}, /* 1 ESCape */
1505   { KB_ASCII,  "1",      "!",      "!",      "",       ""}, /* 2 1 */
1506   { KB_ASCII,  "2",      "@",      "\000",   "",       ""}, /* 3 2 */
1507   { KB_ASCII,  "3",      "#",      "#",      "",       ""}, /* 4 3 */
1508   { KB_ASCII,  "4",      "$",      "$",      "",       ""}, /* 5 4 */
1509   { KB_ASCII,  "5",      "%",      "%",      "",       ""}, /* 6 5 */
1510   { KB_ASCII,  "6",      "^",      "\036",   "",       ""}, /* 7 6 */
1511   { KB_ASCII,  "7",      "&",      "&",      "",       ""}, /* 8 7 */
1512   { KB_ASCII,  "8",      "*",      "\010",   "",       ""}, /* 9 8 */
1513   { KB_ASCII,  "9",      "(",      "(",      "",       ""}, /* 10 9 */
1514   { KB_ASCII,  "0",      ")",      ")",      "",       ""}, /* 11 0 */
1515   { KB_ASCII,  "-",      "_",      "\037",   "",       ""}, /* 12 - */
1516   { KB_ASCII,  "=",      "+",      "+",      "",       ""}, /* 13 = */
1517   { KB_ASCII,  "\177",   "\177",   "\010",   "",       ""}, /* 14 backspace */
1518   { KB_ASCII,  "\t",     "\t",     "\t",     "",       ""}, /* 15 tab */
1519   { KB_ASCII,  "q",      "Q",      "\021",   "",       ""}, /* 16 q */
1520   { KB_ASCII,  "w",      "W",      "\027",   "",       ""}, /* 17 w */
1521   { KB_ASCII,  "e",      "E",      "\005",   "",       ""}, /* 18 e */
1522   { KB_ASCII,  "r",      "R",      "\022",   "",       ""}, /* 19 r */
1523   { KB_ASCII,  "t",      "T",      "\024",   "",       ""}, /* 20 t */
1524   { KB_ASCII,  "y",      "Y",      "\031",   "",       ""}, /* 21 y */
1525   { KB_ASCII,  "u",      "U",      "\025",   "",       ""}, /* 22 u */
1526   { KB_ASCII,  "i",      "I",      "\011",   "",       ""}, /* 23 i */
1527   { KB_ASCII,  "o",      "O",      "\017",   "",       ""}, /* 24 o */
1528   { KB_ASCII,  "p",      "P",      "\020",   "",       ""}, /* 25 p */
1529   { KB_ASCII,  "[",      "{",      "\033",   "",       ""}, /* 26 [ */
1530   { KB_ASCII,  "]",      "}",      "\035",   "",       ""}, /* 27 ] */
1531   { KB_ASCII,  "\r",     "\r",     "\n",     "",       ""}, /* 28 return */
1532   { KB_CTL,    "",       "",       "",       "",       ""}, /* 29 control */
1533   { KB_ASCII,  "a",      "A",      "\001",   "",       ""}, /* 30 a */
1534   { KB_ASCII,  "s",      "S",      "\023",   "",       ""}, /* 31 s */
1535   { KB_ASCII,  "d",      "D",      "\004",   "",       ""}, /* 32 d */
1536   { KB_ASCII,  "f",      "F",      "\006",   "",       ""}, /* 33 f */
1537   { KB_ASCII,  "g",      "G",      "\007",   "",       ""}, /* 34 g */
1538   { KB_ASCII,  "h",      "H",      "\010",   "",       ""}, /* 35 h */
1539   { KB_ASCII,  "j",      "J",      "\n",     "",       ""}, /* 36 j */
1540   { KB_ASCII,  "k",      "K",      "\013",   "",       ""}, /* 37 k */
1541   { KB_ASCII,  "l",      "L",      "\014",   "",       ""}, /* 38 l */
1542   { KB_ASCII,  ";",      ":",      ";",      "",       ""}, /* 39 ; */
1543   { KB_ASCII,  "'",      "\"",     "'",      "",       ""}, /* 40 ' */
1544   { KB_ASCII,  "`",      "~",      "`",      "",       ""}, /* 41 ` */
1545   { KB_SHIFT,  "\001",   "",       "",       "",       ""}, /* 42 shift */
1546   { KB_ASCII,  "\\",     "|",      "\034",   "",       ""}, /* 43 \ */
1547   { KB_ASCII,  "z",      "Z",      "\032",   "",       ""}, /* 44 z */
1548   { KB_ASCII,  "x",      "X",      "\030",   "",       ""}, /* 45 x */
1549   { KB_ASCII,  "c",      "C",      "\003",   "",       ""}, /* 46 c */
1550   { KB_ASCII,  "v",      "V",      "\026",   "",       ""}, /* 47 v */
1551   { KB_ASCII,  "b",      "B",      "\002",   "",       ""}, /* 48 b */
1552   { KB_ASCII,  "n",      "N",      "\016",   "",       ""}, /* 49 n */
1553   { KB_ASCII,  "m",      "M",      "\r",     "",       ""}, /* 50 m */
1554   { KB_ASCII,  ",",      "<",      "<",      "",       ""}, /* 51 , */
1555   { KB_ASCII,  ".",      ">",      ">",      "",       ""}, /* 52 . */
1556   { KB_ASCII,  "/",      "?",      "\037",   "",       ""}, /* 53 / */
1557   { KB_SHIFT,  "\002",   "",       "",       "",       ""}, /* 54 shift */
1558   { KB_KP,     "*",      "*",      "*",      "",       ""}, /* 55 kp * */
1559   { KB_ALT,    "",       "",       "",       "",       ""}, /* 56 alt */
1560   { KB_ASCII,  " ",      " ",      "\000",   "",       ""}, /* 57 space */
1561   { KB_CAPS,   "",       "",       "",       "",       ""}, /* 58 caps */
1562   { KB_FUNC,   "\033[M", "\033[Y", "\033[k", "",       ""}, /* 59 f1 */
1563   { KB_FUNC,   "\033[N", "\033[Z", "\033[l", "",       ""}, /* 60 f2 */
1564   { KB_FUNC,   "\033[O", "\033[a", "\033[m", "",       ""}, /* 61 f3 */
1565   { KB_FUNC,   "\033[P", "\033[b", "\033[n", "",       ""}, /* 62 f4 */
1566   { KB_FUNC,   "\033[Q", "\033[c", "\033[o", "",       ""}, /* 63 f5 */
1567   { KB_FUNC,   "\033[R", "\033[d", "\033[p", "",       ""}, /* 64 f6 */
1568   { KB_FUNC,   "\033[S", "\033[e", "\033[q", "",       ""}, /* 65 f7 */
1569   { KB_FUNC,   "\033[T", "\033[f", "\033[r", "",       ""}, /* 66 f8 */
1570   { KB_FUNC,   "\033[U", "\033[g", "\033[s", "",       ""}, /* 67 f9 */
1571   { KB_FUNC,   "\033[V", "\033[h", "\033[t", "",       ""}, /* 68 f10 */
1572   { KB_NUM,    "",       "",       "",       "",       ""}, /* 69 num lock */
1573   { KB_SCROLL, "",       "",       "",       "",       ""}, /* 70 scroll lock */
1574   { KB_KP,     "7",      "\033[H", "7",      "",       ""}, /* 71 kp 7 */
1575   { KB_KP,     "8",      "\033[A", "8",      "",       ""}, /* 72 kp 8 */
1576   { KB_KP,     "9",      "\033[I", "9",      "",       ""}, /* 73 kp 9 */
1577   { KB_KP,     "-",      "-",      "-",      "",       ""}, /* 74 kp - */
1578   { KB_KP,     "4",      "\033[D", "4",      "",       ""}, /* 75 kp 4 */
1579   { KB_KP,     "5",      "\033[E", "5",      "",       ""}, /* 76 kp 5 */
1580   { KB_KP,     "6",      "\033[C", "6",      "",       ""}, /* 77 kp 6 */
1581   { KB_KP,     "+",      "+",      "+",      "",       ""}, /* 78 kp + */
1582   { KB_KP,     "1",      "\033[F", "1",      "",       ""}, /* 79 kp 1 */
1583   { KB_KP,     "2",      "\033[B", "2",      "",       ""}, /* 80 kp 2 */
1584   { KB_KP,     "3",      "\033[G", "3",      "",       ""}, /* 81 kp 3 */
1585   { KB_KP,     "0",      "\033[L", "0",      "",       ""}, /* 82 kp 0 */
1586   { KB_KP,     ",",      "\177",   ",",      "",       ""}, /* 83 kp , */
1587   { KB_NONE,   "",       "",       "",       "",       ""}, /* 84 0 */
1588   { KB_NONE,   "",       "",       "",       "",       ""}, /* 85 0 */
1589   { KB_NONE,   "",       "",       "",       "",       ""}, /* 86 0 */
1590   { KB_FUNC,   "\033[W", "\033[i", "\033[u", "",       ""}, /* 87 f11 */
1591   { KB_FUNC,   "\033[X", "\033[j", "\033[v", "",       ""}, /* 88 f12 */
1592   { KB_NONE,   "",       "",       "",       "",       ""}, /* 89 0 */
1593   { KB_NONE,   "",       "",       "",       "",       ""}, /* 90 0 */
1594   { KB_NONE,   "",       "",       "",       "",       ""}, /* 91 0 */
1595   { KB_NONE,   "",       "",       "",       "",       ""}, /* 92 0 */
1596   { KB_NONE,   "",       "",       "",       "",       ""}, /* 93 0 */
1597   { KB_NONE,   "",       "",       "",       "",       ""}, /* 94 0 */
1598   { KB_NONE,   "",       "",       "",       "",       ""}, /* 95 0 */
1599   { KB_NONE,   "",       "",       "",       "",       ""}, /* 96 0 */
1600   { KB_NONE,   "",       "",       "",       "",       ""}, /* 97 0 */
1601   { KB_NONE,   "",       "",       "",       "",       ""}, /* 98 0 */
1602   { KB_NONE,   "",       "",       "",       "",       ""}, /* 99 0 */
1603   { KB_NONE,   "",       "",       "",       "",       ""}, /* 100 */
1604   { KB_NONE,   "",       "",       "",       "",       ""}, /* 101 */
1605   { KB_NONE,   "",       "",       "",       "",       ""}, /* 102 */
1606   { KB_NONE,   "",       "",       "",       "",       ""}, /* 103 */
1607   { KB_NONE,   "",       "",       "",       "",       ""}, /* 104 */
1608   { KB_NONE,   "",       "",       "",       "",       ""}, /* 105 */
1609   { KB_NONE,   "",       "",       "",       "",       ""}, /* 106 */
1610   { KB_NONE,   "",       "",       "",       "",       ""}, /* 107 */
1611   { KB_NONE,   "",       "",       "",       "",       ""}, /* 108 */
1612   { KB_NONE,   "",       "",       "",       "",       ""}, /* 109 */
1613   { KB_NONE,   "",       "",       "",       "",       ""}, /* 110 */
1614   { KB_NONE,   "",       "",       "",       "",       ""}, /* 111 */
1615   { KB_NONE,   "",       "",       "",       "",       ""}, /* 112 */
1616   { KB_NONE,   "",       "",       "",       "",       ""}, /* 113 */
1617   { KB_NONE,   "",       "",       "",       "",       ""}, /* 114 */
1618   { KB_NONE,   "",       "",       "",       "",       ""}, /* 115 */
1619   { KB_NONE,   "",       "",       "",       "",       ""}, /* 116 */
1620   { KB_NONE,   "",       "",       "",       "",       ""}, /* 117 */
1621   { KB_NONE,   "",       "",       "",       "",       ""}, /* 118 */
1622   { KB_NONE,   "",       "",       "",       "",       ""}, /* 119 */
1623   { KB_NONE,   "",       "",       "",       "",       ""}, /* 120 */
1624   { KB_NONE,   "",       "",       "",       "",       ""}, /* 121 */
1625   { KB_NONE,   "",       "",       "",       "",       ""}, /* 122 */
1626   { KB_NONE,   "",       "",       "",       "",       ""}, /* 123 */
1627   { KB_NONE,   "",       "",       "",       "",       ""}, /* 124 */
1628   { KB_NONE,   "",       "",       "",       "",       ""}, /* 125 */
1629   { KB_NONE,   "",       "",       "",       "",       ""}, /* 126 */
1630   { KB_NONE,   "",       "",       "",       "",       ""}  /* 127 */
1631 };
1632 
1633 /*
1634  * Get characters from the keyboard.  If none are present, return NULL.
1635  */
1636 char *
1637 sget()
1638 {
1639 	u_char dt;
1640 	static u_char extended = 0, shift_state = 0;
1641 	static u_char capchar[2];
1642 
1643 top:
1644 	KBD_DELAY;
1645 	dt = kbd_data_read_1();
1646 
1647 	switch (dt) {
1648 	case KBR_ACK: case KBR_ECHO:
1649 		kb_oq_get = (kb_oq_get + 1) & 7;
1650 		if(kb_oq_get != kb_oq_put) {
1651 			kbd_data_write_1(kb_oq[kb_oq_get]);
1652 		}
1653 		goto loop;
1654 	case KBR_RESEND:
1655 		kbd_data_write_1(kb_oq[kb_oq_get]);
1656 		goto loop;
1657 	}
1658 
1659 	if (pc_xmode > 0) {
1660 #if defined(DDB) && defined(XSERVER_DDB)
1661 		/* F12 enters the debugger while in X mode */
1662 		if (dt == 88)
1663 			Debugger();
1664 #endif
1665 		capchar[0] = dt;
1666 		capchar[1] = 0;
1667 		/*
1668 		 * Check for locking keys.
1669 		 *
1670 		 * XXX Setting the LEDs this way is a bit bogus.  What if the
1671 		 * keyboard has been remapped in X?
1672 		 */
1673 		switch (scan_codes[dt & 0x7f].type) {
1674 		case KB_NUM:
1675 			if (dt & 0x80) {
1676 				shift_state &= ~KB_NUM;
1677 				break;
1678 			}
1679 			if (shift_state & KB_NUM)
1680 				break;
1681 			shift_state |= KB_NUM;
1682 			lock_state ^= KB_NUM;
1683 			async_update();
1684 			break;
1685 		case KB_CAPS:
1686 			if (dt & 0x80) {
1687 				shift_state &= ~KB_CAPS;
1688 				break;
1689 			}
1690 			if (shift_state & KB_CAPS)
1691 				break;
1692 			shift_state |= KB_CAPS;
1693 			lock_state ^= KB_CAPS;
1694 			async_update();
1695 			break;
1696 		case KB_SCROLL:
1697 			if (dt & 0x80) {
1698 				shift_state &= ~KB_SCROLL;
1699 				break;
1700 			}
1701 			if (shift_state & KB_SCROLL)
1702 				break;
1703 			shift_state |= KB_SCROLL;
1704 			lock_state ^= KB_SCROLL;
1705 			if ((lock_state & KB_SCROLL) == 0)
1706 				wakeup((caddr_t)&lock_state);
1707 			async_update();
1708 			break;
1709 		}
1710 		return capchar;
1711 	}
1712 
1713 	switch (dt) {
1714 	case KBR_EXTENDED:
1715 		extended = 1;
1716 		goto loop;
1717 	}
1718 
1719 #ifdef DDB
1720 	/*
1721 	 * Check for cntl-alt-esc.
1722 	 */
1723 	if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
1724 		/* XXX - check pccons_is_console */
1725 		Debugger();
1726 		dt |= 0x80;	/* discard esc (ddb discarded ctl-alt) */
1727 	}
1728 #endif
1729 
1730 	/*
1731 	 * Check for make/break.
1732 	 */
1733 	if (dt & 0x80) {
1734 		/*
1735 		 * break
1736 		 */
1737 		dt &= 0x7f;
1738 		switch (scan_codes[dt].type) {
1739 		case KB_NUM:
1740 			shift_state &= ~KB_NUM;
1741 			break;
1742 		case KB_CAPS:
1743 			shift_state &= ~KB_CAPS;
1744 			break;
1745 		case KB_SCROLL:
1746 			shift_state &= ~KB_SCROLL;
1747 			break;
1748 		case KB_SHIFT:
1749 			shift_state &= ~KB_SHIFT;
1750 			break;
1751 		case KB_ALT:
1752 			if (extended)
1753 				shift_state &= ~KB_ALTGR;
1754 			else
1755 				shift_state &= ~KB_ALT;
1756 			break;
1757 		case KB_CTL:
1758 			shift_state &= ~KB_CTL;
1759 			break;
1760 		}
1761 	} else {
1762 		/*
1763 		 * make
1764 		 */
1765 		switch (scan_codes[dt].type) {
1766 		/*
1767 		 * locking keys
1768 		 */
1769 		case KB_NUM:
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 (shift_state & KB_CAPS)
1778 				break;
1779 			shift_state |= KB_CAPS;
1780 			lock_state ^= KB_CAPS;
1781 			async_update();
1782 			break;
1783 		case KB_SCROLL:
1784 			if (shift_state & KB_SCROLL)
1785 				break;
1786 			shift_state |= KB_SCROLL;
1787 			lock_state ^= KB_SCROLL;
1788 			if ((lock_state & KB_SCROLL) == 0)
1789 				wakeup((caddr_t)&lock_state);
1790 			async_update();
1791 			break;
1792 		/*
1793 		 * non-locking keys
1794 		 */
1795 		case KB_SHIFT:
1796 			shift_state |= KB_SHIFT;
1797 			break;
1798 		case KB_ALT:
1799 			if (extended)
1800 				shift_state |= KB_ALTGR;
1801 			else
1802 				shift_state |= KB_ALT;
1803 			break;
1804 		case KB_CTL:
1805 			shift_state |= KB_CTL;
1806 			break;
1807 		case KB_ASCII:
1808 			/* control has highest priority */
1809 			if (shift_state & KB_CTL)
1810 				capchar[0] = scan_codes[dt].ctl[0];
1811 			else if (shift_state & KB_ALTGR) {
1812 				if (shift_state & KB_SHIFT)
1813 					capchar[0] = scan_codes[dt].shift_altgr[0];
1814 				else
1815 					capchar[0] = scan_codes[dt].altgr[0];
1816 			}
1817 			else {
1818 				if (shift_state & KB_SHIFT)
1819 					capchar[0] = scan_codes[dt].shift[0];
1820 				else
1821 					capchar[0] = scan_codes[dt].unshift[0];
1822 			}
1823 			if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
1824 			    capchar[0] <= 'z') {
1825 				capchar[0] -= ('a' - 'A');
1826 			}
1827 			capchar[0] |= (shift_state & KB_ALT);
1828 			extended = 0;
1829 			return capchar;
1830 		case KB_NONE:
1831 printf("keycode %d\n",dt);
1832 			break;
1833 		case KB_FUNC: {
1834 			char *more_chars;
1835 			if (shift_state & KB_SHIFT)
1836 				more_chars = scan_codes[dt].shift;
1837 			else if (shift_state & KB_CTL)
1838 				more_chars = scan_codes[dt].ctl;
1839 			else
1840 				more_chars = scan_codes[dt].unshift;
1841 			extended = 0;
1842 			return more_chars;
1843 		}
1844 		case KB_KP: {
1845 			char *more_chars;
1846 			if (shift_state & (KB_SHIFT | KB_CTL) ||
1847 			    (lock_state & KB_NUM) == 0 || extended)
1848 				more_chars = scan_codes[dt].shift;
1849 			else
1850 				more_chars = scan_codes[dt].unshift;
1851 			extended = 0;
1852 			return more_chars;
1853 		}
1854 		}
1855 	}
1856 
1857 	extended = 0;
1858 loop:
1859 	if ((kbd_cmd_read_1() & KBS_DIB) == 0)
1860 		return 0;
1861 	goto top;
1862 }
1863 
1864 paddr_t
1865 pcmmap(dev, offset, nprot)
1866 	dev_t dev;
1867 	off_t offset;
1868 	int nprot;
1869 {
1870 	struct pccons_context *pc = &pccons_console_context;
1871 	paddr_t pa;
1872 
1873 	if (offset >= 0xa0000 && offset < 0xc0000) {
1874 		if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
1875 			return (-1);
1876 		pa += offset - pc->pc_config->pc_mono_memaddr;
1877 		return (mips_btop(pa));
1878 	}
1879 	if (offset >= 0x0000 && offset < 0x10000) {
1880 		if (bus_space_paddr(pc->pc_crt_iot, pc->pc_mono_ioh, &pa))
1881 			return (-1);
1882 		pa += offset - pc->pc_config->pc_mono_iobase;
1883 		return (mips_btop(pa));
1884 	}
1885 	if (offset >= 0x40000000 && offset < 0x40800000) {
1886 		if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
1887 			return (-1);
1888 		pa += offset - 0x40000000 - pc->pc_config->pc_mono_memaddr;
1889 		return (mips_btop(pa));
1890 	}
1891 	return (-1);
1892 }
1893 
1894 void
1895 pc_xmode_on()
1896 {
1897 	if (pc_xmode)
1898 		return;
1899 	pc_xmode = 1;
1900 
1901 #ifdef XFREE86_BUG_COMPAT
1902 	/* If still unchanged, get current shape. */
1903 	if (cursor_shape == 0xffff)
1904 		get_cursor_shape();
1905 #endif
1906 }
1907 
1908 void
1909 pc_xmode_off()
1910 {
1911 	if (pc_xmode == 0)
1912 		return;
1913 	pc_xmode = 0;
1914 
1915 #ifdef XFREE86_BUG_COMPAT
1916 	/* XXX It would be hard to justify why the X server doesn't do this. */
1917 	set_cursor_shape();
1918 #endif
1919 	async_update();
1920 }
1921