Merge branch 'vendor/GCC47'
[dragonfly.git] / sys / dev / misc / syscons / syscons.c
1 /*-
2  * Copyright (c) 1992-1998 Søren Schmidt
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The DragonFly Project
6  * by Sascha Wildner <saw@online.de>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer,
13  *    without modification, immediately at the beginning of the file.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/dev/syscons/syscons.c,v 1.336.2.17 2004/03/25 08:41:09 ru Exp $
32  */
33
34 #include "use_splash.h"
35 #include "opt_syscons.h"
36 #include "opt_ddb.h"
37 #ifdef __i386__
38 #include "use_apm.h"
39 #endif
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/eventhandler.h>
44 #include <sys/reboot.h>
45 #include <sys/conf.h>
46 #include <sys/proc.h>
47 #include <sys/priv.h>
48 #include <sys/signalvar.h>
49 #include <sys/sysctl.h>
50 #include <sys/tty.h>
51 #include <sys/kernel.h>
52 #include <sys/cons.h>
53 #include <sys/random.h>
54
55 #include <sys/thread2.h>
56 #include <sys/mutex2.h>
57
58 #include <machine/clock.h>
59 #include <machine/console.h>
60 #include <machine/psl.h>
61 #include <machine/pc/display.h>
62 #ifdef __i386__
63 #include <machine/apm_bios.h>
64 #endif
65 #include <machine/frame.h>
66
67 #include <dev/misc/kbd/kbdreg.h>
68 #include <dev/video/fb/fbreg.h>
69 #include <dev/video/fb/splashreg.h>
70 #include "syscons.h"
71
72 #define COLD 0
73 #define WARM 1
74
75 #define DEFAULT_BLANKTIME       (5*60)          /* 5 minutes */
76 #define MAX_BLANKTIME           (7*24*60*60)    /* 7 days!? */
77
78 #define KEYCODE_BS              0x0e            /* "<-- Backspace" key, XXX */
79 #define WANT_UNLOCK(m) do {       \
80         if (m)                    \
81                 syscons_unlock(); \
82 } while (0)
83
84 #define WANT_LOCK(m) do {         \
85         if (m)                    \
86                 syscons_lock();   \
87 } while(0)
88
89
90 MALLOC_DEFINE(M_SYSCONS, "syscons", "Syscons");
91
92 typedef struct default_attr {
93         int             std_color;              /* normal hardware color */
94         int             rev_color;              /* reverse hardware color */
95 } default_attr;
96
97 static default_attr user_default = {
98     SC_NORM_ATTR,
99     SC_NORM_REV_ATTR,
100 };
101
102 static default_attr kernel_default = {
103     SC_KERNEL_CONS_ATTR,
104     SC_KERNEL_CONS_REV_ATTR,
105 };
106
107 static  int             sc_console_unit = -1;
108 static  scr_stat        *sc_console;
109 static  struct tty      *sc_console_tty;
110 static  void            *kernel_console_ts;
111
112 static  char            init_done = COLD;
113 static  char            shutdown_in_progress = FALSE;
114 static  char            sc_malloc = FALSE;
115
116 static  int             saver_mode = CONS_NO_SAVER; /* LKM/user saver */
117 static  int             run_scrn_saver = FALSE; /* should run the saver? */
118 static  long            scrn_blank_time = 0;    /* screen saver timeout value */
119 #if NSPLASH > 0
120 static  int             scrn_blanked;           /* # of blanked screen */
121 static  int             sticky_splash = FALSE;
122
123 static  void            none_saver(sc_softc_t *sc, int blank) { }
124 static  void            (*current_saver)(sc_softc_t *, int) = none_saver;
125 #endif
126
127 #if !defined(SC_NO_FONT_LOADING) && defined(SC_DFLT_FONT)
128 #include "font.h"
129 #endif
130
131 static  bios_values_t   bios_value;
132
133 static  int             enable_panic_key;
134 SYSCTL_INT(_machdep, OID_AUTO, enable_panic_key, CTLFLAG_RW, &enable_panic_key,
135            0, "Enable the panic key (CTRL-ALT-SHIFT-ESC)");
136
137 #define SC_CONSOLECTL   255
138
139 #define VIRTUAL_TTY(sc, x) ((SC_DEV((sc),(x)) != NULL) ?        \
140         (SC_DEV((sc),(x))->si_tty) : NULL)
141 #define ISTTYOPEN(tp)   ((tp) && ((tp)->t_state & TS_ISOPEN))
142
143 static  int     debugger;
144 static  cdev_t  cctl_dev;
145 #if 0
146 static  timeout_t blink_screen_callout;
147 #endif
148 static  void    sc_blink_screen(scr_stat *scp);
149 static  struct mtx      syscons_mtx = MTX_INITIALIZER;
150
151 /* prototypes */
152 static int scvidprobe(int unit, int flags, int cons);
153 static int sckbdprobe(int unit, int flags, int cons);
154 static void scmeminit(void *arg);
155 static int scdevtounit(cdev_t dev);
156 static kbd_callback_func_t sckbdevent;
157 static int scparam(struct tty *tp, struct termios *t);
158 static void scstart(struct tty *tp);
159 static void scinit(int unit, int flags);
160 static void scterm(int unit, int flags);
161 static void scshutdown(void *arg, int howto);
162 static void sc_puts(scr_stat *scp, u_char *buf, int len);
163 static u_int scgetc(sc_softc_t *sc, u_int flags);
164 #define SCGETC_CN       1
165 #define SCGETC_NONBLOCK 2
166 static int sccngetch(int flags);
167 static void sccnupdate(scr_stat *scp);
168 static scr_stat *alloc_scp(sc_softc_t *sc, int vty);
169 static void init_scp(sc_softc_t *sc, int vty, scr_stat *scp);
170 static timeout_t scrn_timer;
171 static int and_region(int *s1, int *e1, int s2, int e2);
172 static void scrn_update(scr_stat *scp, int show_cursor);
173
174 #if NSPLASH > 0
175 static int scsplash_callback(int event, void *arg);
176 static void scsplash_saver(sc_softc_t *sc, int show);
177 static int add_scrn_saver(void (*this_saver)(sc_softc_t *, int));
178 static int remove_scrn_saver(void (*this_saver)(sc_softc_t *, int));
179 static int set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border);
180 static int restore_scrn_saver_mode(scr_stat *scp, int changemode);
181 static void stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int));
182 static int wait_scrn_saver_stop(sc_softc_t *sc);
183 #define scsplash_stick(stick)           (sticky_splash = (stick))
184 #else /* !NSPLASH */
185 #define scsplash_stick(stick)
186 #endif /* NSPLASH */
187
188 static void do_switch_scr(sc_softc_t *sc);
189 static int vt_proc_alive(scr_stat *scp);
190 static int signal_vt_rel(scr_stat *scp);
191 static int signal_vt_acq(scr_stat *scp);
192 static int finish_vt_rel(scr_stat *scp, int release);
193 static int finish_vt_acq(scr_stat *scp);
194 static void exchange_scr(sc_softc_t *sc);
195 static void update_cursor_image(scr_stat *scp);
196 static int save_kbd_state(scr_stat *scp, int unlock);
197 static int update_kbd_state(scr_stat *scp, int state, int mask, int unlock);
198 static int update_kbd_leds(scr_stat *scp, int which);
199 static int sc_allocate_keyboard(sc_softc_t *sc, int unit);
200
201 /*
202  * Console locking support functions.
203  *
204  * We use mutex spinlocks here in order to allow reentrancy which should
205  * avoid issues during panics.
206  */
207 static void
208 syscons_lock(void)
209 {
210         mtx_spinlock(&syscons_mtx);
211 }
212
213 /*
214  * Returns 0 on success, EAGAIN on failure.
215  */
216 static int
217 syscons_lock_nonblock(void)
218 {
219         return(mtx_spinlock_try(&syscons_mtx));
220 }
221
222 static void
223 syscons_unlock(void)
224 {
225         mtx_spinunlock(&syscons_mtx);
226 }
227
228 /*
229  * Console driver
230  */
231 static cn_probe_t       sccnprobe;
232 static cn_init_t        sccninit;
233 static cn_init_t        sccninit_fini;
234 static cn_getc_t        sccngetc;
235 static cn_checkc_t      sccncheckc;
236 static cn_putc_t        sccnputc;
237 static cn_dbctl_t       sccndbctl;
238 static cn_term_t        sccnterm;
239
240 CONS_DRIVER(sc, sccnprobe, sccninit, sccninit_fini, sccnterm,
241             sccngetc, sccncheckc, sccnputc, sccndbctl);
242
243 static  d_open_t        scopen;
244 static  d_close_t       scclose;
245 static  d_read_t        scread;
246 static  d_ioctl_t       scioctl;
247 static  d_mmap_t        scmmap;
248
249 static struct dev_ops sc_ops = {
250         { "sc", 0, D_TTY },
251         .d_open =       scopen,
252         .d_close =      scclose,
253         .d_read =       scread,
254         .d_write =      ttywrite,
255         .d_ioctl =      scioctl,
256         .d_mmap =       scmmap,
257         .d_kqfilter =   ttykqfilter,
258         .d_revoke =     ttyrevoke
259 };
260
261 int
262 sc_probe_unit(int unit, int flags)
263 {
264     if (!scvidprobe(unit, flags, FALSE)) {
265         if (bootverbose)
266             kprintf("sc%d: no video adapter found.\n", unit);
267         return ENXIO;
268     }
269
270     /* syscons will be attached even when there is no keyboard */
271     sckbdprobe(unit, flags, FALSE);
272
273     return 0;
274 }
275
276 /* probe video adapters, return TRUE if found */ 
277 static int
278 scvidprobe(int unit, int flags, int cons)
279 {
280     /*
281      * Access the video adapter driver through the back door!
282      * Video adapter drivers need to be configured before syscons.
283      * However, when syscons is being probed as the low-level console,
284      * they have not been initialized yet.  We force them to initialize
285      * themselves here. XXX
286      */
287     vid_configure(cons ? VIO_PROBE_ONLY : 0);
288
289     return (vid_find_adapter("*", unit) >= 0);
290 }
291
292 /* probe the keyboard, return TRUE if found */
293 static int
294 sckbdprobe(int unit, int flags, int cons)
295 {
296     /* access the keyboard driver through the backdoor! */
297     kbd_configure(cons ? KB_CONF_PROBE_ONLY : 0);
298
299     return (kbd_find_keyboard("*", unit) >= 0);
300 }
301
302 static char *
303 adapter_name(video_adapter_t *adp)
304 {
305     static struct {
306         int type;
307         char *name[2];
308     } names[] = {
309         { KD_MONO,      { "MDA",        "MDA" } },
310         { KD_HERCULES,  { "Hercules",   "Hercules" } },
311         { KD_CGA,       { "CGA",        "CGA" } },
312         { KD_EGA,       { "EGA",        "EGA (mono)" } },
313         { KD_VGA,       { "VGA",        "VGA (mono)" } },
314         { KD_TGA,       { "TGA",        "TGA" } },
315         { -1,           { "Unknown",    "Unknown" } },
316     };
317     int i;
318
319     for (i = 0; names[i].type != -1; ++i)
320         if (names[i].type == adp->va_type)
321             break;
322     return names[i].name[(adp->va_flags & V_ADP_COLOR) ? 0 : 1];
323 }
324
325 int
326 sc_attach_unit(int unit, int flags)
327 {
328     sc_softc_t *sc;
329     scr_stat *scp;
330 #ifdef SC_PIXEL_MODE
331     video_info_t info;
332 #endif
333     int vc;
334     cdev_t dev;
335     flags &= ~SC_KERNEL_CONSOLE;
336
337     if (sc_console_unit == unit) {
338         /*
339          * If this unit is being used as the system console, we need to
340          * adjust some variables and buffers before and after scinit().
341          */
342         /* assert(sc_console != NULL) */
343         flags |= SC_KERNEL_CONSOLE;
344         scmeminit(NULL);
345
346         scinit(unit, flags);
347
348         if (sc_console->tsw->te_size > 0) {
349             /* assert(sc_console->ts != NULL); */
350             kernel_console_ts = sc_console->ts;
351             sc_console->ts = kmalloc(sc_console->tsw->te_size,
352                                     M_SYSCONS, M_WAITOK);
353             bcopy(kernel_console_ts, sc_console->ts, sc_console->tsw->te_size);
354             (*sc_console->tsw->te_default_attr)(sc_console,
355                                                 user_default.std_color,
356                                                 user_default.rev_color);
357         }
358     } else {
359         scinit(unit, flags);
360     }
361
362     sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
363
364     /*
365      * If this is the console we couldn't setup sc->dev before because
366      * malloc wasn't working.  Set it up now.
367      */
368     if (flags & SC_KERNEL_CONSOLE) {
369         KKASSERT(sc->dev == NULL);
370         sc->dev = kmalloc(sizeof(cdev_t)*sc->vtys, M_SYSCONS, M_WAITOK|M_ZERO);
371         sc->dev[0] = make_dev(&sc_ops, sc_console_unit*MAXCONS, UID_ROOT, 
372                               GID_WHEEL, 0600, 
373                               "ttyv%r", sc_console_unit*MAXCONS);
374         sc->dev[0]->si_tty = ttymalloc(sc->dev[0]->si_tty);
375         sc->dev[0]->si_drv1 = sc_console;
376     }
377
378     /*
379      * Finish up the standard attach
380      */
381     sc->config = flags;
382     callout_init_mp(&sc->scrn_timer_ch);
383     scp = SC_STAT(sc->dev[0]);
384     if (sc_console == NULL)     /* sc_console_unit < 0 */
385         sc_console = scp;
386
387 #ifdef SC_PIXEL_MODE
388     if ((sc->config & SC_VESA800X600)
389         && ((*vidsw[sc->adapter]->get_info)(sc->adp, M_VESA_800x600, &info) == 0)) {
390 #if NSPLASH > 0
391         if (sc->flags & SC_SPLASH_SCRN)
392             splash_term(sc->adp);
393 #endif
394         sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
395         sc_set_pixel_mode(scp, NULL, 0, 0, 16);
396         sc->initial_mode = M_VESA_800x600;
397 #if NSPLASH > 0
398         /* put up the splash again! */
399         if (sc->flags & SC_SPLASH_SCRN)
400             splash_init(sc->adp, scsplash_callback, sc);
401 #endif
402     }
403 #endif /* SC_PIXEL_MODE */
404
405     /* initialize cursor */
406     if (!ISGRAPHSC(scp))
407         update_cursor_image(scp);
408
409     /* get screen update going */
410     scrn_timer(sc);
411
412     /* set up the keyboard */
413     kbd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
414     update_kbd_state(scp, scp->status, LOCK_MASK, FALSE);
415
416     kprintf("sc%d: %s <%d virtual consoles, flags=0x%x>\n",
417            unit, adapter_name(sc->adp), sc->vtys, sc->config);
418     if (bootverbose) {
419         kprintf("sc%d:", unit);
420         if (sc->adapter >= 0)
421             kprintf(" fb%d", sc->adapter);
422         if (sc->keyboard >= 0)
423             kprintf(", kbd%d", sc->keyboard);
424         if (scp->tsw)
425             kprintf(", terminal emulator: %s (%s)",
426                    scp->tsw->te_name, scp->tsw->te_desc);
427         kprintf("\n");
428     }
429
430     /* register a shutdown callback for the kernel console */
431     if (sc_console_unit == unit)
432         EVENTHANDLER_REGISTER(shutdown_pre_sync, scshutdown, 
433                               (void *)(uintptr_t)unit, SHUTDOWN_PRI_DEFAULT);
434
435     /* 
436      * create devices.
437      *
438      * The first vty already has struct tty and scr_stat initialized
439      * in scinit().  The other vtys will have these structs when
440      * first opened.
441      */
442     for (vc = 1; vc < sc->vtys; vc++) {
443         dev = make_dev(&sc_ops, vc + unit * MAXCONS,
444                         UID_ROOT, GID_WHEEL,
445                         0600, "ttyv%r", vc + unit * MAXCONS);
446         sc->dev[vc] = dev;
447     }
448     cctl_dev = make_dev(&sc_ops, SC_CONSOLECTL,
449                         UID_ROOT, GID_WHEEL, 0600, "consolectl");
450     cctl_dev->si_tty = sc_console_tty = ttymalloc(sc_console_tty);
451     cctl_dev->si_drv1 = sc_console;
452     return 0;
453 }
454
455 static void
456 scmeminit(void *arg)
457 {
458     if (sc_malloc)
459         return;
460     sc_malloc = TRUE;
461
462     /*
463      * As soon as malloc() becomes functional, we had better allocate
464      * various buffers for the kernel console.
465      */
466
467     if (sc_console_unit < 0)    /* sc_console == NULL */
468         return;
469
470     /* copy the temporary buffer to the final buffer */
471     sc_alloc_scr_buffer(sc_console, TRUE, FALSE);
472
473 #ifndef SC_NO_CUTPASTE
474     sc_alloc_cut_buffer(sc_console, TRUE);
475 #endif
476
477 #ifndef SC_NO_HISTORY
478     /* initialize history buffer & pointers */
479     sc_alloc_history_buffer(sc_console, 0, 0, TRUE);
480 #endif
481 }
482
483 SYSINIT(sc_mem, SI_BOOT1_POST, SI_ORDER_ANY, scmeminit, NULL);
484
485 static int
486 scdevtounit(cdev_t dev)
487 {
488     int vty = SC_VTY(dev);
489
490     if (vty == SC_CONSOLECTL)
491         return ((sc_console != NULL) ? sc_console->sc->unit : -1);
492     else if ((vty < 0) || (vty >= MAXCONS*sc_max_unit()))
493         return -1;
494     else
495         return vty/MAXCONS;
496 }
497
498 int
499 scopen(struct dev_open_args *ap)
500 {
501     cdev_t dev = ap->a_head.a_dev;
502     int unit;
503     sc_softc_t *sc;
504     struct tty *tp;
505     scr_stat *scp;
506     keyarg_t key;
507     int error;
508
509     lwkt_gettoken(&tty_token);
510     unit = scdevtounit(dev);
511     DPRINTF(5, ("scopen: dev:%d,%d, unit:%d, vty:%d\n",
512                 major(dev), minor(dev), unit, SC_VTY(dev)));
513
514     sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0);
515     if (sc == NULL) {
516         lwkt_reltoken(&tty_token);
517         return ENXIO;
518     }
519
520     tp = dev->si_tty = ttymalloc(dev->si_tty);
521     tp->t_oproc = scstart;
522     tp->t_param = scparam;
523     tp->t_stop = nottystop;
524
525     tp->t_dev = dev;
526
527     if (!ISTTYOPEN(tp)) {
528         ttychars(tp);
529         /* Use the current setting of the <-- key as default VERASE. */  
530         /* If the Delete key is preferable, an stty is necessary     */
531         if (sc->kbd != NULL) {
532             key.keynum = KEYCODE_BS;
533             kbd_ioctl(sc->kbd, GIO_KEYMAPENT, (caddr_t)&key);
534             tp->t_cc[VERASE] = key.key.map[0];
535         }
536         tp->t_iflag = TTYDEF_IFLAG;
537         tp->t_oflag = TTYDEF_OFLAG;
538         tp->t_cflag = TTYDEF_CFLAG;
539         tp->t_lflag = TTYDEF_LFLAG;
540         tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
541         scparam(tp, &tp->t_termios);
542         (*linesw[tp->t_line].l_modem)(tp, 1);
543     }
544     else
545         if (tp->t_state & TS_XCLUDE && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) {
546             lwkt_reltoken(&tty_token);
547             return(EBUSY);
548         }
549
550     error = (*linesw[tp->t_line].l_open)(dev, tp);
551
552     scp = SC_STAT(dev);
553     if (scp == NULL) {
554         scp = dev->si_drv1 = alloc_scp(sc, SC_VTY(dev));
555         syscons_lock();
556         if (ISGRAPHSC(scp))
557             sc_set_pixel_mode(scp, NULL, COL, ROW, 16);
558         syscons_unlock();
559     }
560     if (!tp->t_winsize.ws_col && !tp->t_winsize.ws_row) {
561         tp->t_winsize.ws_col = scp->xsize;
562         tp->t_winsize.ws_row = scp->ysize;
563     }
564
565     lwkt_reltoken(&tty_token);
566     return error;
567 }
568
569 int
570 scclose(struct dev_close_args *ap)
571 {
572     cdev_t dev = ap->a_head.a_dev;
573     struct tty *tp = dev->si_tty;
574     scr_stat *scp;
575
576     lwkt_gettoken(&tty_token);
577     if (SC_VTY(dev) != SC_CONSOLECTL) {
578         scp = SC_STAT(tp->t_dev);
579         /* were we in the middle of the VT switching process? */
580         DPRINTF(5, ("sc%d: scclose(), ", scp->sc->unit));
581         if ((scp == scp->sc->cur_scp) && (scp->sc->unit == sc_console_unit))
582             cons_unavail = FALSE;
583         if (finish_vt_rel(scp, TRUE) == 0)      /* force release */
584             DPRINTF(5, ("reset WAIT_REL, "));
585         if (finish_vt_acq(scp) == 0)            /* force acknowledge */
586             DPRINTF(5, ("reset WAIT_ACQ, "));
587         syscons_lock();
588 #if 0 /* notyet */
589         if (scp == &main_console) {
590             scp->pid = 0;
591             scp->proc = NULL;
592             scp->smode.mode = VT_AUTO;
593         }
594         else {
595             sc_vtb_destroy(&scp->vtb);
596             sc_vtb_destroy(&scp->scr);
597             sc_free_history_buffer(scp, scp->ysize);
598             SC_STAT(dev) = NULL;
599             kfree(scp, M_SYSCONS);
600         }
601 #else
602         scp->pid = 0;
603         scp->proc = NULL;
604         scp->smode.mode = VT_AUTO;
605 #endif
606         scp->kbd_mode = K_XLATE;
607         syscons_unlock();
608         if (scp == scp->sc->cur_scp)
609             kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
610         DPRINTF(5, ("done.\n"));
611     }
612     (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
613     ttyclose(tp);
614     lwkt_reltoken(&tty_token);
615
616     return(0);
617 }
618
619 int
620 scread(struct dev_read_args *ap)
621 {
622     int ret;
623
624     lwkt_gettoken(&tty_token);
625     sc_touch_scrn_saver();
626     ret = ttyread(ap);
627     lwkt_reltoken(&tty_token);
628     return ret;
629 }
630
631 static int
632 sckbdevent(keyboard_t *thiskbd, int event, void *arg)
633 {
634     sc_softc_t *sc;
635     struct tty *cur_tty;
636     int c; 
637     size_t len;
638     u_char *cp;
639
640     lwkt_gettoken(&tty_token);
641     /*
642      * WARNING: In early boot sc->dev may not be setup yet.
643      */
644     sc = (sc_softc_t *)arg;
645     /* assert(thiskbd == sc->kbd) */
646
647     switch (event) {
648     case KBDIO_KEYINPUT:
649         break;
650     case KBDIO_UNLOADING:
651         syscons_lock();
652         sc->kbd = NULL;
653         sc->keyboard = -1;
654         syscons_unlock();
655         kbd_release(thiskbd, (void *)&sc->keyboard);
656         lwkt_reltoken(&tty_token);
657         return 0;
658     default:
659         lwkt_reltoken(&tty_token);
660         return EINVAL;
661     }
662
663     /* 
664      * Loop while there is still input to get from the keyboard.
665      * I don't think this is nessesary, and it doesn't fix
666      * the Xaccel-2.1 keyboard hang, but it can't hurt.         XXX
667      */
668     while ((c = scgetc(sc, SCGETC_NONBLOCK)) != NOKEY) {
669         cur_tty = VIRTUAL_TTY(sc, sc->cur_scp->index);
670         if (!ISTTYOPEN(cur_tty)) {
671             cur_tty = sc_console_tty;
672             if (!ISTTYOPEN(cur_tty))
673                 continue;
674         }
675
676         syscons_lock();
677         if ((*sc->cur_scp->tsw->te_input)(sc->cur_scp, c, cur_tty)) {
678             syscons_unlock();
679             continue;
680         }
681         syscons_unlock();
682
683         switch (KEYFLAGS(c)) {
684         case 0x0000: /* normal key */
685             (*linesw[cur_tty->t_line].l_rint)(KEYCHAR(c), cur_tty);
686             break;
687         case FKEY:  /* function key, return string */
688             cp = kbd_get_fkeystr(thiskbd, KEYCHAR(c), &len);
689             if (cp != NULL) {
690                 while (len-- >  0)
691                     (*linesw[cur_tty->t_line].l_rint)(*cp++, cur_tty);
692             }
693             break;
694         case MKEY:  /* meta is active, prepend ESC */
695             (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
696             (*linesw[cur_tty->t_line].l_rint)(KEYCHAR(c), cur_tty);
697             break;
698         case BKEY:  /* backtab fixed sequence (esc [ Z) */
699             (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
700             (*linesw[cur_tty->t_line].l_rint)('[', cur_tty);
701             (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty);
702             break;
703         }
704     }
705
706     syscons_lock();
707     sc->cur_scp->status |= MOUSE_HIDDEN;
708     syscons_unlock();
709
710     lwkt_reltoken(&tty_token);
711     return 0;
712 }
713
714 static int
715 scparam(struct tty *tp, struct termios *t)
716 {
717     lwkt_gettoken(&tty_token);
718     tp->t_ispeed = t->c_ispeed;
719     tp->t_ospeed = t->c_ospeed;
720     tp->t_cflag = t->c_cflag;
721     lwkt_reltoken(&tty_token);
722     return 0;
723 }
724
725 int
726 scioctl(struct dev_ioctl_args *ap)
727 {
728     cdev_t dev = ap->a_head.a_dev;
729     u_long cmd = ap->a_cmd;
730     caddr_t data = ap->a_data;
731     int flag = ap->a_fflag;
732     int error;
733     int i;
734     struct tty *tp;
735     sc_softc_t *sc;
736     scr_stat *scp;
737
738     lwkt_gettoken(&tty_token);
739     tp = dev->si_tty;
740
741     error = sc_vid_ioctl(tp, cmd, data, flag);
742     if (error != ENOIOCTL) {
743         lwkt_reltoken(&tty_token);
744         return error;
745     }
746
747 #ifndef SC_NO_HISTORY
748     error = sc_hist_ioctl(tp, cmd, data, flag);
749     if (error != ENOIOCTL) {
750         lwkt_reltoken(&tty_token);
751         return error;
752     }
753 #endif
754
755 #ifndef SC_NO_SYSMOUSE
756     error = sc_mouse_ioctl(tp, cmd, data, flag);
757     if (error != ENOIOCTL) {
758         lwkt_reltoken(&tty_token);
759         return error;
760     }
761 #endif
762
763     scp = SC_STAT(tp->t_dev);
764     /* assert(scp != NULL) */
765     /* scp is sc_console, if SC_VTY(dev) == SC_CONSOLECTL. */
766     sc = scp->sc;
767
768     if (scp->tsw) {
769         syscons_lock();
770         error = (*scp->tsw->te_ioctl)(scp, tp, cmd, data, flag);
771         syscons_unlock();
772         if (error != ENOIOCTL) {
773             lwkt_reltoken(&tty_token);
774             return error;
775         }
776     }
777
778     switch (cmd) {              /* process console hardware related ioctl's */
779
780     case GIO_ATTR:              /* get current attributes */
781         /* this ioctl is not processed here, but in the terminal emulator */
782         lwkt_reltoken(&tty_token);
783         return ENOTTY;
784
785     case GIO_COLOR:             /* is this a color console ? */
786         *(int *)data = (sc->adp->va_flags & V_ADP_COLOR) ? 1 : 0;
787         lwkt_reltoken(&tty_token);
788         return 0;
789
790     case CONS_BLANKTIME:        /* set screen saver timeout (0 = no saver) */
791         if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME) {
792             lwkt_reltoken(&tty_token);
793             return EINVAL;
794         }
795         syscons_lock();
796         scrn_blank_time = *(int *)data;
797         run_scrn_saver = (scrn_blank_time != 0);
798         syscons_unlock();
799         lwkt_reltoken(&tty_token);
800         return 0;
801
802     case CONS_CURSORTYPE:       /* set cursor type blink/noblink */
803         syscons_lock();
804         if (!ISGRAPHSC(sc->cur_scp))
805             sc_remove_cursor_image(sc->cur_scp);
806         if ((*(int*)data) & 0x01)
807             sc->flags |= SC_BLINK_CURSOR;
808         else
809             sc->flags &= ~SC_BLINK_CURSOR;
810         if ((*(int*)data) & 0x02) {
811             sc->flags |= SC_CHAR_CURSOR;
812         } else
813             sc->flags &= ~SC_CHAR_CURSOR;
814         /* 
815          * The cursor shape is global property; all virtual consoles
816          * are affected. Update the cursor in the current console...
817          */
818         if (!ISGRAPHSC(sc->cur_scp)) {
819             sc_set_cursor_image(sc->cur_scp);
820             sc_draw_cursor_image(sc->cur_scp);
821         }
822         syscons_unlock();
823         lwkt_reltoken(&tty_token);
824         return 0;
825
826     case CONS_BELLTYPE:         /* set bell type sound/visual */
827         syscons_lock();
828
829         if ((*(int *)data) & 0x01)
830             sc->flags |= SC_VISUAL_BELL;
831         else
832             sc->flags &= ~SC_VISUAL_BELL;
833
834         if ((*(int *)data) & 0x02)
835             sc->flags |= SC_QUIET_BELL;
836         else
837             sc->flags &= ~SC_QUIET_BELL;
838
839         syscons_unlock();
840         lwkt_reltoken(&tty_token);
841         return 0;
842
843     case CONS_GETINFO:          /* get current (virtual) console info */
844     {
845         vid_info_t *ptr = (vid_info_t*)data;
846         if (ptr->size == sizeof(struct vid_info)) {
847             ptr->m_num = sc->cur_scp->index;
848             ptr->font_size = scp->font_size;
849             ptr->mv_col = scp->xpos;
850             ptr->mv_row = scp->ypos;
851             ptr->mv_csz = scp->xsize;
852             ptr->mv_rsz = scp->ysize;
853             /*
854              * The following fields are filled by the terminal emulator. XXX
855              *
856              * ptr->mv_norm.fore
857              * ptr->mv_norm.back
858              * ptr->mv_rev.fore
859              * ptr->mv_rev.back
860              */
861             ptr->mv_grfc.fore = 0;      /* not supported */
862             ptr->mv_grfc.back = 0;      /* not supported */
863             ptr->mv_ovscan = scp->border;
864             if (scp == sc->cur_scp)
865                 save_kbd_state(scp, FALSE);
866             ptr->mk_keylock = scp->status & LOCK_MASK;
867             lwkt_reltoken(&tty_token);
868             return 0;
869         }
870         lwkt_reltoken(&tty_token);
871         return EINVAL;
872     }
873
874     case CONS_GETVERS:          /* get version number */
875         *(int*)data = 0x200;    /* version 2.0 */
876         lwkt_reltoken(&tty_token);
877         return 0;
878
879     case CONS_IDLE:             /* see if the screen has been idle */
880         /*
881          * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE,
882          * the user process may have been writing something on the
883          * screen and syscons is not aware of it. Declare the screen
884          * is NOT idle if it is in one of these modes. But there is
885          * an exception to it; if a screen saver is running in the 
886          * graphics mode in the current screen, we should say that the
887          * screen has been idle.
888          */
889         *(int *)data = (sc->flags & SC_SCRN_IDLE)
890                        && (!ISGRAPHSC(sc->cur_scp)
891                            || (sc->cur_scp->status & SAVER_RUNNING));
892         lwkt_reltoken(&tty_token);
893         return 0;
894
895     case CONS_SAVERMODE:        /* set saver mode */
896         switch(*(int *)data) {
897         case CONS_NO_SAVER:
898         case CONS_USR_SAVER:
899             syscons_lock();
900             /* if a LKM screen saver is running, stop it first. */
901             scsplash_stick(FALSE);
902             saver_mode = *(int *)data;
903 #if NSPLASH > 0
904             if ((error = wait_scrn_saver_stop(NULL))) {
905                 syscons_unlock();
906                 lwkt_reltoken(&tty_token);
907                 return error;
908             }
909 #endif /* NSPLASH */
910             run_scrn_saver = TRUE;
911             if (saver_mode == CONS_USR_SAVER)
912                 scp->status |= SAVER_RUNNING;
913             else
914                 scp->status &= ~SAVER_RUNNING;
915             scsplash_stick(TRUE);
916             syscons_unlock();
917             break;
918         case CONS_LKM_SAVER:
919             syscons_lock();
920             if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING))
921                 scp->status &= ~SAVER_RUNNING;
922             saver_mode = *(int *)data;
923             syscons_unlock();
924             break;
925         default:
926             lwkt_reltoken(&tty_token);
927             return EINVAL;
928         }
929         lwkt_reltoken(&tty_token);
930         return 0;
931
932     case CONS_SAVERSTART:       /* immediately start/stop the screen saver */
933         /*
934          * Note that this ioctl does not guarantee the screen saver 
935          * actually starts or stops. It merely attempts to do so...
936          */
937         syscons_lock();
938         run_scrn_saver = (*(int *)data != 0);
939         if (run_scrn_saver)
940             sc->scrn_time_stamp -= scrn_blank_time;
941         syscons_unlock();
942         lwkt_reltoken(&tty_token);
943         return 0;
944
945     case CONS_SCRSHOT:          /* get a screen shot */
946     {
947         scrshot_t *ptr = (scrshot_t*)data;
948         syscons_lock();
949         if (ISGRAPHSC(scp)) {
950             syscons_unlock();
951             lwkt_reltoken(&tty_token);
952             return EOPNOTSUPP;
953         }
954         if (scp->xsize != ptr->xsize || scp->ysize != ptr->ysize) {
955             syscons_unlock();
956             lwkt_reltoken(&tty_token);
957             return EINVAL;
958         }
959         syscons_unlock();
960         copyout ((void*)scp->vtb.vtb_buffer, ptr->buf,
961                  ptr->xsize * ptr->ysize * sizeof(uint16_t));
962         lwkt_reltoken(&tty_token);
963         return 0;
964     }
965
966     case VT_SETMODE:            /* set screen switcher mode */
967     {
968         struct vt_mode *mode;
969
970         mode = (struct vt_mode *)data;
971         DPRINTF(5, ("sc%d: VT_SETMODE ", sc->unit));
972         if (scp->smode.mode == VT_PROCESS) {
973             lwkt_gettoken(&proc_token);
974             if (scp->proc == pfindn(scp->pid) && scp->proc != curproc) {
975                 DPRINTF(5, ("error EPERM\n"));
976                 lwkt_reltoken(&proc_token);
977                 lwkt_reltoken(&tty_token);
978                 return EPERM;
979             }
980             lwkt_reltoken(&proc_token);
981         }
982         syscons_lock();
983         if (mode->mode == VT_AUTO) {
984             scp->smode.mode = VT_AUTO;
985             scp->proc = NULL;
986             scp->pid = 0;
987             DPRINTF(5, ("VT_AUTO, "));
988             if ((scp == sc->cur_scp) && (sc->unit == sc_console_unit))
989                 cons_unavail = FALSE;
990             if (finish_vt_rel(scp, TRUE) == 0)
991                 DPRINTF(5, ("reset WAIT_REL, "));
992             if (finish_vt_acq(scp) == 0)
993                 DPRINTF(5, ("reset WAIT_ACQ, "));
994         } else {
995             if (!ISSIGVALID(mode->relsig) || !ISSIGVALID(mode->acqsig)
996                 || !ISSIGVALID(mode->frsig)) {
997                 syscons_unlock();
998                 DPRINTF(5, ("error EINVAL\n"));
999                 lwkt_reltoken(&tty_token);
1000                 return EINVAL;
1001             }
1002             DPRINTF(5, ("VT_PROCESS %d, ", curproc->p_pid));
1003             syscons_unlock();
1004             lwkt_gettoken(&proc_token);
1005             syscons_lock();
1006             bcopy(data, &scp->smode, sizeof(struct vt_mode));
1007             scp->proc = curproc;
1008             scp->pid = scp->proc->p_pid;
1009             lwkt_reltoken(&proc_token);
1010             if ((scp == sc->cur_scp) && (sc->unit == sc_console_unit))
1011                 cons_unavail = TRUE;
1012         }
1013         syscons_unlock();
1014         DPRINTF(5, ("\n"));
1015         lwkt_reltoken(&tty_token);
1016         return 0;
1017     }
1018
1019     case VT_GETMODE:            /* get screen switcher mode */
1020         bcopy(&scp->smode, data, sizeof(struct vt_mode));
1021         lwkt_reltoken(&tty_token);
1022         return 0;
1023
1024     case VT_RELDISP:            /* screen switcher ioctl */
1025         /*
1026          * This must be the current vty which is in the VT_PROCESS
1027          * switching mode...
1028          */
1029         syscons_lock();
1030         if ((scp != sc->cur_scp) || (scp->smode.mode != VT_PROCESS)) {
1031             syscons_unlock();
1032             lwkt_reltoken(&tty_token);
1033             return EINVAL;
1034         }
1035         /* ...and this process is controlling it. */
1036         if (scp->proc != curproc) {
1037             syscons_unlock();
1038             lwkt_reltoken(&tty_token);
1039             return EPERM;
1040         }
1041         error = EINVAL;
1042         switch(*(int *)data) {
1043         case VT_FALSE:          /* user refuses to release screen, abort */
1044             if ((error = finish_vt_rel(scp, FALSE)) == 0)
1045                 DPRINTF(5, ("sc%d: VT_FALSE\n", sc->unit));
1046             break;
1047         case VT_TRUE:           /* user has released screen, go on */
1048             if ((error = finish_vt_rel(scp, TRUE)) == 0)
1049                 DPRINTF(5, ("sc%d: VT_TRUE\n", sc->unit));
1050             break;
1051         case VT_ACKACQ:         /* acquire acknowledged, switch completed */
1052             if ((error = finish_vt_acq(scp)) == 0)
1053                 DPRINTF(5, ("sc%d: VT_ACKACQ\n", sc->unit));
1054             break;
1055         default:
1056             break;
1057         }
1058         syscons_unlock();
1059         lwkt_reltoken(&tty_token);
1060         return error;
1061
1062     case VT_OPENQRY:            /* return free virtual console */
1063         for (i = sc->first_vty; i < sc->first_vty + sc->vtys; i++) {
1064             tp = VIRTUAL_TTY(sc, i);
1065             if (!ISTTYOPEN(tp)) {
1066                 *(int *)data = i + 1;
1067                 lwkt_reltoken(&tty_token);
1068                 return 0;
1069             }
1070         }
1071         lwkt_reltoken(&tty_token);
1072         return EINVAL;
1073
1074     case VT_ACTIVATE:           /* switch to screen *data */
1075         i = (*(int *)data == 0) ? scp->index : (*(int *)data - 1);
1076         syscons_lock();
1077         sc_clean_up(sc->cur_scp);
1078         error = sc_switch_scr(sc, i);
1079         syscons_unlock();
1080         lwkt_reltoken(&tty_token);
1081         return error;
1082
1083     case VT_WAITACTIVE:         /* wait for switch to occur */
1084         i = (*(int *)data == 0) ? scp->index : (*(int *)data - 1);
1085         if ((i < sc->first_vty) || (i >= sc->first_vty + sc->vtys)) {
1086             lwkt_reltoken(&tty_token);
1087             return EINVAL;
1088         }
1089         syscons_lock();
1090         error = sc_clean_up(sc->cur_scp);
1091         syscons_unlock();
1092         if (error) {
1093             lwkt_reltoken(&tty_token);
1094             return error;
1095         }
1096         scp = SC_STAT(SC_DEV(sc, i));
1097         if (scp == scp->sc->cur_scp) {
1098             lwkt_reltoken(&tty_token);
1099             return 0;
1100         }
1101         error = tsleep((caddr_t)&scp->smode, PCATCH, "waitvt", 0);
1102         /* May return ERESTART */
1103         lwkt_reltoken(&tty_token);
1104         return error;
1105
1106     case VT_GETACTIVE:          /* get active vty # */
1107         *(int *)data = sc->cur_scp->index + 1;
1108         lwkt_reltoken(&tty_token);
1109         return 0;
1110
1111     case VT_GETINDEX:           /* get this vty # */
1112         *(int *)data = scp->index + 1;
1113         lwkt_reltoken(&tty_token);
1114         return 0;
1115
1116     case VT_LOCKSWITCH:         /* prevent vty switching */
1117         syscons_lock();
1118         if ((*(int *)data) & 0x01)
1119             sc->flags |= SC_SCRN_VTYLOCK;
1120         else
1121             sc->flags &= ~SC_SCRN_VTYLOCK;
1122         syscons_unlock();
1123         lwkt_reltoken(&tty_token);
1124         return 0;
1125
1126     case KDENABIO:              /* allow io operations */
1127         error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
1128         if (error != 0) {
1129             lwkt_reltoken(&tty_token);
1130             return error;
1131         }
1132         if (securelevel > 0) {
1133             lwkt_reltoken(&tty_token);
1134             return EPERM;
1135         }
1136         lwkt_gettoken(&proc_token);
1137 #if defined(__i386__)
1138         curthread->td_lwp->lwp_md.md_regs->tf_eflags |= PSL_IOPL;
1139 #elif defined(__x86_64__)
1140         curthread->td_lwp->lwp_md.md_regs->tf_rflags |= PSL_IOPL;
1141 #endif
1142         lwkt_reltoken(&proc_token);
1143         lwkt_reltoken(&tty_token);
1144         return 0;
1145
1146     case KDDISABIO:             /* disallow io operations (default) */
1147         lwkt_gettoken(&proc_token);
1148 #if defined(__i386__)
1149         curthread->td_lwp->lwp_md.md_regs->tf_eflags &= ~PSL_IOPL;
1150 #elif defined(__x86_64__)
1151         curthread->td_lwp->lwp_md.md_regs->tf_rflags &= ~PSL_IOPL;
1152 #endif
1153         lwkt_reltoken(&proc_token);
1154         lwkt_reltoken(&tty_token);
1155         return 0;
1156
1157     case KDSKBSTATE:            /* set keyboard state (locks) */
1158         if (*(int *)data & ~LOCK_MASK) {
1159             lwkt_reltoken(&tty_token);
1160             return EINVAL;
1161         }
1162         syscons_lock();
1163         scp->status &= ~LOCK_MASK;
1164         scp->status |= *(int *)data;
1165         syscons_unlock();
1166         if (scp == sc->cur_scp)
1167             update_kbd_state(scp, scp->status, LOCK_MASK, FALSE);
1168         lwkt_reltoken(&tty_token);
1169         return 0;
1170
1171     case KDGKBSTATE:            /* get keyboard state (locks) */
1172         if (scp == sc->cur_scp)
1173             save_kbd_state(scp, FALSE);
1174         *(int *)data = scp->status & LOCK_MASK;
1175         lwkt_reltoken(&tty_token);
1176         return 0;
1177
1178     case KDGETREPEAT:           /* get keyboard repeat & delay rates */
1179     case KDSETREPEAT:           /* set keyboard repeat & delay rates (new) */
1180         error = kbd_ioctl(sc->kbd, cmd, data);
1181         if (error == ENOIOCTL)
1182             error = ENODEV;
1183         lwkt_reltoken(&tty_token);
1184         return error;
1185
1186     case KDSETRAD:              /* set keyboard repeat & delay rates (old) */
1187         if (*(int *)data & ~0x7f) {
1188             lwkt_reltoken(&tty_token);
1189             return EINVAL;
1190         }
1191         error = kbd_ioctl(sc->kbd, cmd, data);
1192         if (error == ENOIOCTL)
1193             error = ENODEV;
1194         lwkt_reltoken(&tty_token);
1195         return error;
1196
1197     case KDSKBMODE:             /* set keyboard mode */
1198         switch (*(int *)data) {
1199         case K_XLATE:           /* switch to XLT ascii mode */
1200         case K_RAW:             /* switch to RAW scancode mode */
1201         case K_CODE:            /* switch to CODE mode */
1202             scp->kbd_mode = *(int *)data;
1203             if (scp == sc->cur_scp)
1204                 kbd_ioctl(sc->kbd, cmd, data);
1205             lwkt_reltoken(&tty_token);
1206             return 0;
1207         default:
1208             lwkt_reltoken(&tty_token);
1209             return EINVAL;
1210         }
1211         /* NOT REACHED */
1212
1213     case KDGKBMODE:             /* get keyboard mode */
1214         *(int *)data = scp->kbd_mode;
1215         lwkt_reltoken(&tty_token);
1216         return 0;
1217
1218     case KDGKBINFO:
1219         error = kbd_ioctl(sc->kbd, cmd, data);
1220         if (error == ENOIOCTL)
1221             error = ENODEV;
1222         lwkt_reltoken(&tty_token);
1223         return error;
1224
1225     case KDMKTONE:              /* sound the bell */
1226         syscons_lock();
1227         if (*(int*)data)
1228             sc_bell(scp, (*(int*)data)&0xffff,
1229                     (((*(int*)data)>>16)&0xffff)*hz/1000);
1230         else
1231             sc_bell(scp, scp->bell_pitch, scp->bell_duration);
1232         syscons_unlock();
1233         lwkt_reltoken(&tty_token);
1234         return 0;
1235
1236     case KIOCSOUND:             /* make tone (*data) hz */
1237         syscons_lock();
1238         if (scp == sc->cur_scp) {
1239             if (*(int *)data) {
1240                 error = sc_tone(*(int *)data);
1241             } else {
1242                 error = sc_tone(0);
1243             }
1244         } else {
1245             error = 0;
1246         }
1247         syscons_unlock();
1248         lwkt_reltoken(&tty_token);
1249         return error;
1250
1251     case KDGKBTYPE:             /* get keyboard type */
1252         error = kbd_ioctl(sc->kbd, cmd, data);
1253         if (error == ENOIOCTL) {
1254             /* always return something? XXX */
1255             *(int *)data = 0;
1256         }
1257         lwkt_reltoken(&tty_token);
1258         return 0;
1259
1260     case KDSETLED:              /* set keyboard LED status */
1261         if (*(int *)data & ~LED_MASK) { /* FIXME: LOCK_MASK? */
1262             lwkt_reltoken(&tty_token);
1263             return EINVAL;
1264         }
1265         syscons_lock();
1266         scp->status &= ~LED_MASK;
1267         scp->status |= *(int *)data;
1268         syscons_unlock();
1269         if (scp == sc->cur_scp)
1270             update_kbd_leds(scp, scp->status);
1271         lwkt_reltoken(&tty_token);
1272         return 0;
1273
1274     case KDGETLED:              /* get keyboard LED status */
1275         if (scp == sc->cur_scp)
1276             save_kbd_state(scp, FALSE);
1277         *(int *)data = scp->status & LED_MASK;
1278         lwkt_reltoken(&tty_token);
1279         return 0;
1280
1281         case KBADDKBD:              /* add/remove keyboard to/from mux */
1282         case KBRELKBD:
1283                 error = kbd_ioctl(sc->kbd, cmd, data);
1284                 if (error == ENOIOCTL)
1285                         error = ENODEV;
1286                 lwkt_reltoken(&tty_token);
1287                 return error;
1288
1289     case CONS_SETKBD:           /* set the new keyboard */
1290         {
1291             keyboard_t *newkbd;
1292
1293             newkbd = kbd_get_keyboard(*(int *)data);
1294             if (newkbd == NULL) {
1295                 lwkt_reltoken(&tty_token);
1296                 return EINVAL;
1297             }
1298             error = 0;
1299             if (sc->kbd != newkbd) {
1300                 i = kbd_allocate(newkbd->kb_name, newkbd->kb_unit,
1301                                  (void *)&sc->keyboard, sckbdevent, sc);
1302                 /* i == newkbd->kb_index */
1303                 if (i >= 0) {
1304                     if (sc->kbd != NULL) {
1305                         save_kbd_state(sc->cur_scp, FALSE);
1306                         kbd_release(sc->kbd, (void *)&sc->keyboard);
1307                     }
1308                     syscons_lock();
1309                     sc->kbd = kbd_get_keyboard(i); /* sc->kbd == newkbd */
1310                     sc->keyboard = i;
1311                     syscons_unlock();
1312                     kbd_ioctl(sc->kbd, KDSKBMODE,
1313                               (caddr_t)&sc->cur_scp->kbd_mode);
1314                     update_kbd_state(sc->cur_scp, sc->cur_scp->status,
1315                         LOCK_MASK, FALSE);
1316                 } else {
1317                     error = EPERM;      /* XXX */
1318                 }
1319             }
1320             lwkt_reltoken(&tty_token);
1321             return error;
1322         }
1323
1324     case CONS_RELKBD:           /* release the current keyboard */
1325         error = 0;
1326         if (sc->kbd != NULL) {
1327             save_kbd_state(sc->cur_scp, FALSE);
1328             error = kbd_release(sc->kbd, (void *)&sc->keyboard);
1329             if (error == 0) {
1330                 syscons_lock();
1331                 sc->kbd = NULL;
1332                 sc->keyboard = -1;
1333                 syscons_unlock();
1334             }
1335         }
1336         lwkt_reltoken(&tty_token);
1337         return error;
1338
1339     case CONS_GETTERM:          /* get the current terminal emulator info */
1340         {
1341             sc_term_sw_t *sw;
1342
1343             if (((term_info_t *)data)->ti_index == 0) {
1344                 sw = scp->tsw;
1345             } else {
1346                 sw = sc_term_match_by_number(((term_info_t *)data)->ti_index);
1347             }
1348             if (sw != NULL) {
1349                 strncpy(((term_info_t *)data)->ti_name, sw->te_name, 
1350                         sizeof(((term_info_t *)data)->ti_name));
1351                 strncpy(((term_info_t *)data)->ti_desc, sw->te_desc, 
1352                         sizeof(((term_info_t *)data)->ti_desc));
1353                 ((term_info_t *)data)->ti_flags = 0;
1354                 lwkt_reltoken(&tty_token);
1355                 return 0;
1356             } else {
1357                 ((term_info_t *)data)->ti_name[0] = '\0';
1358                 ((term_info_t *)data)->ti_desc[0] = '\0';
1359                 ((term_info_t *)data)->ti_flags = 0;
1360                 lwkt_reltoken(&tty_token);
1361                 return EINVAL;
1362             }
1363         }
1364
1365     case CONS_SETTERM:          /* set the current terminal emulator */
1366         syscons_lock();
1367         error = sc_init_emulator(scp, ((term_info_t *)data)->ti_name);
1368         /* FIXME: what if scp == sc_console! XXX */
1369         syscons_unlock();
1370         lwkt_reltoken(&tty_token);
1371         return error;
1372
1373     case GIO_SCRNMAP:           /* get output translation table */
1374         bcopy(&sc->scr_map, data, sizeof(sc->scr_map));
1375         lwkt_reltoken(&tty_token);
1376         return 0;
1377
1378     case PIO_SCRNMAP:           /* set output translation table */
1379         bcopy(data, &sc->scr_map, sizeof(sc->scr_map));
1380         for (i=0; i<sizeof(sc->scr_map); i++) {
1381             sc->scr_rmap[sc->scr_map[i]] = i;
1382         }
1383         lwkt_reltoken(&tty_token);
1384         return 0;
1385
1386     case GIO_KEYMAP:            /* get keyboard translation table */
1387     case PIO_KEYMAP:            /* set keyboard translation table */
1388     case GIO_DEADKEYMAP:        /* get accent key translation table */
1389     case PIO_DEADKEYMAP:        /* set accent key translation table */
1390     case GETFKEY:               /* get function key string */
1391     case SETFKEY:               /* set function key string */
1392         error = kbd_ioctl(sc->kbd, cmd, data);
1393         if (error == ENOIOCTL)
1394             error = ENODEV;
1395         lwkt_reltoken(&tty_token);
1396         return error;
1397
1398 #ifndef SC_NO_FONT_LOADING
1399
1400     case PIO_FONT8x8:           /* set 8x8 dot font */
1401         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1402             lwkt_reltoken(&tty_token);
1403             return ENXIO;
1404         }
1405         syscons_lock();
1406         bcopy(data, sc->font_8, 8*256);
1407         sc->fonts_loaded |= FONT_8;
1408         /*
1409          * FONT KLUDGE
1410          * Always use the font page #0. XXX
1411          * Don't load if the current font size is not 8x8.
1412          */
1413         if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size < 14))
1414             sc_load_font(sc->cur_scp, 0, 8, sc->font_8, 0, 256);
1415         syscons_unlock();
1416         lwkt_reltoken(&tty_token);
1417         return 0;
1418
1419     case GIO_FONT8x8:           /* get 8x8 dot font */
1420         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1421             lwkt_reltoken(&tty_token);
1422             return ENXIO;
1423         }
1424         if (sc->fonts_loaded & FONT_8) {
1425             bcopy(sc->font_8, data, 8*256);
1426             lwkt_reltoken(&tty_token);
1427             return 0;
1428         }
1429         else {
1430             lwkt_reltoken(&tty_token);
1431             return ENXIO;
1432         }
1433
1434     case PIO_FONT8x14:          /* set 8x14 dot font */
1435         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1436             lwkt_reltoken(&tty_token);
1437             return ENXIO;
1438         }
1439         syscons_lock();
1440         bcopy(data, sc->font_14, 14*256);
1441         sc->fonts_loaded |= FONT_14;
1442         /*
1443          * FONT KLUDGE
1444          * Always use the font page #0. XXX
1445          * Don't load if the current font size is not 8x14.
1446          */
1447         if (ISTEXTSC(sc->cur_scp)
1448             && (sc->cur_scp->font_size >= 14)
1449             && (sc->cur_scp->font_size < 16)) {
1450             sc_load_font(sc->cur_scp, 0, 14, sc->font_14, 0, 256);
1451         }
1452         syscons_unlock();
1453         lwkt_reltoken(&tty_token);
1454         return 0;
1455
1456     case GIO_FONT8x14:          /* get 8x14 dot font */
1457         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1458             lwkt_reltoken(&tty_token);
1459             return ENXIO;
1460         }
1461         if (sc->fonts_loaded & FONT_14) {
1462             bcopy(sc->font_14, data, 14*256);
1463             lwkt_reltoken(&tty_token);
1464             return 0;
1465         }
1466         else {
1467             lwkt_reltoken(&tty_token);
1468             return ENXIO;
1469         }
1470
1471     case PIO_FONT8x16:          /* set 8x16 dot font */
1472         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1473             lwkt_reltoken(&tty_token);
1474             return ENXIO;
1475         }
1476         syscons_lock();
1477         bcopy(data, sc->font_16, 16*256);
1478         sc->fonts_loaded |= FONT_16;
1479         /*
1480          * FONT KLUDGE
1481          * Always use the font page #0. XXX
1482          * Don't load if the current font size is not 8x16.
1483          */
1484         if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size >= 16))
1485             sc_load_font(sc->cur_scp, 0, 16, sc->font_16, 0, 256);
1486         syscons_unlock();
1487         lwkt_reltoken(&tty_token);
1488         return 0;
1489
1490     case GIO_FONT8x16:          /* get 8x16 dot font */
1491         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1492             lwkt_reltoken(&tty_token);
1493             return ENXIO;
1494         }
1495         if (sc->fonts_loaded & FONT_16) {
1496             bcopy(sc->font_16, data, 16*256);
1497             lwkt_reltoken(&tty_token);
1498             return 0;
1499         }
1500         else {
1501             lwkt_reltoken(&tty_token);
1502             return ENXIO;
1503         }
1504
1505 #endif /* SC_NO_FONT_LOADING */
1506
1507     default:
1508         break;
1509     }
1510
1511     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, ap->a_cred);
1512     if (error != ENOIOCTL) {
1513         lwkt_reltoken(&tty_token);
1514         return(error);
1515     }
1516     error = ttioctl(tp, cmd, data, flag);
1517     if (error != ENOIOCTL) {
1518         lwkt_reltoken(&tty_token);
1519         return(error);
1520     }
1521     lwkt_reltoken(&tty_token);
1522     return(ENOTTY);
1523 }
1524
1525 static void
1526 scstart(struct tty *tp)
1527 {
1528     struct clist *rbp;
1529     int len;
1530     u_char buf[PCBURST];
1531     scr_stat *scp = SC_STAT(tp->t_dev);
1532
1533     syscons_lock();
1534     if (scp->status & SLKED ||
1535         (scp == scp->sc->cur_scp && scp->sc->blink_in_progress))
1536     {
1537         syscons_unlock();
1538         return;
1539     }
1540     if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
1541         tp->t_state |= TS_BUSY;
1542         rbp = &tp->t_outq;
1543         while (rbp->c_cc) {
1544             len = q_to_b(rbp, buf, PCBURST);
1545             sc_puts(scp, buf, len);
1546         }
1547         tp->t_state &= ~TS_BUSY;
1548         syscons_unlock();
1549         ttwwakeup(tp);
1550     } else {
1551         syscons_unlock();
1552     }
1553 }
1554
1555 static void
1556 sccnprobe(struct consdev *cp)
1557 {
1558     int unit;
1559     int flags;
1560
1561     cp->cn_pri = sc_get_cons_priority(&unit, &flags);
1562
1563     /* a video card is always required */
1564     if (!scvidprobe(unit, flags, TRUE))
1565         cp->cn_pri = CN_DEAD;
1566
1567     /* syscons will become console even when there is no keyboard */
1568     sckbdprobe(unit, flags, TRUE);
1569
1570     if (cp->cn_pri == CN_DEAD) {
1571         return;
1572     }
1573
1574     /* initialize required fields */
1575     cp->cn_probegood = 1;
1576 }
1577
1578 static void
1579 sccninit(struct consdev *cp)
1580 {
1581     int unit;
1582     int flags;
1583
1584     sc_get_cons_priority(&unit, &flags);
1585     scinit(unit, flags | SC_KERNEL_CONSOLE);
1586     sc_console_unit = unit;
1587     sc_console = sc_get_softc(unit, SC_KERNEL_CONSOLE)->console_scp;
1588 }
1589
1590 static void
1591 sccninit_fini(struct consdev *cp)
1592 {
1593         if (cctl_dev == NULL)
1594                 kprintf("sccninit_fini: WARNING: cctl_dev is NULL!\n");
1595         cp->cn_dev = cctl_dev;
1596 }
1597
1598 static void
1599 sccnterm(struct consdev *cp)
1600 {
1601     /* we are not the kernel console any more, release everything */
1602
1603     if (sc_console_unit < 0)
1604         return;                 /* shouldn't happen */
1605
1606 #if 0 /* XXX */
1607     syscons_lock();
1608     sc_clear_screen(sc_console);
1609     sccnupdate(sc_console);
1610     syscons_unlock();
1611 #endif
1612     scterm(sc_console_unit, SC_KERNEL_CONSOLE);
1613     sc_console_unit = -1;
1614     sc_console = NULL;
1615 }
1616
1617 /*
1618  * Console path - cannot block!
1619  */
1620 static void
1621 sccnputc(void *private, int c)
1622 {
1623     u_char buf[1];
1624     scr_stat *scp = sc_console;
1625     void *save;
1626 #ifndef SC_NO_HISTORY
1627 #if 0
1628     struct tty *tp;
1629 #endif
1630 #endif /* !SC_NO_HISTORY */
1631
1632     /* assert(sc_console != NULL) */
1633
1634     syscons_lock();
1635 #ifndef SC_NO_HISTORY
1636     if (scp == scp->sc->cur_scp && scp->status & SLKED) {
1637         scp->status &= ~SLKED;
1638 #if 0
1639         /* This can block, illegal in the console path */
1640         update_kbd_state(scp, scp->status, SLKED, TRUE);
1641 #endif
1642         if (scp->status & BUFFER_SAVED) {
1643             if (!sc_hist_restore(scp))
1644                 sc_remove_cutmarking(scp);
1645             scp->status &= ~BUFFER_SAVED;
1646             scp->status |= CURSOR_ENABLED;
1647             sc_draw_cursor_image(scp);
1648         }
1649 #if 0
1650         tp = VIRTUAL_TTY(scp->sc, scp->index);
1651         /* This can block, illegal in the console path */
1652         if (ISTTYOPEN(tp)) {
1653             scstart(tp);
1654         }
1655 #endif
1656     }
1657 #endif /* !SC_NO_HISTORY */
1658
1659     save = scp->ts;
1660     if (kernel_console_ts != NULL)
1661         scp->ts = kernel_console_ts;
1662     buf[0] = c;
1663     sc_puts(scp, buf, 1);
1664     scp->ts = save;
1665
1666     sccnupdate(scp);
1667     syscons_unlock();
1668 }
1669
1670 /*
1671  * Console path - cannot block!
1672  */
1673 static int
1674 sccngetc(void *private)
1675 {
1676     return sccngetch(0);
1677 }
1678
1679 /*
1680  * Console path - cannot block!
1681  */
1682 static int
1683 sccncheckc(void *private)
1684 {
1685     return sccngetch(SCGETC_NONBLOCK);
1686 }
1687
1688 static void
1689 sccndbctl(void *private, int on)
1690 {
1691     /* assert(sc_console_unit >= 0) */
1692     /* try to switch to the kernel console screen */
1693     if (on && debugger == 0) {
1694         /*
1695          * TRY to make sure the screen saver is stopped, 
1696          * and the screen is updated before switching to 
1697          * the vty0.
1698          */
1699         scrn_timer(NULL);
1700         if (!cold
1701             && sc_console->sc->cur_scp->smode.mode == VT_AUTO
1702             && sc_console->smode.mode == VT_AUTO) {
1703             sc_console->sc->cur_scp->status |= MOUSE_HIDDEN;
1704             syscons_lock();
1705             sc_switch_scr(sc_console->sc, sc_console->index);
1706             syscons_unlock();
1707         }
1708     }
1709     if (on)
1710         ++debugger;
1711     else
1712         --debugger;
1713 }
1714
1715 /*
1716  * Console path - cannot block!
1717  */
1718 static int
1719 sccngetch(int flags)
1720 {
1721     static struct fkeytab fkey;
1722     static int fkeycp;
1723     scr_stat *scp;
1724     u_char *p;
1725     int cur_mode;
1726     int c;
1727
1728     syscons_lock();
1729     /* assert(sc_console != NULL) */
1730
1731     /* 
1732      * Stop the screen saver and update the screen if necessary.
1733      * What if we have been running in the screen saver code... XXX
1734      */
1735     sc_touch_scrn_saver();
1736     scp = sc_console->sc->cur_scp;      /* XXX */
1737     sccnupdate(scp);
1738     syscons_unlock();
1739
1740     if (fkeycp < fkey.len) {
1741         return fkey.str[fkeycp++];
1742     }
1743
1744     if (scp->sc->kbd == NULL) {
1745         return -1;
1746     }
1747
1748     /* 
1749      * Make sure the keyboard is accessible even when the kbd device
1750      * driver is disabled.
1751      */
1752     crit_enter();
1753     kbd_enable(scp->sc->kbd);
1754
1755     /* we shall always use the keyboard in the XLATE mode here */
1756     cur_mode = scp->kbd_mode;
1757     scp->kbd_mode = K_XLATE;
1758     kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
1759
1760     kbd_poll(scp->sc->kbd, TRUE);
1761     c = scgetc(scp->sc, SCGETC_CN | flags);
1762     kbd_poll(scp->sc->kbd, FALSE);
1763
1764     scp->kbd_mode = cur_mode;
1765     kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
1766     kbd_disable(scp->sc->kbd);
1767     crit_exit();
1768
1769     switch (KEYFLAGS(c)) {
1770     case 0:     /* normal char */
1771         return KEYCHAR(c);
1772     case FKEY:  /* function key */
1773         p = kbd_get_fkeystr(scp->sc->kbd, KEYCHAR(c), (size_t *)&fkeycp);
1774         fkey.len = fkeycp;
1775         if ((p != NULL) && (fkey.len > 0)) {
1776             bcopy(p, fkey.str, fkey.len);
1777             fkeycp = 1;
1778             return fkey.str[0];
1779         }
1780         return c;       /* XXX */
1781     case NOKEY:
1782     case ERRKEY:
1783     default:
1784         return -1;
1785     }
1786     /* NOT REACHED */
1787 }
1788
1789 static void
1790 sccnupdate(scr_stat *scp)
1791 {
1792     /* this is a cut-down version of scrn_timer()... */
1793
1794     if (scp->sc->font_loading_in_progress || scp->sc->videoio_in_progress) {
1795         return;
1796     }
1797
1798     if (debugger > 0 || panicstr || shutdown_in_progress) {
1799         sc_touch_scrn_saver();
1800     } else if (scp != scp->sc->cur_scp) {
1801         return;
1802     }
1803
1804     if (!run_scrn_saver)
1805         scp->sc->flags &= ~SC_SCRN_IDLE;
1806 #if NSPLASH > 0
1807     /*
1808      * This is a hard path, we cannot call stop_scrn_saver() here.
1809      */
1810     if ((saver_mode != CONS_LKM_SAVER) || !(scp->sc->flags & SC_SCRN_IDLE))
1811         if (scp->sc->flags & SC_SCRN_BLANKED) {
1812             sc_touch_scrn_saver();
1813             /*stop_scrn_saver(scp->sc, current_saver);*/
1814         }
1815 #endif /* NSPLASH */
1816
1817     if (scp != scp->sc->cur_scp || scp->sc->blink_in_progress
1818         || scp->sc->switch_in_progress) {
1819         return;
1820     }
1821     /*
1822      * FIXME: unlike scrn_timer(), we call scrn_update() from here even
1823      * when write_in_progress is non-zero.  XXX
1824      */
1825
1826     if (!ISGRAPHSC(scp) && !(scp->sc->flags & SC_SCRN_BLANKED))
1827         scrn_update(scp, TRUE);
1828 }
1829
1830 static void
1831 scrn_timer(void *arg)
1832 {
1833     static int kbd_interval = 0;
1834     struct timeval tv;
1835     sc_softc_t *sc;
1836     scr_stat *scp;
1837     int again;
1838
1839     /*
1840      * Setup depending on who called us
1841      */
1842     again = (arg != NULL);
1843     if (arg != NULL) {
1844         sc = (sc_softc_t *)arg;
1845     } else if (sc_console != NULL) {
1846         sc = sc_console->sc;
1847     } else {
1848         return;
1849     }
1850
1851     /*
1852      * Don't do anything when we are performing some I/O operations.
1853      * (These are initiated by the frontend?)
1854      */
1855     if (sc->font_loading_in_progress || sc->videoio_in_progress) {
1856         if (again)
1857             callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
1858         return;
1859     }
1860
1861     /*
1862      * Try to allocate a keyboard automatically
1863      */
1864     if ((sc->kbd == NULL) && (sc->config & SC_AUTODETECT_KBD)) {
1865         if (++kbd_interval >= 25) {
1866             sc->keyboard = sc_allocate_keyboard(sc, -1);
1867             if (sc->keyboard >= 0) {
1868                 sc->kbd = kbd_get_keyboard(sc->keyboard);
1869                 kbd_ioctl(sc->kbd, KDSKBMODE,
1870                           (caddr_t)&sc->cur_scp->kbd_mode);
1871                 update_kbd_state(sc->cur_scp, sc->cur_scp->status,
1872                     LOCK_MASK, FALSE);
1873             }
1874             kbd_interval = 0;
1875         }
1876     }
1877
1878     /*
1879      * Should we stop the screen saver?  We need the syscons_lock
1880      * for most of this stuff.
1881      */
1882     getmicrouptime(&tv);
1883
1884     if (syscons_lock_nonblock() != 0) {
1885         /* failed to get the lock */
1886         if (again)
1887             callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
1888         return;
1889     }
1890     /* successful lock */
1891
1892     if (debugger > 0 || panicstr || shutdown_in_progress)
1893         sc_touch_scrn_saver();
1894     if (run_scrn_saver) {
1895         if (tv.tv_sec > sc->scrn_time_stamp + scrn_blank_time)
1896             sc->flags |= SC_SCRN_IDLE;
1897         else
1898             sc->flags &= ~SC_SCRN_IDLE;
1899     } else {
1900         sc->scrn_time_stamp = tv.tv_sec;
1901         sc->flags &= ~SC_SCRN_IDLE;
1902         if (scrn_blank_time > 0)
1903             run_scrn_saver = TRUE;
1904     }
1905 #if NSPLASH > 0
1906     if ((saver_mode != CONS_LKM_SAVER) || !(sc->flags & SC_SCRN_IDLE))
1907         if (sc->flags & SC_SCRN_BLANKED)
1908             stop_scrn_saver(sc, current_saver);
1909 #endif /* NSPLASH */
1910
1911     /* should we just return ? */
1912     if (sc->blink_in_progress || sc->switch_in_progress ||
1913         sc->write_in_progress)
1914     {
1915         syscons_unlock();
1916         if (again)
1917             callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
1918         return;
1919     }
1920
1921     /* Update the screen */
1922     scp = sc->cur_scp;          /* cur_scp may have changed... */
1923     if (!ISGRAPHSC(scp) && !(sc->flags & SC_SCRN_BLANKED))
1924         scrn_update(scp, TRUE);
1925
1926 #if NSPLASH > 0
1927     /* should we activate the screen saver? */
1928     if ((saver_mode == CONS_LKM_SAVER) && (sc->flags & SC_SCRN_IDLE))
1929         if (!ISGRAPHSC(scp) || (sc->flags & SC_SCRN_BLANKED))
1930             (*current_saver)(sc, TRUE);
1931 #endif /* NSPLASH */
1932
1933     syscons_unlock();
1934     if (again)
1935         callout_reset(&sc->scrn_timer_ch, hz / 25, scrn_timer, sc);
1936 }
1937
1938 static int
1939 and_region(int *s1, int *e1, int s2, int e2)
1940 {
1941     if (*e1 < s2 || e2 < *s1)
1942         return FALSE;
1943     *s1 = imax(*s1, s2);
1944     *e1 = imin(*e1, e2);
1945     return TRUE;
1946 }
1947
1948 static void 
1949 scrn_update(scr_stat *scp, int show_cursor)
1950 {
1951     int start;
1952     int end;
1953     int s;
1954     int e;
1955
1956     /* assert(scp == scp->sc->cur_scp) */
1957
1958     ++scp->sc->videoio_in_progress;
1959
1960 #ifndef SC_NO_CUTPASTE
1961     /* remove the previous mouse pointer image if necessary */
1962     if (scp->status & MOUSE_VISIBLE) {
1963         s = scp->mouse_pos;
1964         e = scp->mouse_pos + scp->xsize + 1;
1965         if ((scp->status & (MOUSE_MOVED | MOUSE_HIDDEN))
1966             || and_region(&s, &e, scp->start, scp->end)
1967             || ((scp->status & CURSOR_ENABLED) && 
1968                 (scp->cursor_pos != scp->cursor_oldpos) &&
1969                 (and_region(&s, &e, scp->cursor_pos, scp->cursor_pos)
1970                  || and_region(&s, &e, scp->cursor_oldpos, scp->cursor_oldpos)))) {
1971             sc_remove_mouse_image(scp);
1972             if (scp->end >= scp->xsize*scp->ysize)
1973                 scp->end = scp->xsize*scp->ysize - 1;
1974         }
1975     }
1976 #endif /* !SC_NO_CUTPASTE */
1977
1978 #if 1
1979     /* debug: XXX */
1980     if (scp->end >= scp->xsize*scp->ysize) {
1981         kprintf("scrn_update(): scp->end %d > size_of_screen!!\n", scp->end);
1982         scp->end = scp->xsize*scp->ysize - 1;
1983     }
1984     if (scp->start < 0) {
1985         kprintf("scrn_update(): scp->start %d < 0\n", scp->start);
1986         scp->start = 0;
1987     }
1988 #endif
1989
1990     /* update screen image */
1991     if (scp->start <= scp->end)  {
1992         if (scp->mouse_cut_end >= 0) {
1993             /* there is a marked region for cut & paste */
1994             if (scp->mouse_cut_start <= scp->mouse_cut_end) {
1995                 start = scp->mouse_cut_start;
1996                 end = scp->mouse_cut_end;
1997             } else {
1998                 start = scp->mouse_cut_end;
1999                 end = scp->mouse_cut_start - 1;
2000             }
2001             s = start;
2002             e = end;
2003             /* does the cut-mark region overlap with the update region? */
2004             if (and_region(&s, &e, scp->start, scp->end)) {
2005                 (*scp->rndr->draw)(scp, s, e - s + 1, TRUE);
2006                 s = 0;
2007                 e = start - 1;
2008                 if (and_region(&s, &e, scp->start, scp->end))
2009                     (*scp->rndr->draw)(scp, s, e - s + 1, FALSE);
2010                 s = end + 1;
2011                 e = scp->xsize*scp->ysize - 1;
2012                 if (and_region(&s, &e, scp->start, scp->end))
2013                     (*scp->rndr->draw)(scp, s, e - s + 1, FALSE);
2014             } else {
2015                 (*scp->rndr->draw)(scp, scp->start,
2016                                    scp->end - scp->start + 1, FALSE);
2017             }
2018         } else {
2019             (*scp->rndr->draw)(scp, scp->start,
2020                                scp->end - scp->start + 1, FALSE);
2021         }
2022     }
2023
2024     /* we are not to show the cursor and the mouse pointer... */
2025     if (!show_cursor) {
2026         scp->end = 0;
2027         scp->start = scp->xsize*scp->ysize - 1;
2028         --scp->sc->videoio_in_progress;
2029         return;
2030     }
2031
2032     /* update cursor image */
2033     if (scp->status & CURSOR_ENABLED) {
2034         s = scp->start;
2035         e = scp->end;
2036         /* did cursor move since last time ? */
2037         if (scp->cursor_pos != scp->cursor_oldpos) {
2038             /* do we need to remove old cursor image ? */
2039             if (!and_region(&s, &e, scp->cursor_oldpos, scp->cursor_oldpos))
2040                 sc_remove_cursor_image(scp);
2041             sc_draw_cursor_image(scp);
2042         } else {
2043             if (and_region(&s, &e, scp->cursor_pos, scp->cursor_pos))
2044                 /* cursor didn't move, but has been overwritten */
2045                 sc_draw_cursor_image(scp);
2046             else if (scp->sc->flags & SC_BLINK_CURSOR)
2047                 /* if it's a blinking cursor, update it */
2048                 (*scp->rndr->blink_cursor)(scp, scp->cursor_pos,
2049                                            sc_inside_cutmark(scp,
2050                                                scp->cursor_pos));
2051         }
2052     }
2053
2054 #ifndef SC_NO_CUTPASTE
2055     /* update "pseudo" mouse pointer image */
2056     if (scp->sc->flags & SC_MOUSE_ENABLED) {
2057         if (!(scp->status & (MOUSE_VISIBLE | MOUSE_HIDDEN))) {
2058             scp->status &= ~MOUSE_MOVED;
2059             sc_draw_mouse_image(scp);
2060         }
2061     }
2062 #endif /* SC_NO_CUTPASTE */
2063
2064     scp->end = 0;
2065     scp->start = scp->xsize*scp->ysize - 1;
2066
2067     --scp->sc->videoio_in_progress;
2068 }
2069
2070 #if NSPLASH > 0
2071 static int
2072 scsplash_callback(int event, void *arg)
2073 {
2074     sc_softc_t *sc;
2075     int error;
2076
2077     sc = (sc_softc_t *)arg;
2078
2079     switch (event) {
2080     case SPLASH_INIT:
2081         if (add_scrn_saver(scsplash_saver) == 0) {
2082             sc->flags &= ~SC_SAVER_FAILED;
2083             run_scrn_saver = TRUE;
2084             if (cold && !(boothowto & (RB_VERBOSE | RB_CONFIG))) {
2085                 scsplash_stick(TRUE);
2086                 (*current_saver)(sc, TRUE);
2087             }
2088         }
2089         return 0;
2090
2091     case SPLASH_TERM:
2092         if (current_saver == scsplash_saver) {
2093             scsplash_stick(FALSE);
2094             error = remove_scrn_saver(scsplash_saver);
2095             if (error) {
2096                 return error;
2097             }
2098         }
2099         return 0;
2100
2101     default:
2102         return EINVAL;
2103     }
2104 }
2105
2106 static void
2107 scsplash_saver(sc_softc_t *sc, int show)
2108 {
2109     static int busy = FALSE;
2110     scr_stat *scp;
2111
2112     if (busy)
2113         return;
2114     busy = TRUE;
2115
2116     scp = sc->cur_scp;
2117     if (show) {
2118         if (!(sc->flags & SC_SAVER_FAILED)) {
2119             if (!(sc->flags & SC_SCRN_BLANKED))
2120                 set_scrn_saver_mode(scp, -1, NULL, 0);
2121             switch (splash(sc->adp, TRUE)) {
2122             case 0:             /* succeeded */
2123                 break;
2124             case EAGAIN:        /* try later */
2125                 restore_scrn_saver_mode(scp, FALSE);
2126                 sc_touch_scrn_saver();          /* XXX */
2127                 break;
2128             default:
2129                 sc->flags |= SC_SAVER_FAILED;
2130                 scsplash_stick(FALSE);
2131                 restore_scrn_saver_mode(scp, TRUE);
2132                 kprintf("scsplash_saver(): failed to put up the image\n");
2133                 break;
2134             }
2135         }
2136     } else if (!sticky_splash) {
2137         if ((sc->flags & SC_SCRN_BLANKED) && (splash(sc->adp, FALSE) == 0))
2138             restore_scrn_saver_mode(scp, TRUE);
2139     }
2140     busy = FALSE;
2141 }
2142
2143 static int
2144 add_scrn_saver(void (*this_saver)(sc_softc_t *, int))
2145 {
2146 #if 0
2147     int error;
2148
2149     if (current_saver != none_saver) {
2150         error = remove_scrn_saver(current_saver);
2151         if (error)
2152             return error;
2153     }
2154 #endif
2155     if (current_saver != none_saver) {
2156         return EBUSY;
2157     }
2158
2159     run_scrn_saver = FALSE;
2160     saver_mode = CONS_LKM_SAVER;
2161     current_saver = this_saver;
2162     return 0;
2163 }
2164
2165 static int
2166 remove_scrn_saver(void (*this_saver)(sc_softc_t *, int))
2167 {
2168     if (current_saver != this_saver)
2169         return EINVAL;
2170
2171 #if 0
2172     /*
2173      * In order to prevent `current_saver' from being called by
2174      * the timeout routine `scrn_timer()' while we manipulate 
2175      * the saver list, we shall set `current_saver' to `none_saver' 
2176      * before stopping the current saver, rather than blocking by `splXX()'.
2177      */
2178     current_saver = none_saver;
2179     if (scrn_blanked)
2180         stop_scrn_saver(this_saver);
2181 #endif
2182     /* unblank all blanked screens */
2183     wait_scrn_saver_stop(NULL);
2184     if (scrn_blanked) {
2185         return EBUSY;
2186     }
2187
2188     current_saver = none_saver;
2189     return 0;
2190 }
2191
2192 static int
2193 set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border)
2194 {
2195
2196     /* assert(scp == scp->sc->cur_scp) */
2197     crit_enter();
2198     if (!ISGRAPHSC(scp))
2199         sc_remove_cursor_image(scp);
2200     scp->splash_save_mode = scp->mode;
2201     scp->splash_save_status = scp->status & (GRAPHICS_MODE | PIXEL_MODE);
2202     scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE);
2203     scp->status |= (UNKNOWN_MODE | SAVER_RUNNING);
2204     scp->sc->flags |= SC_SCRN_BLANKED;
2205     ++scrn_blanked;
2206     crit_exit();
2207     if (mode < 0) {
2208         return 0;
2209     }
2210     scp->mode = mode;
2211     if (set_mode(scp) == 0) {
2212         if (scp->sc->adp->va_info.vi_flags & V_INFO_GRAPHICS)
2213             scp->status |= GRAPHICS_MODE;
2214 #ifndef SC_NO_PALETTE_LOADING
2215         if (pal != NULL)
2216             load_palette(scp->sc->adp, pal);
2217 #endif
2218         sc_set_border(scp, border);
2219         return 0;
2220     } else {
2221         crit_enter();
2222         scp->mode = scp->splash_save_mode;
2223         scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING);
2224         scp->status |= scp->splash_save_status;
2225         crit_exit();
2226         return 1;
2227     }
2228     /* NOTREACHED */
2229 }
2230
2231 static int
2232 restore_scrn_saver_mode(scr_stat *scp, int changemode)
2233 {
2234     int mode;
2235     int status;
2236
2237     /* assert(scp == scp->sc->cur_scp) */
2238     crit_enter();
2239     mode = scp->mode;
2240     status = scp->status;
2241     scp->mode = scp->splash_save_mode;
2242     scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING);
2243     scp->status |= scp->splash_save_status;
2244     scp->sc->flags &= ~SC_SCRN_BLANKED;
2245     if (!changemode) {
2246         if (!ISGRAPHSC(scp))
2247             sc_draw_cursor_image(scp);
2248         --scrn_blanked;
2249         crit_exit();
2250         return 0;
2251     }
2252     if (set_mode(scp) == 0) {
2253 #ifndef SC_NO_PALETTE_LOADING
2254         load_palette(scp->sc->adp, scp->sc->palette);
2255 #endif
2256         --scrn_blanked;
2257         crit_exit();
2258         return 0;
2259     } else {
2260         scp->mode = mode;
2261         scp->status = status;
2262         crit_exit();
2263         return 1;
2264     }
2265     /* NOTREACHED */
2266 }
2267
2268 static void
2269 stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int))
2270 {
2271     (*saver)(sc, FALSE);
2272     run_scrn_saver = FALSE;
2273     /* the screen saver may have chosen not to stop after all... */
2274     if (sc->flags & SC_SCRN_BLANKED) {
2275         return;
2276     }
2277
2278     mark_all(sc->cur_scp);
2279     if (sc->delayed_next_scr)
2280         sc_switch_scr(sc, sc->delayed_next_scr - 1);
2281     wakeup((caddr_t)&scrn_blanked);
2282 }
2283
2284 static int
2285 wait_scrn_saver_stop(sc_softc_t *sc)
2286 {
2287     int error = 0;
2288
2289     while (scrn_blanked > 0) {
2290         run_scrn_saver = FALSE;
2291         if (sc && !(sc->flags & SC_SCRN_BLANKED)) {
2292             error = 0;
2293             break;
2294         }
2295         error = tsleep((caddr_t)&scrn_blanked, PCATCH, "scrsav", 0);
2296         /* May return ERESTART */
2297         if (error)
2298                 break;
2299     }
2300     run_scrn_saver = FALSE;
2301     return error;
2302 }
2303 #endif /* NSPLASH */
2304
2305 void
2306 sc_touch_scrn_saver(void)
2307 {
2308     scsplash_stick(FALSE);
2309     run_scrn_saver = FALSE;
2310 }
2311
2312 int
2313 sc_switch_scr(sc_softc_t *sc, u_int next_scr)
2314 {
2315     scr_stat *cur_scp;
2316     struct tty *tp;
2317
2318     DPRINTF(5, ("sc0: sc_switch_scr() %d ", next_scr + 1));
2319
2320     /* prevent switch if previously requested */
2321     if (sc->flags & SC_SCRN_VTYLOCK) {
2322             sc_bell(sc->cur_scp, sc->cur_scp->bell_pitch,
2323                 sc->cur_scp->bell_duration);
2324             return EPERM;
2325     }
2326
2327     /* delay switch if the screen is blanked or being updated */
2328     if ((sc->flags & SC_SCRN_BLANKED) || sc->write_in_progress
2329         || sc->blink_in_progress || sc->videoio_in_progress) {
2330         sc->delayed_next_scr = next_scr + 1;
2331         sc_touch_scrn_saver();
2332         DPRINTF(5, ("switch delayed\n"));
2333         return 0;
2334     }
2335
2336     cur_scp = sc->cur_scp;
2337
2338     /*
2339      * we are in the middle of the vty switching process...
2340      *
2341      * This may be in the console path, we can only deal with this case
2342      * if the proc_token is available non-blocking.
2343      */
2344     if (sc->switch_in_progress &&
2345         (cur_scp->smode.mode == VT_PROCESS) &&
2346         cur_scp->proc &&
2347         lwkt_trytoken(&proc_token)) {
2348
2349         if (cur_scp->proc != pfindn(cur_scp->pid)) {
2350             /* 
2351              * The controlling process has died!!.  Do some clean up.
2352              * NOTE:`cur_scp->proc' and `cur_scp->smode.mode' 
2353              * are not reset here yet; they will be cleared later.
2354              */
2355             DPRINTF(5, ("cur_scp controlling process %d died, ",
2356                cur_scp->pid));
2357             if (cur_scp->status & SWITCH_WAIT_REL) {
2358                 /*
2359                  * Force the previous switch to finish, but return now 
2360                  * with error.
2361                  *
2362                  */
2363                 DPRINTF(5, ("reset WAIT_REL, "));
2364                 finish_vt_rel(cur_scp, TRUE);
2365                 DPRINTF(5, ("finishing previous switch\n"));
2366                 lwkt_reltoken(&proc_token);
2367                 return EINVAL;
2368             } else if (cur_scp->status & SWITCH_WAIT_ACQ) {
2369                 /* let's assume screen switch has been completed. */
2370                 DPRINTF(5, ("reset WAIT_ACQ, "));
2371                 finish_vt_acq(cur_scp);
2372             } else {
2373                 /* 
2374                  * We are in between screen release and acquisition, and
2375                  * reached here via scgetc() or scrn_timer() which has 
2376                  * interrupted exchange_scr(). Don't do anything stupid.
2377                  */
2378                 DPRINTF(5, ("waiting nothing, "));
2379             }
2380         } else {
2381             /*
2382              * The controlling process is alive, but not responding... 
2383              * It is either buggy or it may be just taking time.
2384              * The following code is a gross kludge to cope with this
2385              * problem for which there is no clean solution. XXX
2386              */
2387             if (cur_scp->status & SWITCH_WAIT_REL) {
2388                 switch (sc->switch_in_progress++) {
2389                 case 1:
2390                     break;
2391                 case 2:
2392                     DPRINTF(5, ("sending relsig again, "));
2393                     signal_vt_rel(cur_scp);
2394                     break;
2395                 case 3:
2396                     break;
2397                 case 4:
2398                 default:
2399                     /*
2400                      * Act as if the controlling program returned
2401                      * VT_FALSE.
2402                      *
2403                      */
2404                     DPRINTF(5, ("force reset WAIT_REL, "));
2405                     finish_vt_rel(cur_scp, FALSE);
2406                     DPRINTF(5, ("act as if VT_FALSE was seen\n"));
2407                     lwkt_reltoken(&proc_token);
2408                     return EINVAL;
2409                 }
2410             } else if (cur_scp->status & SWITCH_WAIT_ACQ) {
2411                 switch (sc->switch_in_progress++) {
2412                 case 1:
2413                     break;
2414                 case 2:
2415                     DPRINTF(5, ("sending acqsig again, "));
2416                     signal_vt_acq(cur_scp);
2417                     break;
2418                 case 3:
2419                     break;
2420                 case 4:
2421                 default:
2422                      /* clear the flag and finish the previous switch */
2423                     DPRINTF(5, ("force reset WAIT_ACQ, "));
2424                     finish_vt_acq(cur_scp);
2425                     break;
2426                 }
2427             }
2428         }
2429         lwkt_reltoken(&proc_token);
2430     }
2431
2432     /*
2433      * Return error if an invalid argument is given, or vty switch
2434      * is still in progress.
2435      */
2436     if ((next_scr < sc->first_vty) || (next_scr >= sc->first_vty + sc->vtys)
2437         || sc->switch_in_progress) {
2438         sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
2439         DPRINTF(5, ("error 1\n"));
2440         return EINVAL;
2441     }
2442
2443     /*
2444      * Don't allow switching away from the graphics mode vty
2445      * if the switch mode is VT_AUTO, unless the next vty is the same 
2446      * as the current or the current vty has been closed (but showing).
2447      */
2448     tp = VIRTUAL_TTY(sc, cur_scp->index);
2449     if ((cur_scp->index != next_scr)
2450         && ISTTYOPEN(tp)
2451         && (cur_scp->smode.mode == VT_AUTO)
2452         && ISGRAPHSC(cur_scp)) {
2453         sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
2454         DPRINTF(5, ("error, graphics mode\n"));
2455         return EINVAL;
2456     }
2457
2458     /*
2459      * Is the wanted vty open? Don't allow switching to a closed vty.
2460      * If we are in DDB, don't switch to a vty in the VT_PROCESS mode.
2461      * Note that we always allow the user to switch to the kernel 
2462      * console even if it is closed.
2463      */
2464     if ((sc_console == NULL) || (next_scr != sc_console->index)) {
2465         tp = VIRTUAL_TTY(sc, next_scr);
2466         if (!ISTTYOPEN(tp)) {
2467             sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
2468             DPRINTF(5, ("error 2, requested vty isn't open!\n"));
2469             return EINVAL;
2470         }
2471         if ((debugger > 0) && (SC_STAT(tp->t_dev)->smode.mode == VT_PROCESS)) {
2472             DPRINTF(5, ("error 3, requested vty is in the VT_PROCESS mode\n"));
2473             return EINVAL;
2474         }
2475     }
2476
2477     /* this is the start of vty switching process... */
2478     ++sc->switch_in_progress;
2479     sc->delayed_next_scr = 0;
2480     sc->old_scp = cur_scp;
2481     sc->new_scp = SC_STAT(SC_DEV(sc, next_scr));
2482     if (sc->new_scp == sc->old_scp) {
2483         sc->switch_in_progress = 0;
2484         wakeup((caddr_t)&sc->new_scp->smode);
2485         DPRINTF(5, ("switch done (new == old)\n"));
2486         return 0;
2487     }
2488
2489     /* has controlling process died? */
2490     vt_proc_alive(sc->old_scp);
2491     vt_proc_alive(sc->new_scp);
2492
2493     /* wait for the controlling process to release the screen, if necessary */
2494     if (signal_vt_rel(sc->old_scp)) {
2495         return 0;
2496     }
2497
2498     /* go set up the new vty screen */
2499     exchange_scr(sc);
2500
2501     /* wake up processes waiting for this vty */
2502     wakeup((caddr_t)&sc->cur_scp->smode);
2503
2504     /* wait for the controlling process to acknowledge, if necessary */
2505     if (signal_vt_acq(sc->cur_scp)) {
2506         return 0;
2507     }
2508
2509     sc->switch_in_progress = 0;
2510     if (sc->unit == sc_console_unit)
2511         cons_unavail = FALSE;
2512     DPRINTF(5, ("switch done\n"));
2513
2514     return 0;
2515 }
2516
2517 static void
2518 do_switch_scr(sc_softc_t *sc)
2519 {
2520     lwkt_gettoken(&tty_token);
2521     vt_proc_alive(sc->new_scp);
2522
2523     exchange_scr(sc);
2524     /* sc->cur_scp == sc->new_scp */
2525     wakeup((caddr_t)&sc->cur_scp->smode);
2526
2527     /* wait for the controlling process to acknowledge, if necessary */
2528     if (!signal_vt_acq(sc->cur_scp)) {
2529         sc->switch_in_progress = 0;
2530         if (sc->unit == sc_console_unit)
2531             cons_unavail = FALSE;
2532     }
2533     lwkt_reltoken(&tty_token);
2534 }
2535
2536 static int
2537 vt_proc_alive(scr_stat *scp)
2538 {
2539     lwkt_gettoken(&tty_token);
2540     lwkt_gettoken(&proc_token);
2541     if (scp->proc) {
2542         if (scp->proc == pfindn(scp->pid)) {
2543             lwkt_reltoken(&proc_token);
2544             lwkt_reltoken(&tty_token);
2545             return TRUE;
2546         }
2547         scp->proc = NULL;
2548         scp->smode.mode = VT_AUTO;
2549         DPRINTF(5, ("vt controlling process %d died\n", scp->pid));
2550     }
2551     lwkt_reltoken(&proc_token);
2552     lwkt_reltoken(&tty_token);
2553     return FALSE;
2554 }
2555
2556 static int
2557 signal_vt_rel(scr_stat *scp)
2558 {
2559     lwkt_gettoken(&tty_token);
2560     if (scp->smode.mode != VT_PROCESS) {
2561         lwkt_reltoken(&tty_token);
2562         return FALSE;
2563     }
2564     scp->status |= SWITCH_WAIT_REL;
2565     lwkt_gettoken(&proc_token);
2566     ksignal(scp->proc, scp->smode.relsig);
2567     lwkt_reltoken(&proc_token);
2568     DPRINTF(5, ("sending relsig to %d\n", scp->pid));
2569     lwkt_reltoken(&tty_token);
2570     return TRUE;
2571 }
2572
2573 static int
2574 signal_vt_acq(scr_stat *scp)
2575 {
2576     lwkt_gettoken(&tty_token);
2577     if (scp->smode.mode != VT_PROCESS) {
2578         lwkt_reltoken(&tty_token);
2579         return FALSE;
2580     }
2581     if (scp->sc->unit == sc_console_unit)
2582         cons_unavail = TRUE;
2583     scp->status |= SWITCH_WAIT_ACQ;
2584     lwkt_gettoken(&proc_token);
2585     ksignal(scp->proc, scp->smode.acqsig);
2586     lwkt_reltoken(&proc_token);
2587     DPRINTF(5, ("sending acqsig to %d\n", scp->pid));
2588     lwkt_reltoken(&tty_token);
2589     return TRUE;
2590 }
2591
2592 static int
2593 finish_vt_rel(scr_stat *scp, int release)
2594 {
2595     lwkt_gettoken(&tty_token);
2596     if (scp == scp->sc->old_scp && scp->status & SWITCH_WAIT_REL) {
2597         scp->status &= ~SWITCH_WAIT_REL;
2598         if (release)
2599             do_switch_scr(scp->sc);
2600         else
2601             scp->sc->switch_in_progress = 0;
2602         lwkt_reltoken(&tty_token);
2603         return 0;
2604     }
2605     lwkt_reltoken(&tty_token);
2606     return EINVAL;
2607 }
2608
2609 static int
2610 finish_vt_acq(scr_stat *scp)
2611 {
2612     lwkt_gettoken(&tty_token);
2613     if (scp == scp->sc->new_scp && scp->status & SWITCH_WAIT_ACQ) {
2614         scp->status &= ~SWITCH_WAIT_ACQ;
2615         scp->sc->switch_in_progress = 0;
2616         lwkt_reltoken(&tty_token);
2617         return 0;
2618     }
2619     lwkt_reltoken(&tty_token);
2620     return EINVAL;
2621 }
2622
2623 static void
2624 exchange_scr(sc_softc_t *sc)
2625 {
2626     scr_stat *scp;
2627
2628     lwkt_gettoken(&tty_token);
2629     /* save the current state of video and keyboard */
2630     sc_move_cursor(sc->old_scp, sc->old_scp->xpos, sc->old_scp->ypos);
2631     if (!ISGRAPHSC(sc->old_scp))
2632         sc_remove_cursor_image(sc->old_scp);
2633     if (sc->old_scp->kbd_mode == K_XLATE)
2634         save_kbd_state(sc->old_scp, TRUE);
2635
2636     /* set up the video for the new screen */
2637     scp = sc->cur_scp = sc->new_scp;
2638     if (sc->old_scp->mode != scp->mode || ISUNKNOWNSC(sc->old_scp))
2639         set_mode(scp);
2640     else
2641         sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
2642                     (void *)sc->adp->va_window, FALSE);
2643     scp->status |= MOUSE_HIDDEN;
2644     sc_move_cursor(scp, scp->xpos, scp->ypos);
2645     if (!ISGRAPHSC(scp))
2646         sc_set_cursor_image(scp);
2647 #ifndef SC_NO_PALETTE_LOADING
2648     if (ISGRAPHSC(sc->old_scp))
2649         load_palette(sc->adp, sc->palette);
2650 #endif
2651     sc_set_border(scp, scp->border);
2652
2653     /* set up the keyboard for the new screen */
2654     if (sc->old_scp->kbd_mode != scp->kbd_mode)
2655         kbd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
2656     update_kbd_state(scp, scp->status, LOCK_MASK, TRUE);
2657
2658     mark_all(scp);
2659     lwkt_reltoken(&tty_token);
2660 }
2661
2662 static void
2663 sc_puts(scr_stat *scp, u_char *buf, int len)
2664 {
2665 #if NSPLASH > 0
2666     /* make screensaver happy */
2667     if (!sticky_splash && scp == scp->sc->cur_scp)
2668         run_scrn_saver = FALSE;
2669 #endif
2670
2671     if (scp->tsw)
2672         (*scp->tsw->te_puts)(scp, buf, len);
2673
2674     if (scp->sc->delayed_next_scr)
2675         sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
2676
2677 }
2678
2679 void
2680 sc_draw_cursor_image(scr_stat *scp)
2681 {
2682     /* assert(scp == scp->sc->cur_scp); */
2683     ++scp->sc->videoio_in_progress;
2684     (*scp->rndr->draw_cursor)(scp, scp->cursor_pos,
2685                               scp->sc->flags & SC_BLINK_CURSOR, TRUE,
2686                               sc_inside_cutmark(scp, scp->cursor_pos));
2687     scp->cursor_oldpos = scp->cursor_pos;
2688     --scp->sc->videoio_in_progress;
2689 }
2690
2691 void
2692 sc_remove_cursor_image(scr_stat *scp)
2693 {
2694     /* assert(scp == scp->sc->cur_scp); */
2695     ++scp->sc->videoio_in_progress;
2696     (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos,
2697                               scp->sc->flags & SC_BLINK_CURSOR, FALSE,
2698                               sc_inside_cutmark(scp, scp->cursor_oldpos));
2699     --scp->sc->videoio_in_progress;
2700 }
2701
2702 static void
2703 update_cursor_image(scr_stat *scp)
2704 {
2705     int blink;
2706
2707     if (scp->sc->flags & SC_CHAR_CURSOR) {
2708         scp->cursor_base = imax(0, scp->sc->cursor_base);
2709         scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
2710     } else {
2711         scp->cursor_base = 0;
2712         scp->cursor_height = scp->font_size;
2713     }
2714     blink = scp->sc->flags & SC_BLINK_CURSOR;
2715
2716     /* assert(scp == scp->sc->cur_scp); */
2717     ++scp->sc->videoio_in_progress;
2718     (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos, blink, FALSE, 
2719                               sc_inside_cutmark(scp, scp->cursor_pos));
2720     (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height, blink);
2721     (*scp->rndr->draw_cursor)(scp, scp->cursor_pos, blink, TRUE, 
2722                               sc_inside_cutmark(scp, scp->cursor_pos));
2723     --scp->sc->videoio_in_progress;
2724 }
2725
2726 void
2727 sc_set_cursor_image(scr_stat *scp)
2728 {
2729     if (scp->sc->flags & SC_CHAR_CURSOR) {
2730         scp->cursor_base = imax(0, scp->sc->cursor_base);
2731         scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
2732     } else {
2733         scp->cursor_base = 0;
2734         scp->cursor_height = scp->font_size;
2735     }
2736
2737     /* assert(scp == scp->sc->cur_scp); */
2738     ++scp->sc->videoio_in_progress;
2739     (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height,
2740                              scp->sc->flags & SC_BLINK_CURSOR);
2741     --scp->sc->videoio_in_progress;
2742 }
2743
2744 static void
2745 scinit(int unit, int flags)
2746 {
2747     /*
2748      * When syscons is being initialized as the kernel console, malloc()
2749      * is not yet functional, because various kernel structures has not been
2750      * fully initialized yet.  Therefore, we need to declare the following
2751      * static buffers for the console.  This is less than ideal, 
2752      * but is necessry evil for the time being.  XXX
2753      */
2754     static scr_stat main_console;
2755     static u_short sc_buffer[ROW*COL];  /* XXX */
2756 #ifndef SC_NO_FONT_LOADING
2757     static u_char font_8[256*8];
2758     static u_char font_14[256*14];
2759     static u_char font_16[256*16];
2760 #endif
2761
2762     sc_softc_t *sc;
2763     scr_stat *scp;
2764     video_adapter_t *adp;
2765     int col;
2766     int row;
2767     int i;
2768
2769     /* one time initialization */
2770     if (init_done == COLD)
2771         sc_get_bios_values(&bios_value);
2772     init_done = WARM;
2773
2774     /*
2775      * Allocate resources.  Even if we are being called for the second
2776      * time, we must allocate them again, because they might have 
2777      * disappeared...
2778      */
2779     sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
2780     adp = NULL;
2781     if (sc->adapter >= 0) {
2782         vid_release(sc->adp, (void *)&sc->adapter);
2783         adp = sc->adp;
2784         sc->adp = NULL;
2785     }
2786     if (sc->keyboard >= 0) {
2787         DPRINTF(5, ("sc%d: releasing kbd%d\n", unit, sc->keyboard));
2788         i = kbd_release(sc->kbd, (void *)&sc->keyboard);
2789         DPRINTF(5, ("sc%d: kbd_release returned %d\n", unit, i));
2790         if (sc->kbd != NULL) {
2791             DPRINTF(5, ("sc%d: kbd != NULL!, index:%d, unit:%d, flags:0x%x\n",
2792                 unit, sc->kbd->kb_index, sc->kbd->kb_unit, sc->kbd->kb_flags));
2793         }
2794         sc->kbd = NULL;
2795     }
2796     sc->adapter = vid_allocate("*", unit, (void *)&sc->adapter);
2797     sc->adp = vid_get_adapter(sc->adapter);
2798     /* assert((sc->adapter >= 0) && (sc->adp != NULL)) */
2799     sc->keyboard = sc_allocate_keyboard(sc, unit);
2800     DPRINTF(1, ("sc%d: keyboard %d\n", unit, sc->keyboard));
2801     sc->kbd = kbd_get_keyboard(sc->keyboard);
2802     if (sc->kbd != NULL) {
2803         DPRINTF(1, ("sc%d: kbd index:%d, unit:%d, flags:0x%x\n",
2804                 unit, sc->kbd->kb_index, sc->kbd->kb_unit, sc->kbd->kb_flags));
2805     }
2806
2807     if (!(sc->flags & SC_INIT_DONE) || (adp != sc->adp)) {
2808
2809         sc->initial_mode = sc->adp->va_initial_mode;
2810
2811 #ifndef SC_NO_FONT_LOADING
2812         if (flags & SC_KERNEL_CONSOLE) {
2813             sc->font_8 = font_8;
2814             sc->font_14 = font_14;
2815             sc->font_16 = font_16;
2816         } else if (sc->font_8 == NULL) {
2817             /* assert(sc_malloc) */
2818             sc->font_8 = kmalloc(sizeof(font_8), M_SYSCONS, M_WAITOK);
2819             sc->font_14 = kmalloc(sizeof(font_14), M_SYSCONS, M_WAITOK);
2820             sc->font_16 = kmalloc(sizeof(font_16), M_SYSCONS, M_WAITOK);
2821         }
2822 #endif
2823
2824         lwkt_gettoken(&tty_token);
2825         /* extract the hardware cursor location and hide the cursor for now */
2826         (*vidsw[sc->adapter]->read_hw_cursor)(sc->adp, &col, &row);
2827         (*vidsw[sc->adapter]->set_hw_cursor)(sc->adp, -1, -1);
2828         lwkt_reltoken(&tty_token);
2829
2830         /* set up the first console */
2831         sc->first_vty = unit*MAXCONS;
2832         sc->vtys = MAXCONS;             /* XXX: should be configurable */
2833         if (flags & SC_KERNEL_CONSOLE) {
2834             scp = &main_console;
2835             sc->console_scp = scp;
2836             init_scp(sc, sc->first_vty, scp);
2837             sc_vtb_init(&scp->vtb, VTB_MEMORY, scp->xsize, scp->ysize,
2838                         (void *)sc_buffer, FALSE);
2839             if (sc_init_emulator(scp, SC_DFLT_TERM))
2840                 sc_init_emulator(scp, "*");
2841             (*scp->tsw->te_default_attr)(scp,
2842                                          kernel_default.std_color,
2843                                          kernel_default.rev_color);
2844         } else {
2845             /* assert(sc_malloc) */
2846             sc->dev = kmalloc(sizeof(cdev_t)*sc->vtys, M_SYSCONS, M_WAITOK | M_ZERO);
2847
2848             sc->dev[0] = make_dev(&sc_ops, unit*MAXCONS, UID_ROOT, 
2849                                 GID_WHEEL, 0600, "ttyv%r", unit*MAXCONS);
2850
2851             sc->dev[0]->si_tty = ttymalloc(sc->dev[0]->si_tty);
2852             scp = alloc_scp(sc, sc->first_vty);
2853             sc->dev[0]->si_drv1 = scp;
2854         }
2855         sc->cur_scp = scp;
2856
2857         /* copy screen to temporary buffer */
2858         sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
2859                     (void *)scp->sc->adp->va_window, FALSE);
2860         if (ISTEXTSC(scp))
2861             sc_vtb_copy(&scp->scr, 0, &scp->vtb, 0, scp->xsize*scp->ysize);
2862
2863         /* move cursors to the initial positions */
2864         if (col >= scp->xsize)
2865             col = 0;
2866         if (row >= scp->ysize)
2867             row = scp->ysize - 1;
2868         scp->xpos = col;
2869         scp->ypos = row;
2870         scp->cursor_pos = scp->cursor_oldpos = row*scp->xsize + col;
2871         if (bios_value.cursor_end < scp->font_size)
2872             sc->cursor_base = scp->font_size - bios_value.cursor_end - 1;
2873         else
2874             sc->cursor_base = 0;
2875         i = bios_value.cursor_end - bios_value.cursor_start + 1;
2876         sc->cursor_height = imin(i, scp->font_size);
2877 #ifndef SC_NO_SYSMOUSE
2878         sc_mouse_move(scp, scp->xpixel/2, scp->ypixel/2);
2879 #endif
2880         if (!ISGRAPHSC(scp)) {
2881             sc_set_cursor_image(scp);
2882             sc_draw_cursor_image(scp);
2883         }
2884
2885         /* save font and palette */
2886 #ifndef SC_NO_FONT_LOADING
2887         sc->fonts_loaded = 0;
2888         if (ISFONTAVAIL(sc->adp->va_flags)) {
2889 #ifdef SC_DFLT_FONT
2890             bcopy(dflt_font_8, sc->font_8, sizeof(dflt_font_8));
2891             bcopy(dflt_font_14, sc->font_14, sizeof(dflt_font_14));
2892             bcopy(dflt_font_16, sc->font_16, sizeof(dflt_font_16));
2893             sc->fonts_loaded = FONT_16 | FONT_14 | FONT_8;
2894             if (scp->font_size < 14) {
2895                 sc_load_font(scp, 0, 8, sc->font_8, 0, 256);
2896             } else if (scp->font_size >= 16) {
2897                 sc_load_font(scp, 0, 16, sc->font_16, 0, 256);
2898             } else {
2899                 sc_load_font(scp, 0, 14, sc->font_14, 0, 256);
2900             }
2901 #else /* !SC_DFLT_FONT */
2902             if (scp->font_size < 14) {
2903                 sc_save_font(scp, 0, 8, sc->font_8, 0, 256);
2904                 sc->fonts_loaded = FONT_8;
2905             } else if (scp->font_size >= 16) {
2906                 sc_save_font(scp, 0, 16, sc->font_16, 0, 256);
2907                 sc->fonts_loaded = FONT_16;
2908             } else {
2909                 sc_save_font(scp, 0, 14, sc->font_14, 0, 256);
2910                 sc->fonts_loaded = FONT_14;
2911             }
2912 #endif /* SC_DFLT_FONT */
2913             /* FONT KLUDGE: always use the font page #0. XXX */
2914             sc_show_font(scp, 0);
2915         }
2916 #endif /* !SC_NO_FONT_LOADING */
2917
2918 #ifndef SC_NO_PALETTE_LOADING
2919         save_palette(sc->adp, sc->palette);
2920 #endif
2921
2922 #if NSPLASH > 0
2923         if (!(sc->flags & SC_SPLASH_SCRN) && (flags & SC_KERNEL_CONSOLE)) {
2924             /* we are ready to put up the splash image! */
2925             splash_init(sc->adp, scsplash_callback, sc);
2926             sc->flags |= SC_SPLASH_SCRN;
2927         }
2928 #endif /* NSPLASH */
2929     }
2930
2931     /* the rest is not necessary, if we have done it once */
2932     if (sc->flags & SC_INIT_DONE) {
2933         return;
2934     }
2935
2936     /* initialize mapscrn arrays to a one to one map */
2937     for (i = 0; i < sizeof(sc->scr_map); i++)
2938         sc->scr_map[i] = sc->scr_rmap[i] = i;
2939
2940     sc->flags |= SC_INIT_DONE;
2941 }
2942
2943 static void
2944 scterm(int unit, int flags)
2945 {
2946     sc_softc_t *sc;
2947     scr_stat *scp;
2948
2949     sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
2950     if (sc == NULL)
2951         return;                 /* shouldn't happen */
2952
2953     lwkt_gettoken(&tty_token);
2954 #if NSPLASH > 0
2955     /* this console is no longer available for the splash screen */
2956     if (sc->flags & SC_SPLASH_SCRN) {
2957         splash_term(sc->adp);
2958         sc->flags &= ~SC_SPLASH_SCRN;
2959     }
2960 #endif /* NSPLASH */
2961
2962 #if 0 /* XXX */
2963     /* move the hardware cursor to the upper-left corner */
2964     (*vidsw[sc->adapter]->set_hw_cursor)(sc->adp, 0, 0);
2965 #endif
2966
2967     /* release the keyboard and the video card */
2968     if (sc->keyboard >= 0)
2969         kbd_release(sc->kbd, &sc->keyboard);
2970     if (sc->adapter >= 0)
2971         vid_release(sc->adp, &sc->adapter);
2972
2973     /* 
2974      * Stop the terminal emulator, if any.  If operating on the
2975      * kernel console sc->dev may not be setup yet.
2976      */
2977     if (flags & SC_KERNEL_CONSOLE)
2978         scp = sc->console_scp;
2979     else
2980         scp = SC_STAT(sc->dev[0]);
2981     if (scp->tsw)
2982         (*scp->tsw->te_term)(scp, &scp->ts);
2983     if (scp->ts != NULL)
2984         kfree(scp->ts, M_SYSCONS);
2985
2986     /* clear the structure */
2987     if (!(flags & SC_KERNEL_CONSOLE)) {
2988         /* XXX: We need delete_dev() for this */
2989         kfree(sc->dev, M_SYSCONS);
2990 #if 0
2991         /* XXX: We need a ttyunregister for this */
2992         kfree(sc->tty, M_SYSCONS);
2993 #endif
2994 #ifndef SC_NO_FONT_LOADING
2995         kfree(sc->font_8, M_SYSCONS);
2996         kfree(sc->font_14, M_SYSCONS);
2997         kfree(sc->font_16, M_SYSCONS);
2998 #endif
2999         /* XXX vtb, history */
3000     }
3001     bzero(sc, sizeof(*sc));
3002     sc->keyboard = -1;
3003     sc->adapter = -1;
3004     lwkt_reltoken(&tty_token);
3005 }
3006
3007 static void
3008 scshutdown(void *arg, int howto)
3009 {
3010     /* assert(sc_console != NULL) */
3011
3012     lwkt_gettoken(&tty_token);
3013     syscons_lock();
3014     sc_touch_scrn_saver();
3015     if (!cold && sc_console
3016         && sc_console->sc->cur_scp->smode.mode == VT_AUTO 
3017         && sc_console->smode.mode == VT_AUTO) {
3018         sc_switch_scr(sc_console->sc, sc_console->index);
3019     }
3020     shutdown_in_progress = TRUE;
3021     syscons_unlock();
3022     lwkt_reltoken(&tty_token);
3023 }
3024
3025 int
3026 sc_clean_up(scr_stat *scp)
3027 {
3028 #if NSPLASH > 0
3029     int error;
3030 #endif /* NSPLASH */
3031
3032     lwkt_gettoken(&tty_token);
3033     if (scp->sc->flags & SC_SCRN_BLANKED) {
3034         sc_touch_scrn_saver();
3035 #if NSPLASH > 0
3036         if ((error = wait_scrn_saver_stop(scp->sc))) {
3037             lwkt_reltoken(&tty_token);
3038             return error;
3039         }
3040 #endif /* NSPLASH */
3041     }
3042     scp->status |= MOUSE_HIDDEN;
3043     sc_remove_mouse_image(scp);
3044     sc_remove_cutmarking(scp);
3045     lwkt_reltoken(&tty_token);
3046     return 0;
3047 }
3048
3049 void
3050 sc_alloc_scr_buffer(scr_stat *scp, int wait, int discard)
3051 {
3052     sc_vtb_t new;
3053     sc_vtb_t old;
3054
3055     lwkt_gettoken(&tty_token);
3056     old = scp->vtb;
3057     sc_vtb_init(&new, VTB_MEMORY, scp->xsize, scp->ysize, NULL, wait);
3058     if (!discard && (old.vtb_flags & VTB_VALID)) {
3059         /* retain the current cursor position and buffer contants */
3060         scp->cursor_oldpos = scp->cursor_pos;
3061         /* 
3062          * This works only if the old buffer has the same size as or larger 
3063          * than the new one. XXX
3064          */
3065         sc_vtb_copy(&old, 0, &new, 0, scp->xsize*scp->ysize);
3066         scp->vtb = new;
3067     } else {
3068         scp->vtb = new;
3069         sc_vtb_destroy(&old);
3070     }
3071
3072 #ifndef SC_NO_SYSMOUSE
3073     /* move the mouse cursor at the center of the screen */
3074     sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
3075 #endif
3076     lwkt_reltoken(&tty_token);
3077 }
3078
3079 static scr_stat *
3080 alloc_scp(sc_softc_t *sc, int vty)
3081 {
3082     scr_stat *scp;
3083
3084     /* assert(sc_malloc) */
3085
3086     scp = kmalloc(sizeof(scr_stat), M_SYSCONS, M_WAITOK);
3087     init_scp(sc, vty, scp);
3088
3089     sc_alloc_scr_buffer(scp, TRUE, TRUE);
3090     if (sc_init_emulator(scp, SC_DFLT_TERM))
3091         sc_init_emulator(scp, "*");
3092
3093 #ifndef SC_NO_CUTPASTE
3094     sc_alloc_cut_buffer(scp, TRUE);
3095 #endif
3096
3097 #ifndef SC_NO_HISTORY
3098     sc_alloc_history_buffer(scp, 0, 0, TRUE);
3099 #endif
3100     return scp;
3101 }
3102
3103 /*
3104  * NOTE: Must be called with tty_token held.
3105  */
3106 static void
3107 init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
3108 {
3109     video_info_t info;
3110
3111     bzero(scp, sizeof(*scp));
3112
3113     scp->index = vty;
3114     scp->sc = sc;
3115     scp->status = 0;
3116     scp->mode = sc->initial_mode;
3117     callout_init_mp(&scp->blink_screen_ch);
3118     lwkt_gettoken(&tty_token);
3119     (*vidsw[sc->adapter]->get_info)(sc->adp, scp->mode, &info);
3120     lwkt_reltoken(&tty_token);
3121     if (info.vi_flags & V_INFO_GRAPHICS) {
3122         scp->status |= GRAPHICS_MODE;
3123         scp->xpixel = info.vi_width;
3124         scp->ypixel = info.vi_height;
3125         scp->xsize = info.vi_width/8;
3126         scp->ysize = info.vi_height/info.vi_cheight;
3127         scp->font_size = 0;
3128         scp->font = NULL;
3129     } else {
3130         scp->xsize = info.vi_width;
3131         scp->ysize = info.vi_height;
3132         scp->xpixel = scp->xsize*8;
3133         scp->ypixel = scp->ysize*info.vi_cheight;
3134         if (info.vi_cheight < 14) {
3135             scp->font_size = 8;
3136 #ifndef SC_NO_FONT_LOADING
3137             scp->font = sc->font_8;
3138 #else
3139             scp->font = NULL;
3140 #endif
3141         } else if (info.vi_cheight >= 16) {
3142             scp->font_size = 16;
3143 #ifndef SC_NO_FONT_LOADING
3144             scp->font = sc->font_16;
3145 #else
3146             scp->font = NULL;
3147 #endif
3148         } else {
3149             scp->font_size = 14;
3150 #ifndef SC_NO_FONT_LOADING
3151             scp->font = sc->font_14;
3152 #else
3153             scp->font = NULL;
3154 #endif
3155         }
3156     }
3157     sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE);
3158     sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE);
3159     scp->xoff = scp->yoff = 0;
3160     scp->xpos = scp->ypos = 0;
3161     scp->start = scp->xsize * scp->ysize - 1;
3162     scp->end = 0;
3163     scp->tsw = NULL;
3164     scp->ts = NULL;
3165     scp->rndr = NULL;
3166     scp->border = BG_BLACK;
3167     scp->cursor_base = sc->cursor_base;
3168     scp->cursor_height = imin(sc->cursor_height, scp->font_size);
3169     scp->mouse_cut_start = scp->xsize*scp->ysize;
3170     scp->mouse_cut_end = -1;
3171     scp->mouse_signal = 0;
3172     scp->mouse_pid = 0;
3173     scp->mouse_proc = NULL;
3174     scp->kbd_mode = K_XLATE;
3175     scp->bell_pitch = bios_value.bell_pitch;
3176     scp->bell_duration = BELL_DURATION;
3177     scp->status |= (bios_value.shift_state & NLKED);
3178     scp->status |= CURSOR_ENABLED | MOUSE_HIDDEN;
3179     scp->pid = 0;
3180     scp->proc = NULL;
3181     scp->smode.mode = VT_AUTO;
3182     scp->history = NULL;
3183     scp->history_pos = 0;
3184     scp->history_size = 0;
3185 }
3186
3187 int
3188 sc_init_emulator(scr_stat *scp, char *name)
3189 {
3190     sc_term_sw_t *sw;
3191     sc_rndr_sw_t *rndr;
3192     void *p;
3193     int error;
3194
3195     if (name == NULL)   /* if no name is given, use the current emulator */
3196         sw = scp->tsw;
3197     else                /* ...otherwise find the named emulator */
3198         sw = sc_term_match(name);
3199     if (sw == NULL) {
3200         return EINVAL;
3201     }
3202
3203     rndr = NULL;
3204     if (strcmp(sw->te_renderer, "*") != 0) {
3205         rndr = sc_render_match(scp, sw->te_renderer, scp->model);
3206     }
3207     if (rndr == NULL) {
3208         rndr = sc_render_match(scp, scp->sc->adp->va_name, scp->model);
3209         if (rndr == NULL) {
3210             return ENODEV;
3211         }
3212     }
3213
3214     if (sw == scp->tsw) {
3215         error = (*sw->te_init)(scp, &scp->ts, SC_TE_WARM_INIT);
3216         scp->rndr = rndr;
3217         sc_clear_screen(scp);
3218         /* assert(error == 0); */
3219         return error;
3220     }
3221
3222     if (sc_malloc && (sw->te_size > 0))
3223         p = kmalloc(sw->te_size, M_SYSCONS, M_NOWAIT);
3224     else
3225         p = NULL;
3226     error = (*sw->te_init)(scp, &p, SC_TE_COLD_INIT);
3227     if (error) {
3228         return error;
3229     }
3230
3231     if (scp->tsw)
3232         (*scp->tsw->te_term)(scp, &scp->ts);
3233     if (scp->ts != NULL)
3234         kfree(scp->ts, M_SYSCONS);
3235     scp->tsw = sw;
3236     scp->ts = p;
3237     scp->rndr = rndr;
3238
3239     /* XXX */
3240     (*sw->te_default_attr)(scp, user_default.std_color, user_default.rev_color);
3241     sc_clear_screen(scp);
3242
3243     return 0;
3244 }
3245
3246 /*
3247  * scgetc(flags) - get character from keyboard.
3248  * If flags & SCGETC_CN, then avoid harmful side effects.
3249  * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else
3250  * return NOKEY if there is nothing there.
3251  */
3252 static u_int
3253 scgetc(sc_softc_t *sc, u_int flags)
3254 {
3255     scr_stat *scp;
3256 #ifndef SC_NO_HISTORY
3257     struct tty *tp;
3258 #endif
3259     u_int c;
3260     int this_scr;
3261     int f;
3262     int i;
3263
3264     lwkt_gettoken(&tty_token);
3265     if (sc->kbd == NULL) {
3266         lwkt_reltoken(&tty_token);
3267         return NOKEY;
3268     }
3269
3270 next_code:
3271 #if 1
3272     /* I don't like this, but... XXX */
3273     if (flags & SCGETC_CN) {
3274         syscons_lock();
3275         sccnupdate(sc->cur_scp);
3276         syscons_unlock();
3277     }
3278 #endif
3279     scp = sc->cur_scp;
3280     /* first see if there is something in the keyboard port */
3281     for (;;) {
3282         c = kbd_read_char(sc->kbd, !(flags & SCGETC_NONBLOCK));
3283         if (c == ERRKEY) {
3284             if (!(flags & SCGETC_CN))
3285                 sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
3286         } else if (c == NOKEY) {
3287             lwkt_reltoken(&tty_token);
3288             return c;
3289         } else {
3290             break;
3291         }
3292     }
3293
3294     /* make screensaver happy */
3295     if (!(c & RELKEY))
3296         sc_touch_scrn_saver();
3297
3298     if (!(flags & SCGETC_CN))
3299         /* do the /dev/random device a favour */
3300         add_keyboard_randomness(c);
3301
3302     if (scp->kbd_mode != K_XLATE) {
3303         lwkt_reltoken(&tty_token);
3304         return KEYCHAR(c);
3305     }
3306
3307     /* if scroll-lock pressed allow history browsing */
3308     if (!ISGRAPHSC(scp) && scp->history && scp->status & SLKED) {
3309
3310         scp->status &= ~CURSOR_ENABLED;
3311         sc_remove_cursor_image(scp);
3312
3313 #ifndef SC_NO_HISTORY
3314         if (!(scp->status & BUFFER_SAVED)) {
3315             scp->status |= BUFFER_SAVED;
3316             sc_hist_save(scp);
3317         }
3318         switch (c) {
3319         /* FIXME: key codes */
3320         case SPCLKEY | FKEY | F(49):  /* home key */
3321             sc_remove_cutmarking(scp);
3322             sc_hist_home(scp);
3323             goto next_code;
3324
3325         case SPCLKEY | FKEY | F(57):  /* end key */
3326             sc_remove_cutmarking(scp);
3327             sc_hist_end(scp);
3328             goto next_code;
3329
3330         case SPCLKEY | FKEY | F(50):  /* up arrow key */
3331             sc_remove_cutmarking(scp);
3332             if (sc_hist_up_line(scp))
3333                 if (!(flags & SCGETC_CN))
3334                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
3335             goto next_code;
3336
3337         case SPCLKEY | FKEY | F(58):  /* down arrow key */
3338             sc_remove_cutmarking(scp);
3339             if (sc_hist_down_line(scp))
3340                 if (!(flags & SCGETC_CN))
3341                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
3342             goto next_code;
3343
3344         case SPCLKEY | FKEY | F(51):  /* page up key */
3345             sc_remove_cutmarking(scp);
3346             for (i=0; i<scp->ysize; i++)
3347             if (sc_hist_up_line(scp)) {
3348                 if (!(flags & SCGETC_CN))
3349                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
3350                 break;
3351             }
3352             goto next_code;
3353
3354         case SPCLKEY | FKEY | F(59):  /* page down key */
3355             sc_remove_cutmarking(scp);
3356             for (i=0; i<scp->ysize; i++)
3357             if (sc_hist_down_line(scp)) {
3358                 if (!(flags & SCGETC_CN))
3359                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
3360                 break;
3361             }
3362             goto next_code;
3363         }
3364 #endif /* SC_NO_HISTORY */
3365     }
3366
3367     /* 
3368      * Process and consume special keys here.  Return a plain char code
3369      * or a char code with the META flag or a function key code.
3370      */
3371     if (c & RELKEY) {
3372         /* key released */
3373         /* goto next_code */
3374     } else {
3375         /* key pressed */
3376         if (c & SPCLKEY) {
3377             c &= ~SPCLKEY;
3378             switch (KEYCHAR(c)) {
3379             /* LOCKING KEYS */
3380             case NLK: case CLK: case ALK:
3381                 break;
3382             case SLK:
3383                 kbd_ioctl(sc->kbd, KDGKBSTATE, (caddr_t)&f);
3384                 if (f & SLKED) {
3385                     scp->status |= SLKED;
3386                 } else {
3387                     if (scp->status & SLKED) {
3388                         scp->status &= ~SLKED;
3389 #ifndef SC_NO_HISTORY
3390                         if (scp->status & BUFFER_SAVED) {
3391                             if (!sc_hist_restore(scp))
3392                                 sc_remove_cutmarking(scp);
3393                             scp->status &= ~BUFFER_SAVED;
3394                             scp->status |= CURSOR_ENABLED;
3395                             sc_draw_cursor_image(scp);
3396                         }
3397                         tp = VIRTUAL_TTY(sc, scp->index);
3398                         if (ISTTYOPEN(tp))
3399                             scstart(tp);
3400 #endif
3401                     }
3402                 }
3403                 break;
3404
3405             /* NON-LOCKING KEYS */
3406             case NOP:
3407             case LSH:  case RSH:  case LCTR: case RCTR:
3408             case LALT: case RALT: case ASH:  case META:
3409                 break;
3410
3411             case BTAB:
3412                 if (!(sc->flags & SC_SCRN_BLANKED)) {
3413                     lwkt_reltoken(&tty_token);
3414                     return c;
3415                 }
3416                 break;
3417
3418             case SPSC:
3419 #if NSPLASH > 0
3420                 /* force activatation/deactivation of the screen saver */
3421                 if (!(sc->flags & SC_SCRN_BLANKED)) {
3422                     run_scrn_saver = TRUE;
3423                     sc->scrn_time_stamp -= scrn_blank_time;
3424                 }
3425                 if (cold) {
3426                     /*
3427                      * While devices are being probed, the screen saver need
3428                      * to be invoked explictly. XXX
3429                      */
3430                     if (sc->flags & SC_SCRN_BLANKED) {
3431                         scsplash_stick(FALSE);
3432                         stop_scrn_saver(sc, current_saver);
3433                     } else {
3434                         if (!ISGRAPHSC(scp)) {
3435                             scsplash_stick(TRUE);
3436                             (*current_saver)(sc, TRUE);
3437                         }
3438                     }
3439                 }
3440 #endif /* NSPLASH */
3441                 break;
3442
3443             case RBT:
3444 #ifndef SC_DISABLE_REBOOT
3445                 shutdown_nice(0);
3446 #endif
3447                 break;
3448
3449             case HALT:
3450 #ifndef SC_DISABLE_REBOOT
3451                 shutdown_nice(RB_HALT);
3452 #endif
3453                 break;
3454
3455             case PDWN:
3456 #ifndef SC_DISABLE_REBOOT
3457                 shutdown_nice(RB_HALT|RB_POWEROFF);
3458 #endif
3459                 break;
3460
3461 #if NAPM > 0
3462             case SUSP:
3463                 apm_suspend(PMST_SUSPEND);
3464                 break;
3465             case STBY:
3466                 apm_suspend(PMST_STANDBY);
3467                 break;
3468 #else
3469             case SUSP:
3470             case STBY:
3471                 break;
3472 #endif
3473
3474             case DBG:
3475 #ifndef SC_DISABLE_DDBKEY
3476 #ifdef DDB
3477                 lwkt_reltoken(&tty_token);
3478                 Debugger("manual escape to debugger");
3479                 lwkt_gettoken(&tty_token);
3480 #else
3481                 kprintf("No debugger in kernel\n");
3482 #endif
3483 #else /* SC_DISABLE_DDBKEY */
3484                 /* do nothing */
3485 #endif /* SC_DISABLE_DDBKEY */
3486                 break;
3487
3488             case PNC:
3489                 if (enable_panic_key)
3490                         panic("Forced by the panic key");
3491                 break;
3492
3493             case NEXT:
3494                 this_scr = scp->index;
3495                 for (i = (this_scr - sc->first_vty + 1)%sc->vtys;
3496                         sc->first_vty + i != this_scr; 
3497                         i = (i + 1)%sc->vtys) {
3498                     struct tty *tp = VIRTUAL_TTY(sc, sc->first_vty + i);
3499                     if (ISTTYOPEN(tp)) {
3500                         syscons_lock();
3501                         sc_switch_scr(scp->sc, sc->first_vty + i);
3502                         syscons_unlock();
3503                         break;
3504                     }
3505                 }
3506                 break;
3507
3508             case PREV:
3509                 this_scr = scp->index;
3510                 for (i = (this_scr - sc->first_vty + sc->vtys - 1)%sc->vtys;
3511                         sc->first_vty + i != this_scr;
3512                         i = (i + sc->vtys - 1)%sc->vtys) {
3513                     struct tty *tp = VIRTUAL_TTY(sc, sc->first_vty + i);
3514                     if (ISTTYOPEN(tp)) {
3515                         syscons_lock();
3516                         sc_switch_scr(scp->sc, sc->first_vty + i);
3517                         syscons_unlock();
3518                         break;
3519                     }
3520                 }
3521                 break;
3522
3523             default:
3524                 if (KEYCHAR(c) >= F_SCR && KEYCHAR(c) <= L_SCR) {
3525                     syscons_lock();
3526                     sc_switch_scr(scp->sc, sc->first_vty + KEYCHAR(c) - F_SCR);
3527                     syscons_unlock();
3528                     break;
3529                 }
3530                 /* assert(c & FKEY) */
3531                 if (!(sc->flags & SC_SCRN_BLANKED)) {
3532                     lwkt_reltoken(&tty_token);
3533                     return c;
3534                 }
3535                 break;
3536             }
3537             /* goto next_code */
3538         } else {
3539             /* regular keys (maybe MKEY is set) */
3540             if (!(sc->flags & SC_SCRN_BLANKED)) {
3541                 lwkt_reltoken(&tty_token);
3542                 return c;
3543             }
3544         }
3545     }
3546
3547     goto next_code;
3548 }
3549
3550 int
3551 scmmap(struct dev_mmap_args *ap)
3552 {
3553     scr_stat *scp;
3554
3555     lwkt_gettoken(&tty_token);
3556     scp = SC_STAT(ap->a_head.a_dev);
3557     if (scp != scp->sc->cur_scp) {
3558         lwkt_reltoken(&tty_token);
3559         return EINVAL;
3560     }
3561     ap->a_result = (*vidsw[scp->sc->adapter]->mmap)(scp->sc->adp, ap->a_offset,
3562                                                     ap->a_nprot);
3563     lwkt_reltoken(&tty_token);
3564     return(0);
3565 }
3566
3567 static int
3568 save_kbd_state(scr_stat *scp, int unlock)
3569 {
3570     int state;
3571     int error;
3572
3573     WANT_UNLOCK(unlock);
3574     error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state);
3575     WANT_LOCK(unlock);
3576
3577     if (error == ENOIOCTL)
3578         error = ENODEV;
3579     if (error == 0) {
3580         scp->status &= ~LOCK_MASK;
3581         scp->status |= state;
3582     }
3583     return error;
3584 }
3585
3586 static int
3587 update_kbd_state(scr_stat *scp, int new_bits, int mask, int unlock)
3588 {
3589     int state;
3590     int error;
3591
3592     if (mask != LOCK_MASK) {
3593         WANT_UNLOCK(unlock);
3594         error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state);
3595         WANT_LOCK(unlock);
3596
3597         if (error == ENOIOCTL)
3598             error = ENODEV;
3599         if (error) {
3600             return error;
3601         }
3602         state &= ~mask;
3603         state |= new_bits & mask;
3604     } else {
3605         state = new_bits & LOCK_MASK;
3606     }
3607     WANT_UNLOCK(unlock);
3608     error = kbd_ioctl(scp->sc->kbd, KDSKBSTATE, (caddr_t)&state);
3609     WANT_LOCK(unlock);
3610     if (error == ENOIOCTL)
3611         error = ENODEV;
3612     return error;
3613 }
3614
3615 static int
3616 update_kbd_leds(scr_stat *scp, int which)
3617 {
3618     int error;
3619
3620     which &= LOCK_MASK;
3621     error = kbd_ioctl(scp->sc->kbd, KDSETLED, (caddr_t)&which);
3622     if (error == ENOIOCTL)
3623         error = ENODEV;
3624     return error;
3625 }
3626
3627 int
3628 set_mode(scr_stat *scp)
3629 {
3630     video_info_t info;
3631
3632     lwkt_gettoken(&tty_token);
3633     /* reject unsupported mode */
3634     if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) {
3635         lwkt_reltoken(&tty_token);
3636         return 1;
3637     }
3638
3639     /* if this vty is not currently showing, do nothing */
3640     if (scp != scp->sc->cur_scp) {
3641         lwkt_reltoken(&tty_token);
3642         return 0;
3643     }
3644
3645     /* setup video hardware for the given mode */
3646     (*vidsw[scp->sc->adapter]->set_mode)(scp->sc->adp, scp->mode);
3647     sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
3648                 (void *)scp->sc->adp->va_window, FALSE);
3649
3650 #ifndef SC_NO_FONT_LOADING
3651     /* load appropriate font */
3652     if (!(scp->status & GRAPHICS_MODE)) {
3653         if (!(scp->status & PIXEL_MODE) && ISFONTAVAIL(scp->sc->adp->va_flags)) {
3654             if (scp->font_size < 14) {
3655                 if (scp->sc->fonts_loaded & FONT_8)
3656                     sc_load_font(scp, 0, 8, scp->sc->font_8, 0, 256);
3657             } else if (scp->font_size >= 16) {
3658                 if (scp->sc->fonts_loaded & FONT_16)
3659                     sc_load_font(scp, 0, 16, scp->sc->font_16, 0, 256);
3660             } else {
3661                 if (scp->sc->fonts_loaded & FONT_14)
3662                     sc_load_font(scp, 0, 14, scp->sc->font_14, 0, 256);
3663             }
3664             /*
3665              * FONT KLUDGE:
3666              * This is an interim kludge to display correct font.
3667              * Always use the font page #0 on the video plane 2.
3668              * Somehow we cannot show the font in other font pages on
3669              * some video cards... XXX
3670              */ 
3671             sc_show_font(scp, 0);
3672         }
3673         mark_all(scp);
3674     }
3675 #endif /* !SC_NO_FONT_LOADING */
3676
3677     sc_set_border(scp, scp->border);
3678     sc_set_cursor_image(scp);
3679
3680     lwkt_reltoken(&tty_token);
3681     return 0;
3682 }
3683
3684 void
3685 refresh_ega_palette(scr_stat *scp)
3686 {
3687     uint32_t r, g, b;
3688     int reg;
3689     int rsize, gsize, bsize;
3690     int rfld, gfld, bfld;
3691     int i;
3692
3693     rsize = scp->sc->adp->va_info.vi_pixel_fsizes[0];
3694     gsize = scp->sc->adp->va_info.vi_pixel_fsizes[1];
3695     bsize = scp->sc->adp->va_info.vi_pixel_fsizes[2];
3696     rfld = scp->sc->adp->va_info.vi_pixel_fields[0];
3697     gfld = scp->sc->adp->va_info.vi_pixel_fields[1];
3698     bfld = scp->sc->adp->va_info.vi_pixel_fields[2];
3699
3700     for (i = 0; i < 16; i++) {
3701         reg = scp->sc->adp->va_palette_regs[i];
3702
3703         r = scp->sc->palette[reg * 3] >> (8 - rsize);
3704         g = scp->sc->palette[reg * 3 + 1] >> (8 - gsize);
3705         b = scp->sc->palette[reg * 3 + 2] >> (8 - bsize);
3706
3707         scp->ega_palette[i] = (r << rfld) + (g << gfld) + (b << bfld);
3708     }
3709 }
3710
3711 void
3712 sc_set_border(scr_stat *scp, int color)
3713 {
3714     ++scp->sc->videoio_in_progress;
3715     (*scp->rndr->draw_border)(scp, color);
3716     --scp->sc->videoio_in_progress;
3717 }
3718
3719 #ifndef SC_NO_FONT_LOADING
3720 void
3721 sc_load_font(scr_stat *scp, int page, int size, u_char *buf,
3722              int base, int count)
3723 {
3724     sc_softc_t *sc;
3725
3726     sc = scp->sc;
3727     sc->font_loading_in_progress = TRUE;
3728     (*vidsw[sc->adapter]->load_font)(sc->adp, page, size, buf, base, count);
3729     sc->font_loading_in_progress = FALSE;
3730 }
3731
3732 void
3733 sc_save_font(scr_stat *scp, int page, int size, u_char *buf,
3734              int base, int count)
3735 {
3736     sc_softc_t *sc;
3737
3738     sc = scp->sc;
3739     sc->font_loading_in_progress = TRUE;
3740     (*vidsw[sc->adapter]->save_font)(sc->adp, page, size, buf, base, count);
3741     sc->font_loading_in_progress = FALSE;
3742 }
3743
3744 void
3745 sc_show_font(scr_stat *scp, int page)
3746 {
3747     (*vidsw[scp->sc->adapter]->show_font)(scp->sc->adp, page);
3748 }
3749 #endif /* !SC_NO_FONT_LOADING */
3750
3751 void
3752 sc_paste(scr_stat *scp, u_char *p, int count) 
3753 {
3754     struct tty *tp;
3755     u_char *rmap;
3756
3757     lwkt_gettoken(&tty_token);
3758     if (scp->status & MOUSE_VISIBLE) {
3759         tp = VIRTUAL_TTY(scp->sc, scp->sc->cur_scp->index);
3760         if (!ISTTYOPEN(tp)) {
3761             lwkt_reltoken(&tty_token);
3762             return;
3763         }
3764         rmap = scp->sc->scr_rmap;
3765         for (; count > 0; --count)
3766             (*linesw[tp->t_line].l_rint)(rmap[*p++], tp);
3767     }
3768     lwkt_reltoken(&tty_token);
3769 }
3770
3771 void
3772 sc_bell(scr_stat *scp, int pitch, int duration)
3773 {
3774     if (cold || shutdown_in_progress)
3775         return;
3776
3777     if (scp != scp->sc->cur_scp && (scp->sc->flags & SC_QUIET_BELL)) {
3778         return;
3779     }
3780
3781     if (scp->sc->flags & SC_VISUAL_BELL) {
3782         if (scp->sc->blink_in_progress) {
3783             return;
3784         }
3785         scp->sc->blink_in_progress = 3;
3786         if (scp != scp->sc->cur_scp)
3787             scp->sc->blink_in_progress += 2;
3788         sc_blink_screen(scp->sc->cur_scp);
3789     } else if (duration != 0 && pitch != 0) {
3790         if (scp != scp->sc->cur_scp)
3791             pitch *= 2;
3792         sysbeep(pitch, duration);
3793     }
3794 }
3795
3796 /*
3797  * Two versions of blink_screen(), one called from the console path
3798  * with the syscons locked, and one called from a timer callout.
3799  */
3800 static void
3801 sc_blink_screen(scr_stat *scp)
3802 {
3803     if (ISGRAPHSC(scp) || (scp->sc->blink_in_progress <= 1)) {
3804         scp->sc->blink_in_progress = 0;
3805         mark_all(scp);
3806         if (scp->sc->delayed_next_scr)
3807             sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
3808     } else {
3809         (*scp->rndr->draw)(scp, 0, scp->xsize*scp->ysize,
3810                            scp->sc->blink_in_progress & 1);
3811         scp->sc->blink_in_progress--;
3812     }
3813 }
3814
3815 #if 0
3816 static void
3817 blink_screen_callout(void *arg)
3818 {
3819     scr_stat *scp = arg;
3820     struct tty *tp;
3821
3822     if (ISGRAPHSC(scp) || (scp->sc->blink_in_progress <= 1)) {
3823         syscons_lock();
3824         scp->sc->blink_in_progress = 0;
3825         mark_all(scp);
3826         syscons_unlock();
3827         tp = VIRTUAL_TTY(scp->sc, scp->index);
3828         if (ISTTYOPEN(tp))
3829             scstart(tp);
3830         if (scp->sc->delayed_next_scr) {
3831             syscons_lock();
3832             sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
3833             syscons_unlock();
3834         }
3835     } else {
3836         syscons_lock();
3837         (*scp->rndr->draw)(scp, 0, scp->xsize*scp->ysize, 
3838                            scp->sc->blink_in_progress & 1);
3839         scp->sc->blink_in_progress--;
3840         syscons_unlock();
3841         callout_reset(&scp->blink_screen_ch, hz / 10,
3842                       blink_screen_callout, scp);
3843     }
3844 }
3845 #endif
3846
3847 /*
3848  * Allocate active keyboard. Try to allocate "kbdmux" keyboard first, and,
3849  * if found, add all non-busy keyboards to "kbdmux". Otherwise look for
3850  * any keyboard.
3851  */
3852
3853 static int
3854 sc_allocate_keyboard(sc_softc_t *sc, int unit)
3855 {
3856         int              idx0, idx;
3857         keyboard_t      *k0, *k;
3858         keyboard_info_t  ki;
3859
3860         idx0 = kbd_allocate("kbdmux", -1, (void *)&sc->keyboard, sckbdevent, sc);
3861         if (idx0 != -1) {
3862                 k0 = kbd_get_keyboard(idx0);
3863
3864                 for (idx = kbd_find_keyboard2("*", -1, 0, 0);
3865                      idx != -1;
3866                      idx = kbd_find_keyboard2("*", -1, idx + 1, 0)) {
3867                         k = kbd_get_keyboard(idx);
3868
3869                         if (idx == idx0 || KBD_IS_BUSY(k))
3870                                 continue;
3871
3872                         bzero(&ki, sizeof(ki));
3873                         strcpy(ki.kb_name, k->kb_name);
3874                         ki.kb_unit = k->kb_unit;
3875
3876                         kbd_ioctl(k0, KBADDKBD, (caddr_t) &ki);
3877                 }
3878         } else
3879                 idx0 = kbd_allocate("*", unit, (void *)&sc->keyboard, sckbdevent, sc);
3880
3881         return (idx0);
3882 }