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