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