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