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