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