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