kernel - Attempt to fix NULL pointer dereference during console switch
[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
1097         /*
1098          * scp might be NULL, we aren't sure why.  Check for NULL.
1099          *
1100          * http://bugs.dragonflybsd.org/issues/2481
1101          */
1102         scp = SC_STAT(SC_DEV(sc, i));
1103         if (scp == NULL || scp == scp->sc->cur_scp) {
1104             lwkt_reltoken(&tty_token);
1105             return 0;
1106         }
1107         error = tsleep((caddr_t)&scp->smode, PCATCH, "waitvt", 0);
1108         /* May return ERESTART */
1109         lwkt_reltoken(&tty_token);
1110         return error;
1111
1112     case VT_GETACTIVE:          /* get active vty # */
1113         *(int *)data = sc->cur_scp->index + 1;
1114         lwkt_reltoken(&tty_token);
1115         return 0;
1116
1117     case VT_GETINDEX:           /* get this vty # */
1118         *(int *)data = scp->index + 1;
1119         lwkt_reltoken(&tty_token);
1120         return 0;
1121
1122     case VT_LOCKSWITCH:         /* prevent vty switching */
1123         syscons_lock();
1124         if ((*(int *)data) & 0x01)
1125             sc->flags |= SC_SCRN_VTYLOCK;
1126         else
1127             sc->flags &= ~SC_SCRN_VTYLOCK;
1128         syscons_unlock();
1129         lwkt_reltoken(&tty_token);
1130         return 0;
1131
1132     case KDENABIO:              /* allow io operations */
1133         error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
1134         if (error != 0) {
1135             lwkt_reltoken(&tty_token);
1136             return error;
1137         }
1138         if (securelevel > 0) {
1139             lwkt_reltoken(&tty_token);
1140             return EPERM;
1141         }
1142         lwkt_gettoken(&proc_token);
1143 #if defined(__i386__)
1144         curthread->td_lwp->lwp_md.md_regs->tf_eflags |= PSL_IOPL;
1145 #elif defined(__x86_64__)
1146         curthread->td_lwp->lwp_md.md_regs->tf_rflags |= PSL_IOPL;
1147 #endif
1148         lwkt_reltoken(&proc_token);
1149         lwkt_reltoken(&tty_token);
1150         return 0;
1151
1152     case KDDISABIO:             /* disallow io operations (default) */
1153         lwkt_gettoken(&proc_token);
1154 #if defined(__i386__)
1155         curthread->td_lwp->lwp_md.md_regs->tf_eflags &= ~PSL_IOPL;
1156 #elif defined(__x86_64__)
1157         curthread->td_lwp->lwp_md.md_regs->tf_rflags &= ~PSL_IOPL;
1158 #endif
1159         lwkt_reltoken(&proc_token);
1160         lwkt_reltoken(&tty_token);
1161         return 0;
1162
1163     case KDSKBSTATE:            /* set keyboard state (locks) */
1164         if (*(int *)data & ~LOCK_MASK) {
1165             lwkt_reltoken(&tty_token);
1166             return EINVAL;
1167         }
1168         syscons_lock();
1169         scp->status &= ~LOCK_MASK;
1170         scp->status |= *(int *)data;
1171         syscons_unlock();
1172         if (scp == sc->cur_scp)
1173             update_kbd_state(scp, scp->status, LOCK_MASK, FALSE);
1174         lwkt_reltoken(&tty_token);
1175         return 0;
1176
1177     case KDGKBSTATE:            /* get keyboard state (locks) */
1178         if (scp == sc->cur_scp)
1179             save_kbd_state(scp, FALSE);
1180         *(int *)data = scp->status & LOCK_MASK;
1181         lwkt_reltoken(&tty_token);
1182         return 0;
1183
1184     case KDGETREPEAT:           /* get keyboard repeat & delay rates */
1185     case KDSETREPEAT:           /* set keyboard repeat & delay rates (new) */
1186         error = kbd_ioctl(sc->kbd, cmd, data);
1187         if (error == ENOIOCTL)
1188             error = ENODEV;
1189         lwkt_reltoken(&tty_token);
1190         return error;
1191
1192     case KDSETRAD:              /* set keyboard repeat & delay rates (old) */
1193         if (*(int *)data & ~0x7f) {
1194             lwkt_reltoken(&tty_token);
1195             return EINVAL;
1196         }
1197         error = kbd_ioctl(sc->kbd, cmd, data);
1198         if (error == ENOIOCTL)
1199             error = ENODEV;
1200         lwkt_reltoken(&tty_token);
1201         return error;
1202
1203     case KDSKBMODE:             /* set keyboard mode */
1204         switch (*(int *)data) {
1205         case K_XLATE:           /* switch to XLT ascii mode */
1206         case K_RAW:             /* switch to RAW scancode mode */
1207         case K_CODE:            /* switch to CODE mode */
1208             scp->kbd_mode = *(int *)data;
1209             if (scp == sc->cur_scp)
1210                 kbd_ioctl(sc->kbd, cmd, data);
1211             lwkt_reltoken(&tty_token);
1212             return 0;
1213         default:
1214             lwkt_reltoken(&tty_token);
1215             return EINVAL;
1216         }
1217         /* NOT REACHED */
1218
1219     case KDGKBMODE:             /* get keyboard mode */
1220         *(int *)data = scp->kbd_mode;
1221         lwkt_reltoken(&tty_token);
1222         return 0;
1223
1224     case KDGKBINFO:
1225         error = kbd_ioctl(sc->kbd, cmd, data);
1226         if (error == ENOIOCTL)
1227             error = ENODEV;
1228         lwkt_reltoken(&tty_token);
1229         return error;
1230
1231     case KDMKTONE:              /* sound the bell */
1232         syscons_lock();
1233         if (*(int*)data)
1234             sc_bell(scp, (*(int*)data)&0xffff,
1235                     (((*(int*)data)>>16)&0xffff)*hz/1000);
1236         else
1237             sc_bell(scp, scp->bell_pitch, scp->bell_duration);
1238         syscons_unlock();
1239         lwkt_reltoken(&tty_token);
1240         return 0;
1241
1242     case KIOCSOUND:             /* make tone (*data) hz */
1243         syscons_lock();
1244         if (scp == sc->cur_scp) {
1245             if (*(int *)data) {
1246                 error = sc_tone(*(int *)data);
1247             } else {
1248                 error = sc_tone(0);
1249             }
1250         } else {
1251             error = 0;
1252         }
1253         syscons_unlock();
1254         lwkt_reltoken(&tty_token);
1255         return error;
1256
1257     case KDGKBTYPE:             /* get keyboard type */
1258         error = kbd_ioctl(sc->kbd, cmd, data);
1259         if (error == ENOIOCTL) {
1260             /* always return something? XXX */
1261             *(int *)data = 0;
1262         }
1263         lwkt_reltoken(&tty_token);
1264         return 0;
1265
1266     case KDSETLED:              /* set keyboard LED status */
1267         if (*(int *)data & ~LED_MASK) { /* FIXME: LOCK_MASK? */
1268             lwkt_reltoken(&tty_token);
1269             return EINVAL;
1270         }
1271         syscons_lock();
1272         scp->status &= ~LED_MASK;
1273         scp->status |= *(int *)data;
1274         syscons_unlock();
1275         if (scp == sc->cur_scp)
1276             update_kbd_leds(scp, scp->status);
1277         lwkt_reltoken(&tty_token);
1278         return 0;
1279
1280     case KDGETLED:              /* get keyboard LED status */
1281         if (scp == sc->cur_scp)
1282             save_kbd_state(scp, FALSE);
1283         *(int *)data = scp->status & LED_MASK;
1284         lwkt_reltoken(&tty_token);
1285         return 0;
1286
1287         case KBADDKBD:              /* add/remove keyboard to/from mux */
1288         case KBRELKBD:
1289                 error = kbd_ioctl(sc->kbd, cmd, data);
1290                 if (error == ENOIOCTL)
1291                         error = ENODEV;
1292                 lwkt_reltoken(&tty_token);
1293                 return error;
1294
1295     case CONS_SETKBD:           /* set the new keyboard */
1296         {
1297             keyboard_t *newkbd;
1298
1299             newkbd = kbd_get_keyboard(*(int *)data);
1300             if (newkbd == NULL) {
1301                 lwkt_reltoken(&tty_token);
1302                 return EINVAL;
1303             }
1304             error = 0;
1305             if (sc->kbd != newkbd) {
1306                 i = kbd_allocate(newkbd->kb_name, newkbd->kb_unit,
1307                                  (void *)&sc->keyboard, sckbdevent, sc);
1308                 /* i == newkbd->kb_index */
1309                 if (i >= 0) {
1310                     if (sc->kbd != NULL) {
1311                         save_kbd_state(sc->cur_scp, FALSE);
1312                         kbd_release(sc->kbd, (void *)&sc->keyboard);
1313                     }
1314                     syscons_lock();
1315                     sc->kbd = kbd_get_keyboard(i); /* sc->kbd == newkbd */
1316                     sc->keyboard = i;
1317                     syscons_unlock();
1318                     kbd_ioctl(sc->kbd, KDSKBMODE,
1319                               (caddr_t)&sc->cur_scp->kbd_mode);
1320                     update_kbd_state(sc->cur_scp, sc->cur_scp->status,
1321                         LOCK_MASK, FALSE);
1322                 } else {
1323                     error = EPERM;      /* XXX */
1324                 }
1325             }
1326             lwkt_reltoken(&tty_token);
1327             return error;
1328         }
1329
1330     case CONS_RELKBD:           /* release the current keyboard */
1331         error = 0;
1332         if (sc->kbd != NULL) {
1333             save_kbd_state(sc->cur_scp, FALSE);
1334             error = kbd_release(sc->kbd, (void *)&sc->keyboard);
1335             if (error == 0) {
1336                 syscons_lock();
1337                 sc->kbd = NULL;
1338                 sc->keyboard = -1;
1339                 syscons_unlock();
1340             }
1341         }
1342         lwkt_reltoken(&tty_token);
1343         return error;
1344
1345     case CONS_GETTERM:          /* get the current terminal emulator info */
1346         {
1347             sc_term_sw_t *sw;
1348
1349             if (((term_info_t *)data)->ti_index == 0) {
1350                 sw = scp->tsw;
1351             } else {
1352                 sw = sc_term_match_by_number(((term_info_t *)data)->ti_index);
1353             }
1354             if (sw != NULL) {
1355                 strncpy(((term_info_t *)data)->ti_name, sw->te_name, 
1356                         sizeof(((term_info_t *)data)->ti_name));
1357                 strncpy(((term_info_t *)data)->ti_desc, sw->te_desc, 
1358                         sizeof(((term_info_t *)data)->ti_desc));
1359                 ((term_info_t *)data)->ti_flags = 0;
1360                 lwkt_reltoken(&tty_token);
1361                 return 0;
1362             } else {
1363                 ((term_info_t *)data)->ti_name[0] = '\0';
1364                 ((term_info_t *)data)->ti_desc[0] = '\0';
1365                 ((term_info_t *)data)->ti_flags = 0;
1366                 lwkt_reltoken(&tty_token);
1367                 return EINVAL;
1368             }
1369         }
1370
1371     case CONS_SETTERM:          /* set the current terminal emulator */
1372         syscons_lock();
1373         error = sc_init_emulator(scp, ((term_info_t *)data)->ti_name);
1374         /* FIXME: what if scp == sc_console! XXX */
1375         syscons_unlock();
1376         lwkt_reltoken(&tty_token);
1377         return error;
1378
1379     case GIO_SCRNMAP:           /* get output translation table */
1380         bcopy(&sc->scr_map, data, sizeof(sc->scr_map));
1381         lwkt_reltoken(&tty_token);
1382         return 0;
1383
1384     case PIO_SCRNMAP:           /* set output translation table */
1385         bcopy(data, &sc->scr_map, sizeof(sc->scr_map));
1386         for (i=0; i<sizeof(sc->scr_map); i++) {
1387             sc->scr_rmap[sc->scr_map[i]] = i;
1388         }
1389         lwkt_reltoken(&tty_token);
1390         return 0;
1391
1392     case GIO_KEYMAP:            /* get keyboard translation table */
1393     case PIO_KEYMAP:            /* set keyboard translation table */
1394     case GIO_DEADKEYMAP:        /* get accent key translation table */
1395     case PIO_DEADKEYMAP:        /* set accent key translation table */
1396     case GETFKEY:               /* get function key string */
1397     case SETFKEY:               /* set function key string */
1398         error = kbd_ioctl(sc->kbd, cmd, data);
1399         if (error == ENOIOCTL)
1400             error = ENODEV;
1401         lwkt_reltoken(&tty_token);
1402         return error;
1403
1404 #ifndef SC_NO_FONT_LOADING
1405
1406     case PIO_FONT8x8:           /* set 8x8 dot font */
1407         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1408             lwkt_reltoken(&tty_token);
1409             return ENXIO;
1410         }
1411         syscons_lock();
1412         bcopy(data, sc->font_8, 8*256);
1413         sc->fonts_loaded |= FONT_8;
1414         /*
1415          * FONT KLUDGE
1416          * Always use the font page #0. XXX
1417          * Don't load if the current font size is not 8x8.
1418          */
1419         if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size < 14))
1420             sc_load_font(sc->cur_scp, 0, 8, sc->font_8, 0, 256);
1421         syscons_unlock();
1422         lwkt_reltoken(&tty_token);
1423         return 0;
1424
1425     case GIO_FONT8x8:           /* get 8x8 dot font */
1426         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1427             lwkt_reltoken(&tty_token);
1428             return ENXIO;
1429         }
1430         if (sc->fonts_loaded & FONT_8) {
1431             bcopy(sc->font_8, data, 8*256);
1432             lwkt_reltoken(&tty_token);
1433             return 0;
1434         }
1435         else {
1436             lwkt_reltoken(&tty_token);
1437             return ENXIO;
1438         }
1439
1440     case PIO_FONT8x14:          /* set 8x14 dot font */
1441         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1442             lwkt_reltoken(&tty_token);
1443             return ENXIO;
1444         }
1445         syscons_lock();
1446         bcopy(data, sc->font_14, 14*256);
1447         sc->fonts_loaded |= FONT_14;
1448         /*
1449          * FONT KLUDGE
1450          * Always use the font page #0. XXX
1451          * Don't load if the current font size is not 8x14.
1452          */
1453         if (ISTEXTSC(sc->cur_scp)
1454             && (sc->cur_scp->font_size >= 14)
1455             && (sc->cur_scp->font_size < 16)) {
1456             sc_load_font(sc->cur_scp, 0, 14, sc->font_14, 0, 256);
1457         }
1458         syscons_unlock();
1459         lwkt_reltoken(&tty_token);
1460         return 0;
1461
1462     case GIO_FONT8x14:          /* get 8x14 dot font */
1463         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1464             lwkt_reltoken(&tty_token);
1465             return ENXIO;
1466         }
1467         if (sc->fonts_loaded & FONT_14) {
1468             bcopy(sc->font_14, data, 14*256);
1469             lwkt_reltoken(&tty_token);
1470             return 0;
1471         }
1472         else {
1473             lwkt_reltoken(&tty_token);
1474             return ENXIO;
1475         }
1476
1477     case PIO_FONT8x16:          /* set 8x16 dot font */
1478         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1479             lwkt_reltoken(&tty_token);
1480             return ENXIO;
1481         }
1482         syscons_lock();
1483         bcopy(data, sc->font_16, 16*256);
1484         sc->fonts_loaded |= FONT_16;
1485         /*
1486          * FONT KLUDGE
1487          * Always use the font page #0. XXX
1488          * Don't load if the current font size is not 8x16.
1489          */
1490         if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size >= 16))
1491             sc_load_font(sc->cur_scp, 0, 16, sc->font_16, 0, 256);
1492         syscons_unlock();
1493         lwkt_reltoken(&tty_token);
1494         return 0;
1495
1496     case GIO_FONT8x16:          /* get 8x16 dot font */
1497         if (!ISFONTAVAIL(sc->adp->va_flags)) {
1498             lwkt_reltoken(&tty_token);
1499             return ENXIO;
1500         }
1501         if (sc->fonts_loaded & FONT_16) {
1502             bcopy(sc->font_16, data, 16*256);
1503             lwkt_reltoken(&tty_token);
1504             return 0;
1505         }
1506         else {
1507             lwkt_reltoken(&tty_token);
1508             return ENXIO;
1509         }
1510
1511 #endif /* SC_NO_FONT_LOADING */
1512
1513     default:
1514         break;
1515     }
1516
1517     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, ap->a_cred);
1518     if (error != ENOIOCTL) {
1519         lwkt_reltoken(&tty_token);
1520         return(error);
1521     }
1522     error = ttioctl(tp, cmd, data, flag);
1523     if (error != ENOIOCTL) {
1524         lwkt_reltoken(&tty_token);
1525         return(error);
1526     }
1527     lwkt_reltoken(&tty_token);
1528     return(ENOTTY);
1529 }
1530
1531 static void
1532 scstart(struct tty *tp)
1533 {
1534     struct clist *rbp;
1535     int len;
1536     u_char buf[PCBURST];
1537     scr_stat *scp = SC_STAT(tp->t_dev);
1538
1539     syscons_lock();
1540     if (scp->status & SLKED ||
1541         (scp == scp->sc->cur_scp && scp->sc->blink_in_progress))
1542     {
1543         syscons_unlock();
1544         return;
1545     }
1546     if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
1547         tp->t_state |= TS_BUSY;
1548         rbp = &tp->t_outq;
1549         while (rbp->c_cc) {
1550             len = q_to_b(rbp, buf, PCBURST);
1551             sc_puts(scp, buf, len);
1552         }
1553         tp->t_state &= ~TS_BUSY;
1554         syscons_unlock();
1555         ttwwakeup(tp);
1556     } else {
1557         syscons_unlock();
1558     }
1559 }
1560
1561 static void
1562 sccnprobe(struct consdev *cp)
1563 {
1564     int unit;
1565     int flags;
1566
1567     cp->cn_pri = sc_get_cons_priority(&unit, &flags);
1568
1569     /* a video card is always required */
1570     if (!scvidprobe(unit, flags, TRUE))
1571         cp->cn_pri = CN_DEAD;
1572
1573     /* syscons will become console even when there is no keyboard */
1574     sckbdprobe(unit, flags, TRUE);
1575
1576     if (cp->cn_pri == CN_DEAD) {
1577         return;
1578     }
1579
1580     /* initialize required fields */
1581     cp->cn_probegood = 1;
1582 }
1583
1584 static void
1585 sccninit(struct consdev *cp)
1586 {
1587     int unit;
1588     int flags;
1589
1590     sc_get_cons_priority(&unit, &flags);
1591     scinit(unit, flags | SC_KERNEL_CONSOLE);
1592     sc_console_unit = unit;
1593     sc_console = sc_get_softc(unit, SC_KERNEL_CONSOLE)->console_scp;
1594 }
1595
1596 static void
1597 sccninit_fini(struct consdev *cp)
1598 {
1599         if (cctl_dev == NULL)
1600                 kprintf("sccninit_fini: WARNING: cctl_dev is NULL!\n");
1601         cp->cn_dev = cctl_dev;
1602 }
1603
1604 static void
1605 sccnterm(struct consdev *cp)
1606 {
1607     /* we are not the kernel console any more, release everything */
1608
1609     if (sc_console_unit < 0)
1610         return;                 /* shouldn't happen */
1611
1612 #if 0 /* XXX */
1613     syscons_lock();
1614     sc_clear_screen(sc_console);
1615     sccnupdate(sc_console);
1616     syscons_unlock();
1617 #endif
1618     scterm(sc_console_unit, SC_KERNEL_CONSOLE);
1619     sc_console_unit = -1;
1620     sc_console = NULL;
1621 }
1622
1623 /*
1624  * Console path - cannot block!
1625  */
1626 static void
1627 sccnputc(void *private, int c)
1628 {
1629     u_char buf[1];
1630     scr_stat *scp = sc_console;
1631     void *save;
1632 #ifndef SC_NO_HISTORY
1633 #if 0
1634     struct tty *tp;
1635 #endif
1636 #endif /* !SC_NO_HISTORY */
1637
1638     /* assert(sc_console != NULL) */
1639
1640     syscons_lock();
1641 #ifndef SC_NO_HISTORY
1642     if (scp == scp->sc->cur_scp && scp->status & SLKED) {
1643         scp->status &= ~SLKED;
1644 #if 0
1645         /* This can block, illegal in the console path */
1646         update_kbd_state(scp, scp->status, SLKED, TRUE);
1647 #endif
1648         if (scp->status & BUFFER_SAVED) {
1649             if (!sc_hist_restore(scp))
1650                 sc_remove_cutmarking(scp);
1651             scp->status &= ~BUFFER_SAVED;
1652             scp->status |= CURSOR_ENABLED;
1653             sc_draw_cursor_image(scp);
1654         }
1655 #if 0
1656         tp = VIRTUAL_TTY(scp->sc, scp->index);
1657         /* This can block, illegal in the console path */
1658         if (ISTTYOPEN(tp)) {
1659             scstart(tp);
1660         }
1661 #endif
1662     }
1663 #endif /* !SC_NO_HISTORY */
1664
1665     save = scp->ts;
1666     if (kernel_console_ts != NULL)
1667         scp->ts = kernel_console_ts;
1668     buf[0] = c;
1669     sc_puts(scp, buf, 1);
1670     scp->ts = save;
1671
1672     sccnupdate(scp);
1673     syscons_unlock();
1674 }
1675
1676 /*
1677  * Console path - cannot block!
1678  */
1679 static int
1680 sccngetc(void *private)
1681 {
1682     return sccngetch(0);
1683 }
1684
1685 /*
1686  * Console path - cannot block!
1687  */
1688 static int
1689 sccncheckc(void *private)
1690 {
1691     return sccngetch(SCGETC_NONBLOCK);
1692 }
1693
1694 static void
1695 sccndbctl(void *private, int on)
1696 {
1697     /* assert(sc_console_unit >= 0) */
1698     /* try to switch to the kernel console screen */
1699     if (on && debugger == 0) {
1700         /*
1701          * TRY to make sure the screen saver is stopped, 
1702          * and the screen is updated before switching to 
1703          * the vty0.
1704          */
1705         scrn_timer(NULL);
1706         if (!cold
1707             && sc_console->sc->cur_scp->smode.mode == VT_AUTO
1708             && sc_console->smode.mode == VT_AUTO) {
1709             sc_console->sc->cur_scp->status |= MOUSE_HIDDEN;
1710             syscons_lock();
1711             sc_switch_scr(sc_console->sc, sc_console->index);
1712             syscons_unlock();
1713         }
1714     }
1715     if (on)
1716         ++debugger;
1717     else
1718         --debugger;
1719 }
1720
1721 /*
1722  * Console path - cannot block!
1723  */
1724 static int
1725 sccngetch(int flags)
1726 {
1727     static struct fkeytab fkey;
1728     static int fkeycp;
1729     scr_stat *scp;
1730     u_char *p;
1731     int cur_mode;
1732     int c;
1733
1734     syscons_lock();
1735     /* assert(sc_console != NULL) */
1736
1737     /* 
1738      * Stop the screen saver and update the screen if necessary.
1739      * What if we have been running in the screen saver code... XXX
1740      */
1741     sc_touch_scrn_saver();
1742     scp = sc_console->sc->cur_scp;      /* XXX */
1743     sccnupdate(scp);
1744     syscons_unlock();
1745
1746     if (fkeycp < fkey.len) {
1747         return fkey.str[fkeycp++];
1748     }
1749
1750     if (scp->sc->kbd == NULL) {
1751         return -1;
1752     }
1753
1754     /* 
1755      * Make sure the keyboard is accessible even when the kbd device
1756      * driver is disabled.
1757      */
1758     crit_enter();
1759     kbd_enable(scp->sc->kbd);
1760
1761     /* we shall always use the keyboard in the XLATE mode here */
1762     cur_mode = scp->kbd_mode;
1763     scp->kbd_mode = K_XLATE;
1764     kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
1765
1766     kbd_poll(scp->sc->kbd, TRUE);
1767     c = scgetc(scp->sc, SCGETC_CN | flags);
1768     kbd_poll(scp->sc->kbd, FALSE);
1769
1770     scp->kbd_mode = cur_mode;
1771     kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
1772     kbd_disable(scp->sc->kbd);
1773     crit_exit();
1774
1775     switch (KEYFLAGS(c)) {
1776     case 0:     /* normal char */
1777         return KEYCHAR(c);
1778     case FKEY:  /* function key */
1779         p = kbd_get_fkeystr(scp->sc->kbd, KEYCHAR(c), (size_t *)&fkeycp);
1780         fkey.len = fkeycp;
1781         if ((p != NULL) && (fkey.len > 0)) {
1782             bcopy(p, fkey.str, fkey.len);
1783             fkeycp = 1;
1784             return fkey.str[0];
1785         }
1786         return c;       /* XXX */
1787     case NOKEY:
1788     case ERRKEY:
1789     default:
1790         return -1;
1791     }
1792     /* NOT REACHED */
1793 }
1794
1795 static void
1796 sccnupdate(scr_stat *scp)
1797 {
1798     /* this is a cut-down version of scrn_timer()... */
1799
1800     if (scp->sc->font_loading_in_progress || scp->sc->videoio_in_progress) {
1801         return;
1802     }
1803
1804     if (debugger > 0 || panicstr || shutdown_in_progress) {
1805         sc_touch_scrn_saver();
1806     } else if (scp != scp->sc->cur_scp) {
1807         return;
1808     }
1809
1810     if (!run_scrn_saver)
1811         scp->sc->flags &= ~SC_SCRN_IDLE;
1812 #if NSPLASH > 0
1813     /*
1814      * This is a hard path, we cannot call stop_scrn_saver() here.
1815      */
1816     if ((saver_mode != CONS_LKM_SAVER) || !(scp->sc->flags & SC_SCRN_IDLE))
1817         if (scp->sc->flags & SC_SCRN_BLANKED) {
1818             sc_touch_scrn_saver();
1819             /*stop_scrn_saver(scp->sc, current_saver);*/
1820         }
1821 #endif /* NSPLASH */
1822
1823     if (scp != scp->sc->cur_scp || scp->sc->blink_in_progress
1824         || scp->sc->switch_in_progress) {
1825         return;
1826     }
1827     /*
1828      * FIXME: unlike scrn_timer(), we call scrn_update() from here even
1829      * when write_in_progress is non-zero.  XXX
1830      */
1831
1832     if (!ISGRAPHSC(scp) && !(scp->sc->flags & SC_SCRN_BLANKED))
1833         scrn_update(scp, TRUE);
1834 }
1835
1836 static void
1837 scrn_timer(void *arg)
1838 {
1839     static int kbd_interval = 0;
1840     struct timeval tv;
1841     sc_softc_t *sc;
1842     scr_stat *scp;
1843     int again;
1844
1845     /*
1846      * Setup depending on who called us
1847      */
1848     again = (arg != NULL);
1849     if (arg != NULL) {
1850         sc = (sc_softc_t *)arg;
1851     } else if (sc_console != NULL) {
1852         sc = sc_console->sc;
1853     } else {
1854         return;
1855     }
1856
1857     /*
1858      * Don't do anything when we are performing some I/O operations.
1859      * (These are initiated by the frontend?)
1860      */
1861     if (sc->font_loading_in_progress || sc->videoio_in_progress) {
1862         if (again)
1863             callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
1864         return;
1865     }
1866
1867     /*
1868      * Try to allocate a keyboard automatically
1869      */
1870     if ((sc->kbd == NULL) && (sc->config & SC_AUTODETECT_KBD)) {
1871         if (++kbd_interval >= 25) {
1872             sc->keyboard = sc_allocate_keyboard(sc, -1);
1873             if (sc->keyboard >= 0) {
1874                 sc->kbd = kbd_get_keyboard(sc->keyboard);
1875                 kbd_ioctl(sc->kbd, KDSKBMODE,
1876                           (caddr_t)&sc->cur_scp->kbd_mode);
1877                 update_kbd_state(sc->cur_scp, sc->cur_scp->status,
1878                     LOCK_MASK, FALSE);
1879             }
1880             kbd_interval = 0;
1881         }
1882     }
1883
1884     /*
1885      * Should we stop the screen saver?  We need the syscons_lock
1886      * for most of this stuff.
1887      */
1888     getmicrouptime(&tv);
1889
1890     if (syscons_lock_nonblock() != 0) {
1891         /* failed to get the lock */
1892         if (again)
1893             callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
1894         return;
1895     }
1896     /* successful lock */
1897
1898     if (debugger > 0 || panicstr || shutdown_in_progress)
1899         sc_touch_scrn_saver();
1900     if (run_scrn_saver) {
1901         if (tv.tv_sec > sc->scrn_time_stamp + scrn_blank_time)
1902             sc->flags |= SC_SCRN_IDLE;
1903         else
1904             sc->flags &= ~SC_SCRN_IDLE;
1905     } else {
1906         sc->scrn_time_stamp = tv.tv_sec;
1907         sc->flags &= ~SC_SCRN_IDLE;
1908         if (scrn_blank_time > 0)
1909             run_scrn_saver = TRUE;
1910     }
1911 #if NSPLASH > 0
1912     if ((saver_mode != CONS_LKM_SAVER) || !(sc->flags & SC_SCRN_IDLE))
1913         if (sc->flags & SC_SCRN_BLANKED)
1914             stop_scrn_saver(sc, current_saver);
1915 #endif /* NSPLASH */
1916
1917     /* should we just return ? */
1918     if (sc->blink_in_progress || sc->switch_in_progress ||
1919         sc->write_in_progress)
1920     {
1921         syscons_unlock();
1922         if (again)
1923             callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
1924         return;
1925     }
1926
1927     /* Update the screen */
1928     scp = sc->cur_scp;          /* cur_scp may have changed... */
1929     if (!ISGRAPHSC(scp) && !(sc->flags & SC_SCRN_BLANKED))
1930         scrn_update(scp, TRUE);
1931
1932 #if NSPLASH > 0
1933     /* should we activate the screen saver? */
1934     if ((saver_mode == CONS_LKM_SAVER) && (sc->flags & SC_SCRN_IDLE))
1935         if (!ISGRAPHSC(scp) || (sc->flags & SC_SCRN_BLANKED))
1936             (*current_saver)(sc, TRUE);
1937 #endif /* NSPLASH */
1938
1939     syscons_unlock();
1940     if (again)
1941         callout_reset(&sc->scrn_timer_ch, hz / 25, scrn_timer, sc);
1942 }
1943
1944 static int
1945 and_region(int *s1, int *e1, int s2, int e2)
1946 {
1947     if (*e1 < s2 || e2 < *s1)
1948         return FALSE;
1949     *s1 = imax(*s1, s2);
1950     *e1 = imin(*e1, e2);
1951     return TRUE;
1952 }
1953
1954 static void 
1955 scrn_update(scr_stat *scp, int show_cursor)
1956 {
1957     int start;
1958     int end;
1959     int s;
1960     int e;
1961
1962     /* assert(scp == scp->sc->cur_scp) */
1963
1964     ++scp->sc->videoio_in_progress;
1965
1966 #ifndef SC_NO_CUTPASTE
1967     /* remove the previous mouse pointer image if necessary */
1968     if (scp->status & MOUSE_VISIBLE) {
1969         s = scp->mouse_pos;
1970         e = scp->mouse_pos + scp->xsize + 1;
1971         if ((scp->status & (MOUSE_MOVED | MOUSE_HIDDEN))
1972             || and_region(&s, &e, scp->start, scp->end)
1973             || ((scp->status & CURSOR_ENABLED) && 
1974                 (scp->cursor_pos != scp->cursor_oldpos) &&
1975                 (and_region(&s, &e, scp->cursor_pos, scp->cursor_pos)
1976                  || and_region(&s, &e, scp->cursor_oldpos, scp->cursor_oldpos)))) {
1977             sc_remove_mouse_image(scp);
1978             if (scp->end >= scp->xsize*scp->ysize)
1979                 scp->end = scp->xsize*scp->ysize - 1;
1980         }
1981     }
1982 #endif /* !SC_NO_CUTPASTE */
1983
1984 #if 1
1985     /* debug: XXX */
1986     if (scp->end >= scp->xsize*scp->ysize) {
1987         kprintf("scrn_update(): scp->end %d > size_of_screen!!\n", scp->end);
1988         scp->end = scp->xsize*scp->ysize - 1;
1989     }
1990     if (scp->start < 0) {
1991         kprintf("scrn_update(): scp->start %d < 0\n", scp->start);
1992         scp->start = 0;
1993     }
1994 #endif
1995
1996     /* update screen image */
1997     if (scp->start <= scp->end)  {
1998         if (scp->mouse_cut_end >= 0) {
1999             /* there is a marked region for cut & paste */
2000             if (scp->mouse_cut_start <= scp->mouse_cut_end) {
2001                 start = scp->mouse_cut_start;
2002                 end = scp->mouse_cut_end;
2003             } else {
2004                 start = scp->mouse_cut_end;
2005                 end = scp->mouse_cut_start - 1;
2006             }
2007             s = start;
2008             e = end;
2009             /* does the cut-mark region overlap with the update region? */
2010             if (and_region(&s, &e, scp->start, scp->end)) {
2011                 (*scp->rndr->draw)(scp, s, e - s + 1, TRUE);
2012                 s = 0;
2013                 e = start - 1;
2014                 if (and_region(&s, &e, scp->start, scp->end))
2015                     (*scp->rndr->draw)(scp, s, e - s + 1, FALSE);
2016                 s = end + 1;
2017                 e = scp->xsize*scp->ysize - 1;
2018                 if (and_region(&s, &e, scp->start, scp->end))
2019                     (*scp->rndr->draw)(scp, s, e - s + 1, FALSE);
2020             } else {
2021                 (*scp->rndr->draw)(scp, scp->start,
2022                                    scp->end - scp->start + 1, FALSE);
2023             }
2024         } else {
2025             (*scp->rndr->draw)(scp, scp->start,
2026                                scp->end - scp->start + 1, FALSE);
2027         }
2028     }
2029
2030     /* we are not to show the cursor and the mouse pointer... */
2031     if (!show_cursor) {
2032         scp->end = 0;
2033         scp->start = scp->xsize*scp->ysize - 1;
2034         --scp->sc->videoio_in_progress;
2035         return;
2036     }
2037
2038     /* update cursor image */
2039     if (scp->status & CURSOR_ENABLED) {
2040         s = scp->start;
2041         e = scp->end;
2042         /* did cursor move since last time ? */
2043         if (scp->cursor_pos != scp->cursor_oldpos) {
2044             /* do we need to remove old cursor image ? */
2045             if (!and_region(&s, &e, scp->cursor_oldpos, scp->cursor_oldpos))
2046                 sc_remove_cursor_image(scp);
2047             sc_draw_cursor_image(scp);
2048         } else {
2049             if (and_region(&s, &e, scp->cursor_pos, scp->cursor_pos))
2050                 /* cursor didn't move, but has been overwritten */
2051                 sc_draw_cursor_image(scp);
2052             else if (scp->sc->flags & SC_BLINK_CURSOR)
2053                 /* if it's a blinking cursor, update it */
2054                 (*scp->rndr->blink_cursor)(scp, scp->cursor_pos,
2055                                            sc_inside_cutmark(scp,
2056                                                scp->cursor_pos));
2057         }
2058     }
2059
2060 #ifndef SC_NO_CUTPASTE
2061     /* update "pseudo" mouse pointer image */
2062     if (scp->sc->flags & SC_MOUSE_ENABLED) {
2063         if (!(scp->status & (MOUSE_VISIBLE | MOUSE_HIDDEN))) {
2064             scp->status &= ~MOUSE_MOVED;
2065             sc_draw_mouse_image(scp);
2066         }
2067     }
2068 #endif /* SC_NO_CUTPASTE */
2069
2070     scp->end = 0;
2071     scp->start = scp->xsize*scp->ysize - 1;
2072
2073     --scp->sc->videoio_in_progress;
2074 }
2075
2076 #if NSPLASH > 0
2077 static int
2078 scsplash_callback(int event, void *arg)
2079 {
2080     sc_softc_t *sc;
2081     int error;
2082
2083     sc = (sc_softc_t *)arg;
2084
2085     switch (event) {
2086     case SPLASH_INIT:
2087         if (add_scrn_saver(scsplash_saver) == 0) {
2088             sc->flags &= ~SC_SAVER_FAILED;
2089             run_scrn_saver = TRUE;
2090             if (cold && !(boothowto & (RB_VERBOSE | RB_CONFIG))) {
2091                 scsplash_stick(TRUE);
2092                 (*current_saver)(sc, TRUE);
2093             }
2094         }
2095         return 0;
2096
2097     case SPLASH_TERM:
2098         if (current_saver == scsplash_saver) {
2099             scsplash_stick(FALSE);
2100             error = remove_scrn_saver(scsplash_saver);
2101             if (error) {
2102                 return error;
2103             }
2104         }
2105         return 0;
2106
2107     default:
2108         return EINVAL;
2109     }
2110 }
2111
2112 static void
2113 scsplash_saver(sc_softc_t *sc, int show)
2114 {
2115     static int busy = FALSE;
2116     scr_stat *scp;
2117
2118     if (busy)
2119         return;
2120     busy = TRUE;
2121
2122     scp = sc->cur_scp;
2123     if (show) {
2124         if (!(sc->flags & SC_SAVER_FAILED)) {
2125             if (!(sc->flags & SC_SCRN_BLANKED))
2126                 set_scrn_saver_mode(scp, -1, NULL, 0);
2127             switch (splash(sc->adp, TRUE)) {
2128             case 0:             /* succeeded */
2129                 break;
2130             case EAGAIN:        /* try later */
2131                 restore_scrn_saver_mode(scp, FALSE);
2132                 sc_touch_scrn_saver();          /* XXX */
2133                 break;
2134             default:
2135                 sc->flags |= SC_SAVER_FAILED;
2136                 scsplash_stick(FALSE);
2137                 restore_scrn_saver_mode(scp, TRUE);
2138                 kprintf("scsplash_saver(): failed to put up the image\n");
2139                 break;
2140             }
2141         }
2142     } else if (!sticky_splash) {
2143         if ((sc->flags & SC_SCRN_BLANKED) && (splash(sc->adp, FALSE) == 0))
2144             restore_scrn_saver_mode(scp, TRUE);
2145     }
2146     busy = FALSE;
2147 }
2148
2149 static int
2150 add_scrn_saver(void (*this_saver)(sc_softc_t *, int))
2151 {
2152 #if 0
2153     int error;
2154
2155     if (current_saver != none_saver) {
2156         error = remove_scrn_saver(current_saver);
2157         if (error)
2158             return error;
2159     }
2160 #endif
2161     if (current_saver != none_saver) {
2162         return EBUSY;
2163     }
2164
2165     run_scrn_saver = FALSE;
2166     saver_mode = CONS_LKM_SAVER;
2167     current_saver = this_saver;
2168     return 0;
2169 }
2170
2171 static int
2172 remove_scrn_saver(void (*this_saver)(sc_softc_t *, int))
2173 {
2174     if (current_saver != this_saver)
2175         return EINVAL;
2176
2177 #if 0
2178     /*
2179      * In order to prevent `current_saver' from being called by
2180      * the timeout routine `scrn_timer()' while we manipulate 
2181      * the saver list, we shall set `current_saver' to `none_saver' 
2182      * before stopping the current saver, rather than blocking by `splXX()'.
2183      */
2184     current_saver = none_saver;
2185     if (scrn_blanked)
2186         stop_scrn_saver(this_saver);
2187 #endif
2188     /* unblank all blanked screens */
2189     wait_scrn_saver_stop(NULL);
2190     if (scrn_blanked) {
2191         return EBUSY;
2192     }
2193
2194     current_saver = none_saver;
2195     return 0;
2196 }
2197
2198 static int
2199 set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border)
2200 {
2201
2202     /* assert(scp == scp->sc->cur_scp) */
2203     crit_enter();
2204     if (!ISGRAPHSC(scp))
2205         sc_remove_cursor_image(scp);
2206     scp->splash_save_mode = scp->mode;
2207     scp->splash_save_status = scp->status & (GRAPHICS_MODE | PIXEL_MODE);
2208     scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE);
2209     scp->status |= (UNKNOWN_MODE | SAVER_RUNNING);
2210     scp->sc->flags |= SC_SCRN_BLANKED;
2211     ++scrn_blanked;
2212     crit_exit();
2213     if (mode < 0) {
2214         return 0;
2215     }
2216     scp->mode = mode;
2217     if (set_mode(scp) == 0) {
2218         if (scp->sc->adp->va_info.vi_flags & V_INFO_GRAPHICS)
2219             scp->status |= GRAPHICS_MODE;
2220 #ifndef SC_NO_PALETTE_LOADING
2221         if (pal != NULL)
2222             load_palette(scp->sc->adp, pal);
2223 #endif
2224         sc_set_border(scp, border);
2225         return 0;
2226     } else {
2227         crit_enter();
2228         scp->mode = scp->splash_save_mode;
2229         scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING);
2230         scp->status |= scp->splash_save_status;
2231         crit_exit();
2232         return 1;
2233     }
2234     /* NOTREACHED */
2235 }
2236
2237 static int
2238 restore_scrn_saver_mode(scr_stat *scp, int changemode)
2239 {
2240     int mode;
2241     int status;
2242
2243     /* assert(scp == scp->sc->cur_scp) */
2244     crit_enter();
2245     mode = scp->mode;
2246     status = scp->status;
2247     scp->mode = scp->splash_save_mode;
2248     scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING);
2249     scp->status |= scp->splash_save_status;
2250     scp->sc->flags &= ~SC_SCRN_BLANKED;
2251     if (!changemode) {
2252         if (!ISGRAPHSC(scp))
2253             sc_draw_cursor_image(scp);
2254         --scrn_blanked;
2255         crit_exit();
2256         return 0;
2257     }
2258     if (set_mode(scp) == 0) {
2259 #ifndef SC_NO_PALETTE_LOADING
2260         load_palette(scp->sc->adp, scp->sc->palette);
2261 #endif
2262         --scrn_blanked;
2263         crit_exit();
2264         return 0;
2265     } else {
2266         scp->mode = mode;
2267         scp->status = status;
2268         crit_exit();
2269         return 1;
2270     }
2271     /* NOTREACHED */
2272 }
2273
2274 static void
2275 stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int))
2276 {
2277     (*saver)(sc, FALSE);
2278     run_scrn_saver = FALSE;
2279     /* the screen saver may have chosen not to stop after all... */
2280     if (sc->flags & SC_SCRN_BLANKED) {
2281         return;
2282     }
2283
2284     mark_all(sc->cur_scp);
2285     if (sc->delayed_next_scr)
2286         sc_switch_scr(sc, sc->delayed_next_scr - 1);
2287     wakeup((caddr_t)&scrn_blanked);
2288 }
2289
2290 static int
2291 wait_scrn_saver_stop(sc_softc_t *sc)
2292 {
2293     int error = 0;
2294
2295     while (scrn_blanked > 0) {
2296         run_scrn_saver = FALSE;
2297         if (sc && !(sc->flags & SC_SCRN_BLANKED)) {
2298             error = 0;
2299             break;
2300         }
2301         error = tsleep((caddr_t)&scrn_blanked, PCATCH, "scrsav", 0);
2302         /* May return ERESTART */
2303         if (error)
2304                 break;
2305     }
2306     run_scrn_saver = FALSE;
2307     return error;
2308 }
2309 #endif /* NSPLASH */
2310
2311 void
2312 sc_touch_scrn_saver(void)
2313 {
2314     scsplash_stick(FALSE);
2315     run_scrn_saver = FALSE;
2316 }
2317
2318 int
2319 sc_switch_scr(sc_softc_t *sc, u_int next_scr)
2320 {
2321     scr_stat *cur_scp;
2322     struct tty *tp;
2323
2324     DPRINTF(5, ("sc0: sc_switch_scr() %d ", next_scr + 1));
2325
2326     /* prevent switch if previously requested */
2327     if (sc->flags & SC_SCRN_VTYLOCK) {
2328             sc_bell(sc->cur_scp, sc->cur_scp->bell_pitch,
2329                 sc->cur_scp->bell_duration);
2330             return EPERM;
2331     }
2332
2333     /* delay switch if the screen is blanked or being updated */
2334     if ((sc->flags & SC_SCRN_BLANKED) || sc->write_in_progress
2335         || sc->blink_in_progress || sc->videoio_in_progress) {
2336         sc->delayed_next_scr = next_scr + 1;
2337         sc_touch_scrn_saver();
2338         DPRINTF(5, ("switch delayed\n"));
2339         return 0;
2340     }
2341
2342     cur_scp = sc->cur_scp;
2343
2344     /*
2345      * we are in the middle of the vty switching process...
2346      *
2347      * This may be in the console path, we can only deal with this case
2348      * if the proc_token is available non-blocking.
2349      */
2350     if (sc->switch_in_progress &&
2351         (cur_scp->smode.mode == VT_PROCESS) &&
2352         cur_scp->proc &&
2353         lwkt_trytoken(&proc_token)) {
2354
2355         if (cur_scp->proc != pfindn(cur_scp->pid)) {
2356             /* 
2357              * The controlling process has died!!.  Do some clean up.
2358              * NOTE:`cur_scp->proc' and `cur_scp->smode.mode' 
2359              * are not reset here yet; they will be cleared later.
2360              */
2361             DPRINTF(5, ("cur_scp controlling process %d died, ",
2362                cur_scp->pid));
2363             if (cur_scp->status & SWITCH_WAIT_REL) {
2364                 /*
2365                  * Force the previous switch to finish, but return now 
2366                  * with error.
2367                  *
2368                  */
2369                 DPRINTF(5, ("reset WAIT_REL, "));
2370                 finish_vt_rel(cur_scp, TRUE);
2371                 DPRINTF(5, ("finishing previous switch\n"));
2372                 lwkt_reltoken(&proc_token);
2373                 return EINVAL;
2374             } else if (cur_scp->status & SWITCH_WAIT_ACQ) {
2375                 /* let's assume screen switch has been completed. */
2376                 DPRINTF(5, ("reset WAIT_ACQ, "));
2377                 finish_vt_acq(cur_scp);
2378             } else {
2379                 /* 
2380                  * We are in between screen release and acquisition, and
2381                  * reached here via scgetc() or scrn_timer() which has 
2382                  * interrupted exchange_scr(). Don't do anything stupid.
2383                  */
2384                 DPRINTF(5, ("waiting nothing, "));
2385             }
2386         } else {
2387             /*
2388              * The controlling process is alive, but not responding... 
2389              * It is either buggy or it may be just taking time.
2390              * The following code is a gross kludge to cope with this
2391              * problem for which there is no clean solution. XXX
2392              */
2393             if (cur_scp->status & SWITCH_WAIT_REL) {
2394                 switch (sc->switch_in_progress++) {
2395                 case 1:
2396                     break;
2397                 case 2:
2398                     DPRINTF(5, ("sending relsig again, "));
2399                     signal_vt_rel(cur_scp);
2400                     break;
2401                 case 3:
2402                     break;
2403                 case 4:
2404                 default:
2405                     /*
2406                      * Act as if the controlling program returned
2407                      * VT_FALSE.
2408                      *
2409                      */
2410                     DPRINTF(5, ("force reset WAIT_REL, "));
2411                     finish_vt_rel(cur_scp, FALSE);
2412                     DPRINTF(5, ("act as if VT_FALSE was seen\n"));
2413                     lwkt_reltoken(&proc_token);
2414                     return EINVAL;
2415                 }
2416             } else if (cur_scp->status & SWITCH_WAIT_ACQ) {
2417                 switch (sc->switch_in_progress++) {
2418                 case 1:
2419                     break;
2420                 case 2:
2421                     DPRINTF(5, ("sending acqsig again, "));
2422                     signal_vt_acq(cur_scp);
2423                     break;
2424                 case 3:
2425                     break;
2426                 case 4:
2427                 default:
2428                      /* clear the flag and finish the previous switch */
2429                     DPRINTF(5, ("force reset WAIT_ACQ, "));
2430                     finish_vt_acq(cur_scp);
2431                     break;
2432                 }
2433             }
2434         }
2435         lwkt_reltoken(&proc_token);
2436     }
2437
2438     /*
2439      * Return error if an invalid argument is given, or vty switch
2440      * is still in progress.
2441      */
2442     if ((next_scr < sc->first_vty) || (next_scr >= sc->first_vty + sc->vtys)
2443         || sc->switch_in_progress) {
2444         sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
2445         DPRINTF(5, ("error 1\n"));
2446         return EINVAL;
2447     }
2448
2449     /*
2450      * Don't allow switching away from the graphics mode vty
2451      * if the switch mode is VT_AUTO, unless the next vty is the same 
2452      * as the current or the current vty has been closed (but showing).
2453      */
2454     tp = VIRTUAL_TTY(sc, cur_scp->index);
2455     if ((cur_scp->index != next_scr)
2456         && ISTTYOPEN(tp)
2457         && (cur_scp->smode.mode == VT_AUTO)
2458         && ISGRAPHSC(cur_scp)) {
2459         sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
2460         DPRINTF(5, ("error, graphics mode\n"));
2461         return EINVAL;
2462     }
2463
2464     /*
2465      * Is the wanted vty open? Don't allow switching to a closed vty.
2466      * If we are in DDB, don't switch to a vty in the VT_PROCESS mode.
2467      * Note that we always allow the user to switch to the kernel 
2468      * console even if it is closed.
2469      */
2470     if ((sc_console == NULL) || (next_scr != sc_console->index)) {
2471         tp = VIRTUAL_TTY(sc, next_scr);
2472         if (!ISTTYOPEN(tp)) {
2473             sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
2474             DPRINTF(5, ("error 2, requested vty isn't open!\n"));
2475             return EINVAL;
2476         }
2477         if ((debugger > 0) && (SC_STAT(tp->t_dev)->smode.mode == VT_PROCESS)) {
2478             DPRINTF(5, ("error 3, requested vty is in the VT_PROCESS mode\n"));
2479             return EINVAL;
2480         }
2481     }
2482
2483     /* this is the start of vty switching process... */
2484     ++sc->switch_in_progress;
2485     sc->delayed_next_scr = 0;
2486     sc->old_scp = cur_scp;
2487     sc->new_scp = SC_STAT(SC_DEV(sc, next_scr));
2488     if (sc->new_scp == sc->old_scp) {
2489         sc->switch_in_progress = 0;
2490         wakeup((caddr_t)&sc->new_scp->smode);
2491         DPRINTF(5, ("switch done (new == old)\n"));
2492         return 0;
2493     }
2494
2495     /* has controlling process died? */
2496     vt_proc_alive(sc->old_scp);
2497     vt_proc_alive(sc->new_scp);
2498
2499     /* wait for the controlling process to release the screen, if necessary */
2500     if (signal_vt_rel(sc->old_scp)) {
2501         return 0;
2502     }
2503
2504     /* go set up the new vty screen */
2505     exchange_scr(sc);
2506
2507     /* wake up processes waiting for this vty */
2508     wakeup((caddr_t)&sc->cur_scp->smode);
2509
2510     /* wait for the controlling process to acknowledge, if necessary */
2511     if (signal_vt_acq(sc->cur_scp)) {
2512         return 0;
2513     }
2514
2515     sc->switch_in_progress = 0;
2516     if (sc->unit == sc_console_unit)
2517         cons_unavail = FALSE;
2518     DPRINTF(5, ("switch done\n"));
2519
2520     return 0;
2521 }
2522
2523 static void
2524 do_switch_scr(sc_softc_t *sc)
2525 {
2526     lwkt_gettoken(&tty_token);
2527     vt_proc_alive(sc->new_scp);
2528
2529     exchange_scr(sc);
2530     /* sc->cur_scp == sc->new_scp */
2531     wakeup((caddr_t)&sc->cur_scp->smode);
2532
2533     /* wait for the controlling process to acknowledge, if necessary */
2534     if (!signal_vt_acq(sc->cur_scp)) {
2535         sc->switch_in_progress = 0;
2536         if (sc->unit == sc_console_unit)
2537             cons_unavail = FALSE;
2538     }
2539     lwkt_reltoken(&tty_token);
2540 }
2541
2542 static int
2543 vt_proc_alive(scr_stat *scp)
2544 {
2545     lwkt_gettoken(&tty_token);
2546     lwkt_gettoken(&proc_token);
2547     if (scp->proc) {
2548         if (scp->proc == pfindn(scp->pid)) {
2549             lwkt_reltoken(&proc_token);
2550             lwkt_reltoken(&tty_token);
2551             return TRUE;
2552         }
2553         scp->proc = NULL;
2554         scp->smode.mode = VT_AUTO;
2555         DPRINTF(5, ("vt controlling process %d died\n", scp->pid));
2556     }
2557     lwkt_reltoken(&proc_token);
2558     lwkt_reltoken(&tty_token);
2559     return FALSE;
2560 }
2561
2562 static int
2563 signal_vt_rel(scr_stat *scp)
2564 {
2565     lwkt_gettoken(&tty_token);
2566     if (scp->smode.mode != VT_PROCESS) {
2567         lwkt_reltoken(&tty_token);
2568         return FALSE;
2569     }
2570     scp->status |= SWITCH_WAIT_REL;
2571     lwkt_gettoken(&proc_token);
2572     ksignal(scp->proc, scp->smode.relsig);
2573     lwkt_reltoken(&proc_token);
2574     DPRINTF(5, ("sending relsig to %d\n", scp->pid));
2575     lwkt_reltoken(&tty_token);
2576     return TRUE;
2577 }
2578
2579 static int
2580 signal_vt_acq(scr_stat *scp)
2581 {
2582     lwkt_gettoken(&tty_token);
2583     if (scp->smode.mode != VT_PROCESS) {
2584         lwkt_reltoken(&tty_token);
2585         return FALSE;
2586     }
2587     if (scp->sc->unit == sc_console_unit)
2588         cons_unavail = TRUE;
2589     scp->status |= SWITCH_WAIT_ACQ;
2590     lwkt_gettoken(&proc_token);
2591     ksignal(scp->proc, scp->smode.acqsig);
2592     lwkt_reltoken(&proc_token);
2593     DPRINTF(5, ("sending acqsig to %d\n", scp->pid));
2594     lwkt_reltoken(&tty_token);
2595     return TRUE;
2596 }
2597
2598 static int
2599 finish_vt_rel(scr_stat *scp, int release)
2600 {
2601     lwkt_gettoken(&tty_token);
2602     if (scp == scp->sc->old_scp && scp->status & SWITCH_WAIT_REL) {
2603         scp->status &= ~SWITCH_WAIT_REL;
2604         if (release)
2605             do_switch_scr(scp->sc);
2606         else
2607             scp->sc->switch_in_progress = 0;
2608         lwkt_reltoken(&tty_token);
2609         return 0;
2610     }
2611     lwkt_reltoken(&tty_token);
2612     return EINVAL;
2613 }
2614
2615 static int
2616 finish_vt_acq(scr_stat *scp)
2617 {
2618     lwkt_gettoken(&tty_token);
2619     if (scp == scp->sc->new_scp && scp->status & SWITCH_WAIT_ACQ) {
2620         scp->status &= ~SWITCH_WAIT_ACQ;
2621         scp->sc->switch_in_progress = 0;
2622         lwkt_reltoken(&tty_token);
2623         return 0;
2624     }
2625     lwkt_reltoken(&tty_token);
2626     return EINVAL;
2627 }
2628
2629 static void
2630 exchange_scr(sc_softc_t *sc)
2631 {
2632     scr_stat *scp;
2633
2634     lwkt_gettoken(&tty_token);
2635     /* save the current state of video and keyboard */
2636     sc_move_cursor(sc->old_scp, sc->old_scp->xpos, sc->old_scp->ypos);
2637     if (!ISGRAPHSC(sc->old_scp))
2638         sc_remove_cursor_image(sc->old_scp);
2639     if (sc->old_scp->kbd_mode == K_XLATE)
2640         save_kbd_state(sc->old_scp, TRUE);
2641
2642     /* set up the video for the new screen */
2643     scp = sc->cur_scp = sc->new_scp;
2644     if (sc->old_scp->mode != scp->mode || ISUNKNOWNSC(sc->old_scp))
2645         set_mode(scp);
2646     else
2647         sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
2648                     (void *)sc->adp->va_window, FALSE);
2649     scp->status |= MOUSE_HIDDEN;
2650     sc_move_cursor(scp, scp->xpos, scp->ypos);
2651     if (!ISGRAPHSC(scp))
2652         sc_set_cursor_image(scp);
2653 #ifndef SC_NO_PALETTE_LOADING
2654     if (ISGRAPHSC(sc->old_scp))
2655         load_palette(sc->adp, sc->palette);
2656 #endif
2657     sc_set_border(scp, scp->border);
2658
2659     /* set up the keyboard for the new screen */
2660     if (sc->old_scp->kbd_mode != scp->kbd_mode)
2661         kbd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
2662     update_kbd_state(scp, scp->status, LOCK_MASK, TRUE);
2663
2664     mark_all(scp);
2665     lwkt_reltoken(&tty_token);
2666 }
2667
2668 static void
2669 sc_puts(scr_stat *scp, u_char *buf, int len)
2670 {
2671 #if NSPLASH > 0
2672     /* make screensaver happy */
2673     if (!sticky_splash && scp == scp->sc->cur_scp)
2674         run_scrn_saver = FALSE;
2675 #endif
2676
2677     if (scp->tsw)
2678         (*scp->tsw->te_puts)(scp, buf, len);
2679
2680     if (scp->sc->delayed_next_scr)
2681         sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
2682
2683 }
2684
2685 void
2686 sc_draw_cursor_image(scr_stat *scp)
2687 {
2688     /* assert(scp == scp->sc->cur_scp); */
2689     ++scp->sc->videoio_in_progress;
2690     (*scp->rndr->draw_cursor)(scp, scp->cursor_pos,
2691                               scp->sc->flags & SC_BLINK_CURSOR, TRUE,
2692                               sc_inside_cutmark(scp, scp->cursor_pos));
2693     scp->cursor_oldpos = scp->cursor_pos;
2694     --scp->sc->videoio_in_progress;
2695 }
2696
2697 void
2698 sc_remove_cursor_image(scr_stat *scp)
2699 {
2700     /* assert(scp == scp->sc->cur_scp); */
2701     ++scp->sc->videoio_in_progress;
2702     (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos,
2703                               scp->sc->flags & SC_BLINK_CURSOR, FALSE,
2704                               sc_inside_cutmark(scp, scp->cursor_oldpos));
2705     --scp->sc->videoio_in_progress;
2706 }
2707
2708 static void
2709 update_cursor_image(scr_stat *scp)
2710 {
2711     int blink;
2712
2713     if (scp->sc->flags & SC_CHAR_CURSOR) {
2714         scp->cursor_base = imax(0, scp->sc->cursor_base);
2715         scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
2716     } else {
2717         scp->cursor_base = 0;
2718         scp->cursor_height = scp->font_size;
2719     }
2720     blink = scp->sc->flags & SC_BLINK_CURSOR;
2721
2722     /* assert(scp == scp->sc->cur_scp); */
2723     ++scp->sc->videoio_in_progress;
2724     (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos, blink, FALSE, 
2725                               sc_inside_cutmark(scp, scp->cursor_pos));
2726     (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height, blink);
2727     (*scp->rndr->draw_cursor)(scp, scp->cursor_pos, blink, TRUE, 
2728                               sc_inside_cutmark(scp, scp->cursor_pos));
2729     --scp->sc->videoio_in_progress;
2730 }
2731
2732 void
2733 sc_set_cursor_image(scr_stat *scp)
2734 {
2735     if (scp->sc->flags & SC_CHAR_CURSOR) {
2736         scp->cursor_base = imax(0, scp->sc->cursor_base);
2737         scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
2738     } else {
2739         scp->cursor_base = 0;
2740         scp->cursor_height = scp->font_size;
2741     }
2742
2743     /* assert(scp == scp->sc->cur_scp); */
2744     ++scp->sc->videoio_in_progress;
2745     (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height,
2746                              scp->sc->flags & SC_BLINK_CURSOR);
2747     --scp->sc->videoio_in_progress;
2748 }
2749
2750 static void
2751 scinit(int unit, int flags)
2752 {
2753     /*
2754      * When syscons is being initialized as the kernel console, malloc()
2755      * is not yet functional, because various kernel structures has not been
2756      * fully initialized yet.  Therefore, we need to declare the following
2757      * static buffers for the console.  This is less than ideal, 
2758      * but is necessry evil for the time being.  XXX
2759      */
2760     static scr_stat main_console;
2761     static u_short sc_buffer[ROW*COL];  /* XXX */
2762 #ifndef SC_NO_FONT_LOADING
2763     static u_char font_8[256*8];
2764     static u_char font_14[256*14];
2765     static u_char font_16[256*16];
2766 #endif
2767
2768     sc_softc_t *sc;
2769     scr_stat *scp;
2770     video_adapter_t *adp;
2771     int col;
2772     int row;
2773     int i;
2774
2775     /* one time initialization */
2776     if (init_done == COLD)
2777         sc_get_bios_values(&bios_value);
2778     init_done = WARM;
2779
2780     /*
2781      * Allocate resources.  Even if we are being called for the second
2782      * time, we must allocate them again, because they might have 
2783      * disappeared...
2784      */
2785     sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
2786     adp = NULL;
2787     if (sc->adapter >= 0) {
2788         vid_release(sc->adp, (void *)&sc->adapter);
2789         adp = sc->adp;
2790         sc->adp = NULL;
2791     }
2792     if (sc->keyboard >= 0) {
2793         DPRINTF(5, ("sc%d: releasing kbd%d\n", unit, sc->keyboard));
2794         i = kbd_release(sc->kbd, (void *)&sc->keyboard);
2795         DPRINTF(5, ("sc%d: kbd_release returned %d\n", unit, i));
2796         if (sc->kbd != NULL) {
2797             DPRINTF(5, ("sc%d: kbd != NULL!, index:%d, unit:%d, flags:0x%x\n",
2798                 unit, sc->kbd->kb_index, sc->kbd->kb_unit, sc->kbd->kb_flags));
2799         }
2800         sc->kbd = NULL;
2801     }
2802     sc->adapter = vid_allocate("*", unit, (void *)&sc->adapter);
2803     sc->adp = vid_get_adapter(sc->adapter);
2804     /* assert((sc->adapter >= 0) && (sc->adp != NULL)) */
2805     sc->keyboard = sc_allocate_keyboard(sc, unit);
2806     DPRINTF(1, ("sc%d: keyboard %d\n", unit, sc->keyboard));
2807     sc->kbd = kbd_get_keyboard(sc->keyboard);
2808     if (sc->kbd != NULL) {
2809         DPRINTF(1, ("sc%d: kbd index:%d, unit:%d, flags:0x%x\n",
2810                 unit, sc->kbd->kb_index, sc->kbd->kb_unit, sc->kbd->kb_flags));
2811     }
2812
2813     if (!(sc->flags & SC_INIT_DONE) || (adp != sc->adp)) {
2814
2815         sc->initial_mode = sc->adp->va_initial_mode;
2816
2817 #ifndef SC_NO_FONT_LOADING
2818         if (flags & SC_KERNEL_CONSOLE) {
2819             sc->font_8 = font_8;
2820             sc->font_14 = font_14;
2821             sc->font_16 = font_16;
2822         } else if (sc->font_8 == NULL) {
2823             /* assert(sc_malloc) */
2824             sc->font_8 = kmalloc(sizeof(font_8), M_SYSCONS, M_WAITOK);
2825             sc->font_14 = kmalloc(sizeof(font_14), M_SYSCONS, M_WAITOK);
2826             sc->font_16 = kmalloc(sizeof(font_16), M_SYSCONS, M_WAITOK);
2827         }
2828 #endif
2829
2830         lwkt_gettoken(&tty_token);
2831         /* extract the hardware cursor location and hide the cursor for now */
2832         (*vidsw[sc->adapter]->read_hw_cursor)(sc->adp, &col, &row);
2833         (*vidsw[sc->adapter]->set_hw_cursor)(sc->adp, -1, -1);
2834         lwkt_reltoken(&tty_token);
2835
2836         /* set up the first console */
2837         sc->first_vty = unit*MAXCONS;
2838         sc->vtys = MAXCONS;             /* XXX: should be configurable */
2839         if (flags & SC_KERNEL_CONSOLE) {
2840             scp = &main_console;
2841             sc->console_scp = scp;
2842             init_scp(sc, sc->first_vty, scp);
2843             sc_vtb_init(&scp->vtb, VTB_MEMORY, scp->xsize, scp->ysize,
2844                         (void *)sc_buffer, FALSE);
2845             if (sc_init_emulator(scp, SC_DFLT_TERM))
2846                 sc_init_emulator(scp, "*");
2847             (*scp->tsw->te_default_attr)(scp,
2848                                          kernel_default.std_color,
2849                                          kernel_default.rev_color);
2850         } else {
2851             /* assert(sc_malloc) */
2852             sc->dev = kmalloc(sizeof(cdev_t)*sc->vtys, M_SYSCONS, M_WAITOK | M_ZERO);
2853
2854             sc->dev[0] = make_dev(&sc_ops, unit*MAXCONS, UID_ROOT, 
2855                                 GID_WHEEL, 0600, "ttyv%r", unit*MAXCONS);
2856
2857             sc->dev[0]->si_tty = ttymalloc(sc->dev[0]->si_tty);
2858             scp = alloc_scp(sc, sc->first_vty);
2859             sc->dev[0]->si_drv1 = scp;
2860         }
2861         sc->cur_scp = scp;
2862
2863         /* copy screen to temporary buffer */
2864         sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
2865                     (void *)scp->sc->adp->va_window, FALSE);
2866         if (ISTEXTSC(scp))
2867             sc_vtb_copy(&scp->scr, 0, &scp->vtb, 0, scp->xsize*scp->ysize);
2868
2869         /* move cursors to the initial positions */
2870         if (col >= scp->xsize)
2871             col = 0;
2872         if (row >= scp->ysize)
2873             row = scp->ysize - 1;
2874         scp->xpos = col;
2875         scp->ypos = row;
2876         scp->cursor_pos = scp->cursor_oldpos = row*scp->xsize + col;
2877         if (bios_value.cursor_end < scp->font_size)
2878             sc->cursor_base = scp->font_size - bios_value.cursor_end - 1;
2879         else
2880             sc->cursor_base = 0;
2881         i = bios_value.cursor_end - bios_value.cursor_start + 1;
2882         sc->cursor_height = imin(i, scp->font_size);
2883 #ifndef SC_NO_SYSMOUSE
2884         sc_mouse_move(scp, scp->xpixel/2, scp->ypixel/2);
2885 #endif
2886         if (!ISGRAPHSC(scp)) {
2887             sc_set_cursor_image(scp);
2888             sc_draw_cursor_image(scp);
2889         }
2890
2891         /* save font and palette */
2892 #ifndef SC_NO_FONT_LOADING
2893         sc->fonts_loaded = 0;
2894         if (ISFONTAVAIL(sc->adp->va_flags)) {
2895 #ifdef SC_DFLT_FONT
2896             bcopy(dflt_font_8, sc->font_8, sizeof(dflt_font_8));
2897             bcopy(dflt_font_14, sc->font_14, sizeof(dflt_font_14));
2898             bcopy(dflt_font_16, sc->font_16, sizeof(dflt_font_16));
2899             sc->fonts_loaded = FONT_16 | FONT_14 | FONT_8;
2900             if (scp->font_size < 14) {
2901                 sc_load_font(scp, 0, 8, sc->font_8, 0, 256);
2902             } else if (scp->font_size >= 16) {
2903                 sc_load_font(scp, 0, 16, sc->font_16, 0, 256);
2904             } else {
2905                 sc_load_font(scp, 0, 14, sc->font_14, 0, 256);
2906             }
2907 #else /* !SC_DFLT_FONT */
2908             if (scp->font_size < 14) {
2909                 sc_save_font(scp, 0, 8, sc->font_8, 0, 256);
2910                 sc->fonts_loaded = FONT_8;
2911             } else if (scp->font_size >= 16) {
2912                 sc_save_font(scp, 0, 16, sc->font_16, 0, 256);
2913                 sc->fonts_loaded = FONT_16;
2914             } else {
2915                 sc_save_font(scp, 0, 14, sc->font_14, 0, 256);
2916                 sc->fonts_loaded = FONT_14;
2917             }
2918 #endif /* SC_DFLT_FONT */
2919             /* FONT KLUDGE: always use the font page #0. XXX */
2920             sc_show_font(scp, 0);
2921         }
2922 #endif /* !SC_NO_FONT_LOADING */
2923
2924 #ifndef SC_NO_PALETTE_LOADING
2925         save_palette(sc->adp, sc->palette);
2926 #endif
2927
2928 #if NSPLASH > 0
2929         if (!(sc->flags & SC_SPLASH_SCRN) && (flags & SC_KERNEL_CONSOLE)) {
2930             /* we are ready to put up the splash image! */
2931             splash_init(sc->adp, scsplash_callback, sc);
2932             sc->flags |= SC_SPLASH_SCRN;
2933         }
2934 #endif /* NSPLASH */
2935     }
2936
2937     /* the rest is not necessary, if we have done it once */
2938     if (sc->flags & SC_INIT_DONE) {
2939         return;
2940     }
2941
2942     /* initialize mapscrn arrays to a one to one map */
2943     for (i = 0; i < sizeof(sc->scr_map); i++)
2944         sc->scr_map[i] = sc->scr_rmap[i] = i;
2945
2946     sc->flags |= SC_INIT_DONE;
2947 }
2948
2949 static void
2950 scterm(int unit, int flags)
2951 {
2952     sc_softc_t *sc;
2953     scr_stat *scp;
2954
2955     sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
2956     if (sc == NULL)
2957         return;                 /* shouldn't happen */
2958
2959     lwkt_gettoken(&tty_token);
2960 #if NSPLASH > 0
2961     /* this console is no longer available for the splash screen */
2962     if (sc->flags & SC_SPLASH_SCRN) {
2963         splash_term(sc->adp);
2964         sc->flags &= ~SC_SPLASH_SCRN;
2965     }
2966 #endif /* NSPLASH */
2967
2968 #if 0 /* XXX */
2969     /* move the hardware cursor to the upper-left corner */
2970     (*vidsw[sc->adapter]->set_hw_cursor)(sc->adp, 0, 0);
2971 #endif
2972
2973     /* release the keyboard and the video card */
2974     if (sc->keyboard >= 0)
2975         kbd_release(sc->kbd, &sc->keyboard);
2976     if (sc->adapter >= 0)
2977         vid_release(sc->adp, &sc->adapter);
2978
2979     /* 
2980      * Stop the terminal emulator, if any.  If operating on the
2981      * kernel console sc->dev may not be setup yet.
2982      */
2983     if (flags & SC_KERNEL_CONSOLE)
2984         scp = sc->console_scp;
2985     else
2986         scp = SC_STAT(sc->dev[0]);
2987     if (scp->tsw)
2988         (*scp->tsw->te_term)(scp, &scp->ts);
2989     if (scp->ts != NULL)
2990         kfree(scp->ts, M_SYSCONS);
2991
2992     /* clear the structure */
2993     if (!(flags & SC_KERNEL_CONSOLE)) {
2994         /* XXX: We need delete_dev() for this */
2995         kfree(sc->dev, M_SYSCONS);
2996 #if 0
2997         /* XXX: We need a ttyunregister for this */
2998         kfree(sc->tty, M_SYSCONS);
2999 #endif
3000 #ifndef SC_NO_FONT_LOADING
3001         kfree(sc->font_8, M_SYSCONS);
3002         kfree(sc->font_14, M_SYSCONS);
3003         kfree(sc->font_16, M_SYSCONS);
3004 #endif
3005         /* XXX vtb, history */
3006     }
3007     bzero(sc, sizeof(*sc));
3008     sc->keyboard = -1;
3009     sc->adapter = -1;
3010     lwkt_reltoken(&tty_token);
3011 }
3012
3013 static void
3014 scshutdown(void *arg, int howto)
3015 {
3016     /* assert(sc_console != NULL) */
3017
3018     lwkt_gettoken(&tty_token);
3019     syscons_lock();
3020     sc_touch_scrn_saver();
3021     if (!cold && sc_console
3022         && sc_console->sc->cur_scp->smode.mode == VT_AUTO 
3023         && sc_console->smode.mode == VT_AUTO) {
3024         sc_switch_scr(sc_console->sc, sc_console->index);
3025     }
3026     shutdown_in_progress = TRUE;
3027     syscons_unlock();
3028     lwkt_reltoken(&tty_token);
3029 }
3030
3031 int
3032 sc_clean_up(scr_stat *scp)
3033 {
3034 #if NSPLASH > 0
3035     int error;
3036 #endif /* NSPLASH */
3037
3038     lwkt_gettoken(&tty_token);
3039     if (scp->sc->flags & SC_SCRN_BLANKED) {
3040         sc_touch_scrn_saver();
3041 #if NSPLASH > 0
3042         if ((error = wait_scrn_saver_stop(scp->sc))) {
3043             lwkt_reltoken(&tty_token);
3044             return error;
3045         }
3046 #endif /* NSPLASH */
3047     }
3048     scp->status |= MOUSE_HIDDEN;
3049     sc_remove_mouse_image(scp);
3050     sc_remove_cutmarking(scp);
3051     lwkt_reltoken(&tty_token);
3052     return 0;
3053 }
3054
3055 void
3056 sc_alloc_scr_buffer(scr_stat *scp, int wait, int discard)
3057 {
3058     sc_vtb_t new;
3059     sc_vtb_t old;
3060
3061     lwkt_gettoken(&tty_token);
3062     old = scp->vtb;
3063     sc_vtb_init(&new, VTB_MEMORY, scp->xsize, scp->ysize, NULL, wait);
3064     if (!discard && (old.vtb_flags & VTB_VALID)) {
3065         /* retain the current cursor position and buffer contants */
3066         scp->cursor_oldpos = scp->cursor_pos;
3067         /* 
3068          * This works only if the old buffer has the same size as or larger 
3069          * than the new one. XXX
3070          */
3071         sc_vtb_copy(&old, 0, &new, 0, scp->xsize*scp->ysize);
3072         scp->vtb = new;
3073     } else {
3074         scp->vtb = new;
3075         sc_vtb_destroy(&old);
3076     }
3077
3078 #ifndef SC_NO_SYSMOUSE
3079     /* move the mouse cursor at the center of the screen */
3080     sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
3081 #endif
3082     lwkt_reltoken(&tty_token);
3083 }
3084
3085 static scr_stat *
3086 alloc_scp(sc_softc_t *sc, int vty)
3087 {
3088     scr_stat *scp;
3089
3090     /* assert(sc_malloc) */
3091
3092     scp = kmalloc(sizeof(scr_stat), M_SYSCONS, M_WAITOK);
3093     init_scp(sc, vty, scp);
3094
3095     sc_alloc_scr_buffer(scp, TRUE, TRUE);
3096     if (sc_init_emulator(scp, SC_DFLT_TERM))
3097         sc_init_emulator(scp, "*");
3098
3099 #ifndef SC_NO_CUTPASTE
3100     sc_alloc_cut_buffer(scp, TRUE);
3101 #endif
3102
3103 #ifndef SC_NO_HISTORY
3104     sc_alloc_history_buffer(scp, 0, 0, TRUE);
3105 #endif
3106     return scp;
3107 }
3108
3109 /*
3110  * NOTE: Must be called with tty_token held.
3111  */
3112 static void
3113 init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
3114 {
3115     video_info_t info;
3116
3117     bzero(scp, sizeof(*scp));
3118
3119     scp->index = vty;
3120     scp->sc = sc;
3121     scp->status = 0;
3122     scp->mode = sc->initial_mode;
3123     callout_init_mp(&scp->blink_screen_ch);
3124     lwkt_gettoken(&tty_token);
3125     (*vidsw[sc->adapter]->get_info)(sc->adp, scp->mode, &info);
3126     lwkt_reltoken(&tty_token);
3127     if (info.vi_flags & V_INFO_GRAPHICS) {
3128         scp->status |= GRAPHICS_MODE;
3129         scp->xpixel = info.vi_width;
3130         scp->ypixel = info.vi_height;
3131         scp->xsize = info.vi_width/8;
3132         scp->ysize = info.vi_height/info.vi_cheight;
3133         scp->font_size = 0;
3134         scp->font = NULL;
3135     } else {
3136         scp->xsize = info.vi_width;
3137         scp->ysize = info.vi_height;
3138         scp->xpixel = scp->xsize*8;
3139         scp->ypixel = scp->ysize*info.vi_cheight;
3140         if (info.vi_cheight < 14) {
3141             scp->font_size = 8;
3142 #ifndef SC_NO_FONT_LOADING
3143             scp->font = sc->font_8;
3144 #else
3145             scp->font = NULL;
3146 #endif
3147         } else if (info.vi_cheight >= 16) {
3148             scp->font_size = 16;
3149 #ifndef SC_NO_FONT_LOADING
3150             scp->font = sc->font_16;
3151 #else
3152             scp->font = NULL;
3153 #endif
3154         } else {
3155             scp->font_size = 14;
3156 #ifndef SC_NO_FONT_LOADING
3157             scp->font = sc->font_14;
3158 #else
3159             scp->font = NULL;
3160 #endif
3161         }
3162     }
3163     sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE);
3164     sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE);
3165     scp->xoff = scp->yoff = 0;
3166     scp->xpos = scp->ypos = 0;
3167     scp->start = scp->xsize * scp->ysize - 1;
3168     scp->end = 0;
3169     scp->tsw = NULL;
3170     scp->ts = NULL;
3171     scp->rndr = NULL;
3172     scp->border = BG_BLACK;
3173     scp->cursor_base = sc->cursor_base;
3174     scp->cursor_height = imin(sc->cursor_height, scp->font_size);
3175     scp->mouse_cut_start = scp->xsize*scp->ysize;
3176     scp->mouse_cut_end = -1;
3177     scp->mouse_signal = 0;
3178     scp->mouse_pid = 0;
3179     scp->mouse_proc = NULL;
3180     scp->kbd_mode = K_XLATE;
3181     scp->bell_pitch = bios_value.bell_pitch;
3182     scp->bell_duration = BELL_DURATION;
3183     scp->status |= (bios_value.shift_state & NLKED);
3184     scp->status |= CURSOR_ENABLED | MOUSE_HIDDEN;
3185     scp->pid = 0;
3186     scp->proc = NULL;
3187     scp->smode.mode = VT_AUTO;
3188     scp->history = NULL;
3189     scp->history_pos = 0;
3190     scp->history_size = 0;
3191 }
3192
3193 int
3194 sc_init_emulator(scr_stat *scp, char *name)
3195 {
3196     sc_term_sw_t *sw;
3197     sc_rndr_sw_t *rndr;
3198     void *p;
3199     int error;
3200
3201     if (name == NULL)   /* if no name is given, use the current emulator */
3202         sw = scp->tsw;
3203     else                /* ...otherwise find the named emulator */
3204         sw = sc_term_match(name);
3205     if (sw == NULL) {
3206         return EINVAL;
3207     }
3208
3209     rndr = NULL;
3210     if (strcmp(sw->te_renderer, "*") != 0) {
3211         rndr = sc_render_match(scp, sw->te_renderer, scp->model);
3212     }
3213     if (rndr == NULL) {
3214         rndr = sc_render_match(scp, scp->sc->adp->va_name, scp->model);
3215         if (rndr == NULL) {
3216             return ENODEV;
3217         }
3218     }
3219
3220     if (sw == scp->tsw) {
3221         error = (*sw->te_init)(scp, &scp->ts, SC_TE_WARM_INIT);
3222         scp->rndr = rndr;
3223         sc_clear_screen(scp);
3224         /* assert(error == 0); */
3225         return error;
3226     }
3227
3228     if (sc_malloc && (sw->te_size > 0))
3229         p = kmalloc(sw->te_size, M_SYSCONS, M_NOWAIT);
3230     else
3231         p = NULL;
3232     error = (*sw->te_init)(scp, &p, SC_TE_COLD_INIT);
3233     if (error) {
3234         return error;
3235     }
3236
3237     if (scp->tsw)
3238         (*scp->tsw->te_term)(scp, &scp->ts);
3239     if (scp->ts != NULL)
3240         kfree(scp->ts, M_SYSCONS);
3241     scp->tsw = sw;
3242     scp->ts = p;
3243     scp->rndr = rndr;
3244
3245     /* XXX */
3246     (*sw->te_default_attr)(scp, user_default.std_color, user_default.rev_color);
3247     sc_clear_screen(scp);
3248
3249     return 0;
3250 }
3251
3252 /*
3253  * scgetc(flags) - get character from keyboard.
3254  * If flags & SCGETC_CN, then avoid harmful side effects.
3255  * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else
3256  * return NOKEY if there is nothing there.
3257  */
3258 static u_int
3259 scgetc(sc_softc_t *sc, u_int flags)
3260 {
3261     scr_stat *scp;
3262 #ifndef SC_NO_HISTORY
3263     struct tty *tp;
3264 #endif
3265     u_int c;
3266     int this_scr;
3267     int f;
3268     int i;
3269
3270     lwkt_gettoken(&tty_token);
3271     if (sc->kbd == NULL) {
3272         lwkt_reltoken(&tty_token);
3273         return NOKEY;
3274     }
3275
3276 next_code:
3277 #if 1
3278     /* I don't like this, but... XXX */
3279     if (flags & SCGETC_CN) {
3280         syscons_lock();
3281         sccnupdate(sc->cur_scp);
3282         syscons_unlock();
3283     }
3284 #endif
3285     scp = sc->cur_scp;
3286     /* first see if there is something in the keyboard port */
3287     for (;;) {
3288         c = kbd_read_char(sc->kbd, !(flags & SCGETC_NONBLOCK));
3289         if (c == ERRKEY) {
3290             if (!(flags & SCGETC_CN))
3291                 sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
3292         } else if (c == NOKEY) {
3293             lwkt_reltoken(&tty_token);
3294             return c;
3295         } else {
3296             break;
3297         }
3298     }
3299
3300     /* make screensaver happy */
3301     if (!(c & RELKEY))
3302         sc_touch_scrn_saver();
3303
3304     if (!(flags & SCGETC_CN))
3305         /* do the /dev/random device a favour */
3306         add_keyboard_randomness(c);
3307
3308     if (scp->kbd_mode != K_XLATE) {
3309         lwkt_reltoken(&tty_token);
3310         return KEYCHAR(c);
3311     }
3312
3313     /* if scroll-lock pressed allow history browsing */
3314     if (!ISGRAPHSC(scp) && scp->history && scp->status & SLKED) {
3315
3316         scp->status &= ~CURSOR_ENABLED;
3317         sc_remove_cursor_image(scp);
3318
3319 #ifndef SC_NO_HISTORY
3320         if (!(scp->status & BUFFER_SAVED)) {
3321             scp->status |= BUFFER_SAVED;
3322             sc_hist_save(scp);
3323         }
3324         switch (c) {
3325         /* FIXME: key codes */
3326         case SPCLKEY | FKEY | F(49):  /* home key */
3327             sc_remove_cutmarking(scp);
3328             sc_hist_home(scp);
3329             goto next_code;
3330
3331         case SPCLKEY | FKEY | F(57):  /* end key */
3332             sc_remove_cutmarking(scp);
3333             sc_hist_end(scp);
3334             goto next_code;
3335
3336         case SPCLKEY | FKEY | F(50):  /* up arrow key */
3337             sc_remove_cutmarking(scp);
3338             if (sc_hist_up_line(scp))
3339                 if (!(flags & SCGETC_CN))
3340                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
3341             goto next_code;
3342
3343         case SPCLKEY | FKEY | F(58):  /* down arrow key */
3344             sc_remove_cutmarking(scp);
3345             if (sc_hist_down_line(scp))
3346                 if (!(flags & SCGETC_CN))
3347                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
3348             goto next_code;
3349
3350         case SPCLKEY | FKEY | F(51):  /* page up key */
3351             sc_remove_cutmarking(scp);
3352             for (i=0; i<scp->ysize; i++)
3353             if (sc_hist_up_line(scp)) {
3354                 if (!(flags & SCGETC_CN))
3355                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
3356                 break;
3357             }
3358             goto next_code;
3359
3360         case SPCLKEY | FKEY | F(59):  /* page down key */
3361             sc_remove_cutmarking(scp);
3362             for (i=0; i<scp->ysize; i++)
3363             if (sc_hist_down_line(scp)) {
3364                 if (!(flags & SCGETC_CN))
3365                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
3366                 break;
3367             }
3368             goto next_code;
3369         }
3370 #endif /* SC_NO_HISTORY */
3371     }
3372
3373     /* 
3374      * Process and consume special keys here.  Return a plain char code
3375      * or a char code with the META flag or a function key code.
3376      */
3377     if (c & RELKEY) {
3378         /* key released */
3379         /* goto next_code */
3380     } else {
3381         /* key pressed */
3382         if (c & SPCLKEY) {
3383             c &= ~SPCLKEY;
3384             switch (KEYCHAR(c)) {
3385             /* LOCKING KEYS */
3386             case NLK: case CLK: case ALK:
3387                 break;
3388             case SLK:
3389                 kbd_ioctl(sc->kbd, KDGKBSTATE, (caddr_t)&f);
3390                 if (f & SLKED) {
3391                     scp->status |= SLKED;
3392                 } else {
3393                     if (scp->status & SLKED) {
3394                         scp->status &= ~SLKED;
3395 #ifndef SC_NO_HISTORY
3396                         if (scp->status & BUFFER_SAVED) {
3397                             if (!sc_hist_restore(scp))
3398                                 sc_remove_cutmarking(scp);
3399                             scp->status &= ~BUFFER_SAVED;
3400                             scp->status |= CURSOR_ENABLED;
3401                             sc_draw_cursor_image(scp);
3402                         }
3403                         tp = VIRTUAL_TTY(sc, scp->index);
3404                         if (ISTTYOPEN(tp))
3405                             scstart(tp);
3406 #endif
3407                     }
3408                 }
3409                 break;
3410
3411             /* NON-LOCKING KEYS */
3412             case NOP:
3413             case LSH:  case RSH:  case LCTR: case RCTR:
3414             case LALT: case RALT: case ASH:  case META:
3415                 break;
3416
3417             case BTAB:
3418                 if (!(sc->flags & SC_SCRN_BLANKED)) {
3419                     lwkt_reltoken(&tty_token);
3420                     return c;
3421                 }
3422                 break;
3423
3424             case SPSC:
3425 #if NSPLASH > 0
3426                 /* force activatation/deactivation of the screen saver */
3427                 if (!(sc->flags & SC_SCRN_BLANKED)) {
3428                     run_scrn_saver = TRUE;
3429                     sc->scrn_time_stamp -= scrn_blank_time;
3430                 }
3431                 if (cold) {
3432                     /*
3433                      * While devices are being probed, the screen saver need
3434                      * to be invoked explictly. XXX
3435                      */
3436                     if (sc->flags & SC_SCRN_BLANKED) {
3437                         scsplash_stick(FALSE);
3438                         stop_scrn_saver(sc, current_saver);
3439                     } else {
3440                         if (!ISGRAPHSC(scp)) {
3441                             scsplash_stick(TRUE);
3442                             (*current_saver)(sc, TRUE);
3443                         }
3444                     }
3445                 }
3446 #endif /* NSPLASH */
3447                 break;
3448
3449             case RBT:
3450 #ifndef SC_DISABLE_REBOOT
3451                 shutdown_nice(0);
3452 #endif
3453                 break;
3454
3455             case HALT:
3456 #ifndef SC_DISABLE_REBOOT
3457                 shutdown_nice(RB_HALT);
3458 #endif
3459                 break;
3460
3461             case PDWN:
3462 #ifndef SC_DISABLE_REBOOT
3463                 shutdown_nice(RB_HALT|RB_POWEROFF);
3464 #endif
3465                 break;
3466
3467 #if NAPM > 0
3468             case SUSP:
3469                 apm_suspend(PMST_SUSPEND);
3470                 break;
3471             case STBY:
3472                 apm_suspend(PMST_STANDBY);
3473                 break;
3474 #else
3475             case SUSP:
3476             case STBY:
3477                 break;
3478 #endif
3479
3480             case DBG:
3481 #ifndef SC_DISABLE_DDBKEY
3482 #ifdef DDB
3483                 lwkt_reltoken(&tty_token);
3484                 Debugger("manual escape to debugger");
3485                 lwkt_gettoken(&tty_token);
3486 #else
3487                 kprintf("No debugger in kernel\n");
3488 #endif
3489 #else /* SC_DISABLE_DDBKEY */
3490                 /* do nothing */
3491 #endif /* SC_DISABLE_DDBKEY */
3492                 break;
3493
3494             case PNC:
3495                 if (enable_panic_key)
3496                         panic("Forced by the panic key");
3497                 break;
3498
3499             case NEXT:
3500                 this_scr = scp->index;
3501                 for (i = (this_scr - sc->first_vty + 1)%sc->vtys;
3502                         sc->first_vty + i != this_scr; 
3503                         i = (i + 1)%sc->vtys) {
3504                     struct tty *tp = VIRTUAL_TTY(sc, sc->first_vty + i);
3505                     if (ISTTYOPEN(tp)) {
3506                         syscons_lock();
3507                         sc_switch_scr(scp->sc, sc->first_vty + i);
3508                         syscons_unlock();
3509                         break;
3510                     }
3511                 }
3512                 break;
3513
3514             case PREV:
3515                 this_scr = scp->index;
3516                 for (i = (this_scr - sc->first_vty + sc->vtys - 1)%sc->vtys;
3517                         sc->first_vty + i != this_scr;
3518                         i = (i + sc->vtys - 1)%sc->vtys) {
3519                     struct tty *tp = VIRTUAL_TTY(sc, sc->first_vty + i);
3520                     if (ISTTYOPEN(tp)) {
3521                         syscons_lock();
3522                         sc_switch_scr(scp->sc, sc->first_vty + i);
3523                         syscons_unlock();
3524                         break;
3525                     }
3526                 }
3527                 break;
3528
3529             default:
3530                 if (KEYCHAR(c) >= F_SCR && KEYCHAR(c) <= L_SCR) {
3531                     syscons_lock();
3532                     sc_switch_scr(scp->sc, sc->first_vty + KEYCHAR(c) - F_SCR);
3533                     syscons_unlock();
3534                     break;
3535                 }
3536                 /* assert(c & FKEY) */
3537                 if (!(sc->flags & SC_SCRN_BLANKED)) {
3538                     lwkt_reltoken(&tty_token);
3539                     return c;
3540                 }
3541                 break;
3542             }
3543             /* goto next_code */
3544         } else {
3545             /* regular keys (maybe MKEY is set) */
3546             if (!(sc->flags & SC_SCRN_BLANKED)) {
3547                 lwkt_reltoken(&tty_token);
3548                 return c;
3549             }
3550         }
3551     }
3552
3553     goto next_code;
3554 }
3555
3556 int
3557 scmmap(struct dev_mmap_args *ap)
3558 {
3559     scr_stat *scp;
3560
3561     lwkt_gettoken(&tty_token);
3562     scp = SC_STAT(ap->a_head.a_dev);
3563     if (scp != scp->sc->cur_scp) {
3564         lwkt_reltoken(&tty_token);
3565         return EINVAL;
3566     }
3567     ap->a_result = (*vidsw[scp->sc->adapter]->mmap)(scp->sc->adp, ap->a_offset,
3568                                                     ap->a_nprot);
3569     lwkt_reltoken(&tty_token);
3570     return(0);
3571 }
3572
3573 static int
3574 save_kbd_state(scr_stat *scp, int unlock)
3575 {
3576     int state;
3577     int error;
3578
3579     WANT_UNLOCK(unlock);
3580     error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state);
3581     WANT_LOCK(unlock);
3582
3583     if (error == ENOIOCTL)
3584         error = ENODEV;
3585     if (error == 0) {
3586         scp->status &= ~LOCK_MASK;
3587         scp->status |= state;
3588     }
3589     return error;
3590 }
3591
3592 static int
3593 update_kbd_state(scr_stat *scp, int new_bits, int mask, int unlock)
3594 {
3595     int state;
3596     int error;
3597
3598     if (mask != LOCK_MASK) {
3599         WANT_UNLOCK(unlock);
3600         error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state);
3601         WANT_LOCK(unlock);
3602
3603         if (error == ENOIOCTL)
3604             error = ENODEV;
3605         if (error) {
3606             return error;
3607         }
3608         state &= ~mask;
3609         state |= new_bits & mask;
3610     } else {
3611         state = new_bits & LOCK_MASK;
3612     }
3613     WANT_UNLOCK(unlock);
3614     error = kbd_ioctl(scp->sc->kbd, KDSKBSTATE, (caddr_t)&state);
3615     WANT_LOCK(unlock);
3616     if (error == ENOIOCTL)
3617         error = ENODEV;
3618     return error;
3619 }
3620
3621 static int
3622 update_kbd_leds(scr_stat *scp, int which)
3623 {
3624     int error;
3625
3626     which &= LOCK_MASK;
3627     error = kbd_ioctl(scp->sc->kbd, KDSETLED, (caddr_t)&which);
3628     if (error == ENOIOCTL)
3629         error = ENODEV;
3630     return error;
3631 }
3632
3633 int
3634 set_mode(scr_stat *scp)
3635 {
3636     video_info_t info;
3637
3638     lwkt_gettoken(&tty_token);
3639     /* reject unsupported mode */
3640     if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) {
3641         lwkt_reltoken(&tty_token);
3642         return 1;
3643     }
3644
3645     /* if this vty is not currently showing, do nothing */
3646     if (scp != scp->sc->cur_scp) {
3647         lwkt_reltoken(&tty_token);
3648         return 0;
3649     }
3650
3651     /* setup video hardware for the given mode */
3652     (*vidsw[scp->sc->adapter]->set_mode)(scp->sc->adp, scp->mode);
3653     sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
3654                 (void *)scp->sc->adp->va_window, FALSE);
3655
3656 #ifndef SC_NO_FONT_LOADING
3657     /* load appropriate font */
3658     if (!(scp->status & GRAPHICS_MODE)) {
3659         if (!(scp->status & PIXEL_MODE) && ISFONTAVAIL(scp->sc->adp->va_flags)) {
3660             if (scp->font_size < 14) {
3661                 if (scp->sc->fonts_loaded & FONT_8)
3662                     sc_load_font(scp, 0, 8, scp->sc->font_8, 0, 256);
3663             } else if (scp->font_size >= 16) {
3664                 if (scp->sc->fonts_loaded & FONT_16)
3665                     sc_load_font(scp, 0, 16, scp->sc->font_16, 0, 256);
3666             } else {
3667                 if (scp->sc->fonts_loaded & FONT_14)
3668                     sc_load_font(scp, 0, 14, scp->sc->font_14, 0, 256);
3669             }
3670             /*
3671              * FONT KLUDGE:
3672              * This is an interim kludge to display correct font.
3673              * Always use the font page #0 on the video plane 2.
3674              * Somehow we cannot show the font in other font pages on
3675              * some video cards... XXX
3676              */ 
3677             sc_show_font(scp, 0);
3678         }
3679         mark_all(scp);
3680     }
3681 #endif /* !SC_NO_FONT_LOADING */
3682
3683     sc_set_border(scp, scp->border);
3684     sc_set_cursor_image(scp);
3685
3686     lwkt_reltoken(&tty_token);
3687     return 0;
3688 }
3689
3690 void
3691 refresh_ega_palette(scr_stat *scp)
3692 {
3693     uint32_t r, g, b;
3694     int reg;
3695     int rsize, gsize, bsize;
3696     int rfld, gfld, bfld;
3697     int i;
3698
3699     rsize = scp->sc->adp->va_info.vi_pixel_fsizes[0];
3700     gsize = scp->sc->adp->va_info.vi_pixel_fsizes[1];
3701     bsize = scp->sc->adp->va_info.vi_pixel_fsizes[2];
3702     rfld = scp->sc->adp->va_info.vi_pixel_fields[0];
3703     gfld = scp->sc->adp->va_info.vi_pixel_fields[1];
3704     bfld = scp->sc->adp->va_info.vi_pixel_fields[2];
3705
3706     for (i = 0; i < 16; i++) {
3707         reg = scp->sc->adp->va_palette_regs[i];
3708
3709         r = scp->sc->palette[reg * 3] >> (8 - rsize);
3710         g = scp->sc->palette[reg * 3 + 1] >> (8 - gsize);
3711         b = scp->sc->palette[reg * 3 + 2] >> (8 - bsize);
3712
3713         scp->ega_palette[i] = (r << rfld) + (g << gfld) + (b << bfld);
3714     }
3715 }
3716
3717 void
3718 sc_set_border(scr_stat *scp, int color)
3719 {
3720     ++scp->sc->videoio_in_progress;
3721     (*scp->rndr->draw_border)(scp, color);
3722     --scp->sc->videoio_in_progress;
3723 }
3724
3725 #ifndef SC_NO_FONT_LOADING
3726 void
3727 sc_load_font(scr_stat *scp, int page, int size, u_char *buf,
3728              int base, int count)
3729 {
3730     sc_softc_t *sc;
3731
3732     sc = scp->sc;
3733     sc->font_loading_in_progress = TRUE;
3734     (*vidsw[sc->adapter]->load_font)(sc->adp, page, size, buf, base, count);
3735     sc->font_loading_in_progress = FALSE;
3736 }
3737
3738 void
3739 sc_save_font(scr_stat *scp, int page, int size, u_char *buf,
3740              int base, int count)
3741 {
3742     sc_softc_t *sc;
3743
3744     sc = scp->sc;
3745     sc->font_loading_in_progress = TRUE;
3746     (*vidsw[sc->adapter]->save_font)(sc->adp, page, size, buf, base, count);
3747     sc->font_loading_in_progress = FALSE;
3748 }
3749
3750 void
3751 sc_show_font(scr_stat *scp, int page)
3752 {
3753     (*vidsw[scp->sc->adapter]->show_font)(scp->sc->adp, page);
3754 }
3755 #endif /* !SC_NO_FONT_LOADING */
3756
3757 void
3758 sc_paste(scr_stat *scp, u_char *p, int count) 
3759 {
3760     struct tty *tp;
3761     u_char *rmap;
3762
3763     lwkt_gettoken(&tty_token);
3764     if (scp->status & MOUSE_VISIBLE) {
3765         tp = VIRTUAL_TTY(scp->sc, scp->sc->cur_scp->index);
3766         if (!ISTTYOPEN(tp)) {
3767             lwkt_reltoken(&tty_token);
3768             return;
3769         }
3770         rmap = scp->sc->scr_rmap;
3771         for (; count > 0; --count)
3772             (*linesw[tp->t_line].l_rint)(rmap[*p++], tp);
3773     }
3774     lwkt_reltoken(&tty_token);
3775 }
3776
3777 void
3778 sc_bell(scr_stat *scp, int pitch, int duration)
3779 {
3780     if (cold || shutdown_in_progress)
3781         return;
3782
3783     if (scp != scp->sc->cur_scp && (scp->sc->flags & SC_QUIET_BELL)) {
3784         return;
3785     }
3786
3787     if (scp->sc->flags & SC_VISUAL_BELL) {
3788         if (scp->sc->blink_in_progress) {
3789             return;
3790         }
3791         scp->sc->blink_in_progress = 3;
3792         if (scp != scp->sc->cur_scp)
3793             scp->sc->blink_in_progress += 2;
3794         sc_blink_screen(scp->sc->cur_scp);
3795     } else if (duration != 0 && pitch != 0) {
3796         if (scp != scp->sc->cur_scp)
3797             pitch *= 2;
3798         sysbeep(pitch, duration);
3799     }
3800 }
3801
3802 /*
3803  * Two versions of blink_screen(), one called from the console path
3804  * with the syscons locked, and one called from a timer callout.
3805  */
3806 static void
3807 sc_blink_screen(scr_stat *scp)
3808 {
3809     if (ISGRAPHSC(scp) || (scp->sc->blink_in_progress <= 1)) {
3810         scp->sc->blink_in_progress = 0;
3811         mark_all(scp);
3812         if (scp->sc->delayed_next_scr)
3813             sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
3814     } else {
3815         (*scp->rndr->draw)(scp, 0, scp->xsize*scp->ysize,
3816                            scp->sc->blink_in_progress & 1);
3817         scp->sc->blink_in_progress--;
3818     }
3819 }
3820
3821 #if 0
3822 static void
3823 blink_screen_callout(void *arg)
3824 {
3825     scr_stat *scp = arg;
3826     struct tty *tp;
3827
3828     if (ISGRAPHSC(scp) || (scp->sc->blink_in_progress <= 1)) {
3829         syscons_lock();
3830         scp->sc->blink_in_progress = 0;
3831         mark_all(scp);
3832         syscons_unlock();
3833         tp = VIRTUAL_TTY(scp->sc, scp->index);
3834         if (ISTTYOPEN(tp))
3835             scstart(tp);
3836         if (scp->sc->delayed_next_scr) {
3837             syscons_lock();
3838             sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
3839             syscons_unlock();
3840         }
3841     } else {
3842         syscons_lock();
3843         (*scp->rndr->draw)(scp, 0, scp->xsize*scp->ysize, 
3844                            scp->sc->blink_in_progress & 1);
3845         scp->sc->blink_in_progress--;
3846         syscons_unlock();
3847         callout_reset(&scp->blink_screen_ch, hz / 10,
3848                       blink_screen_callout, scp);
3849     }
3850 }
3851 #endif
3852
3853 /*
3854  * Allocate active keyboard. Try to allocate "kbdmux" keyboard first, and,
3855  * if found, add all non-busy keyboards to "kbdmux". Otherwise look for
3856  * any keyboard.
3857  */
3858
3859 static int
3860 sc_allocate_keyboard(sc_softc_t *sc, int unit)
3861 {
3862         int              idx0, idx;
3863         keyboard_t      *k0, *k;
3864         keyboard_info_t  ki;
3865
3866         idx0 = kbd_allocate("kbdmux", -1, (void *)&sc->keyboard, sckbdevent, sc);
3867         if (idx0 != -1) {
3868                 k0 = kbd_get_keyboard(idx0);
3869
3870                 for (idx = kbd_find_keyboard2("*", -1, 0, 0);
3871                      idx != -1;
3872                      idx = kbd_find_keyboard2("*", -1, idx + 1, 0)) {
3873                         k = kbd_get_keyboard(idx);
3874
3875                         if (idx == idx0 || KBD_IS_BUSY(k))
3876                                 continue;
3877
3878                         bzero(&ki, sizeof(ki));
3879                         strcpy(ki.kb_name, k->kb_name);
3880                         ki.kb_unit = k->kb_unit;
3881
3882                         kbd_ioctl(k0, KBADDKBD, (caddr_t) &ki);
3883                 }
3884         } else
3885                 idx0 = kbd_allocate("*", unit, (void *)&sc->keyboard, sckbdevent, sc);
3886
3887         return (idx0);
3888 }