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