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