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