Deleted Added
full compact
syscons.c (39287) syscons.c (39591)
1/*-
2 * Copyright (c) 1992-1998 S�ren Schmidt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
1/*-
2 * Copyright (c) 1992-1998 S�ren Schmidt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id$
28 * $Id: syscons.c,v 1.278 1998/09/15 18:16:37 sos Exp $
29 */
30
31#include "sc.h"
32#include "apm.h"
33#include "opt_ddb.h"
34#include "opt_devfs.h"
35#include "opt_vesa.h"
36#include "opt_vm86.h"
37#include "opt_syscons.h"
38
39#if NSC > 0
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/reboot.h>
43#include <sys/conf.h>
44#include <sys/proc.h>
45#include <sys/signalvar.h>
46#include <sys/tty.h>
47#include <sys/kernel.h>
48#include <sys/malloc.h>
49#ifdef DEVFS
50#include <sys/devfsext.h>
51#endif
52
53#include <machine/bootinfo.h>
54#include <machine/clock.h>
55#include <machine/cons.h>
56#include <machine/console.h>
57#include <machine/mouse.h>
58#include <machine/md_var.h>
59#include <machine/psl.h>
60#include <machine/frame.h>
61#include <machine/pc/display.h>
62#include <machine/pc/vesa.h>
63#include <machine/apm_bios.h>
64#include <machine/random.h>
65
66#include <vm/vm.h>
67#include <vm/vm_param.h>
68#include <vm/pmap.h>
69
70#include <i386/isa/isa.h>
71#include <i386/isa/isa_device.h>
72#include <i386/isa/timerreg.h>
73#include <i386/isa/kbdtables.h>
74#include <i386/isa/kbdio.h>
75#include <i386/isa/videoio.h>
76#include <i386/isa/syscons.h>
77
78#if !defined(MAXCONS)
79#define MAXCONS 16
80#endif
81
82#if !defined(SC_MAX_HISTORY_SIZE)
83#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS)
84#endif
85
86#if !defined(SC_HISTORY_SIZE)
87#define SC_HISTORY_SIZE (ROW * 4)
88#endif
89
90#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE
91#undef SC_MAX_HISTORY_SIZE
92#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS)
93#endif
94
95#if !defined(SC_MOUSE_CHAR)
96#define SC_MOUSE_CHAR (0xd0)
97#endif
98
99#define COLD 0
100#define WARM 1
101
102#define DEFAULT_BLANKTIME (5*60) /* 5 minutes */
103#define MAX_BLANKTIME (7*24*60*60) /* 7 days!? */
104
105/* for backward compatibility */
106#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t)
107
108typedef struct old_mouse_data {
109 int x;
110 int y;
111 int buttons;
112} old_mouse_data_t;
113
114typedef struct old_mouse_info {
115 int operation;
116 union {
117 struct old_mouse_data data;
118 struct mouse_mode mode;
119 } u;
120} old_mouse_info_t;
121
122/* XXX use sc_bcopy where video memory is concerned */
123extern void generic_bcopy(const void *, void *, size_t);
29 */
30
31#include "sc.h"
32#include "apm.h"
33#include "opt_ddb.h"
34#include "opt_devfs.h"
35#include "opt_vesa.h"
36#include "opt_vm86.h"
37#include "opt_syscons.h"
38
39#if NSC > 0
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/reboot.h>
43#include <sys/conf.h>
44#include <sys/proc.h>
45#include <sys/signalvar.h>
46#include <sys/tty.h>
47#include <sys/kernel.h>
48#include <sys/malloc.h>
49#ifdef DEVFS
50#include <sys/devfsext.h>
51#endif
52
53#include <machine/bootinfo.h>
54#include <machine/clock.h>
55#include <machine/cons.h>
56#include <machine/console.h>
57#include <machine/mouse.h>
58#include <machine/md_var.h>
59#include <machine/psl.h>
60#include <machine/frame.h>
61#include <machine/pc/display.h>
62#include <machine/pc/vesa.h>
63#include <machine/apm_bios.h>
64#include <machine/random.h>
65
66#include <vm/vm.h>
67#include <vm/vm_param.h>
68#include <vm/pmap.h>
69
70#include <i386/isa/isa.h>
71#include <i386/isa/isa_device.h>
72#include <i386/isa/timerreg.h>
73#include <i386/isa/kbdtables.h>
74#include <i386/isa/kbdio.h>
75#include <i386/isa/videoio.h>
76#include <i386/isa/syscons.h>
77
78#if !defined(MAXCONS)
79#define MAXCONS 16
80#endif
81
82#if !defined(SC_MAX_HISTORY_SIZE)
83#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS)
84#endif
85
86#if !defined(SC_HISTORY_SIZE)
87#define SC_HISTORY_SIZE (ROW * 4)
88#endif
89
90#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE
91#undef SC_MAX_HISTORY_SIZE
92#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS)
93#endif
94
95#if !defined(SC_MOUSE_CHAR)
96#define SC_MOUSE_CHAR (0xd0)
97#endif
98
99#define COLD 0
100#define WARM 1
101
102#define DEFAULT_BLANKTIME (5*60) /* 5 minutes */
103#define MAX_BLANKTIME (7*24*60*60) /* 7 days!? */
104
105/* for backward compatibility */
106#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t)
107
108typedef struct old_mouse_data {
109 int x;
110 int y;
111 int buttons;
112} old_mouse_data_t;
113
114typedef struct old_mouse_info {
115 int operation;
116 union {
117 struct old_mouse_data data;
118 struct mouse_mode mode;
119 } u;
120} old_mouse_info_t;
121
122/* XXX use sc_bcopy where video memory is concerned */
123extern void generic_bcopy(const void *, void *, size_t);
124extern void generic_bzero(void *, size_t);
124
125static default_attr user_default = {
126 (FG_LIGHTGREY | BG_BLACK) << 8,
127 (FG_BLACK | BG_LIGHTGREY) << 8
128};
129
130static default_attr kernel_default = {
131 (FG_WHITE | BG_BLACK) << 8,
132 (FG_BLACK | BG_LIGHTGREY) << 8
133};
134
135static scr_stat main_console;
136static scr_stat *console[MAXCONS];
137#ifdef DEVFS
138static void *sc_devfs_token[MAXCONS];
139static void *sc_mouse_devfs_token;
140static void *sc_console_devfs_token;
141#endif
142 scr_stat *cur_console;
143static scr_stat *new_scp, *old_scp;
144static term_stat kernel_console;
145static default_attr *current_default;
146static int flags = 0;
147static int sc_port = IO_KBD;
148static KBDC sc_kbdc = NULL;
149static char init_done = COLD;
150static u_short sc_buffer[ROW*COL];
151static char shutdown_in_progress = FALSE;
152static char font_loading_in_progress = FALSE;
153static char switch_in_progress = FALSE;
154static char write_in_progress = FALSE;
155static char blink_in_progress = FALSE;
156static int blinkrate = 0;
157 u_int crtc_addr = MONO_BASE;
158 char crtc_type = KD_MONO;
159 char crtc_vga = FALSE;
160static int adp_flags = 0;
161static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0;
162static u_char accents = 0;
163static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0;
164static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab);
165static int delayed_next_scr = FALSE;
166static long scrn_blank_time = 0; /* screen saver timeout value */
167 int scrn_blanked = 0; /* screen saver active flag */
168static long scrn_time_stamp;
169static int saver_mode = CONS_LKM_SAVER; /* LKM/user saver */
170static int run_scrn_saver = FALSE; /* should run the saver? */
171static int scrn_idle = FALSE; /* about to run the saver */
172 u_char scr_map[256];
173 u_char scr_rmap[256];
174static int initial_video_mode; /* initial video mode # */
175static int bios_video_mode; /* video mode # set by BIOS */
176 int fonts_loaded = 0
177#ifdef STD8X16FONT
178 | FONT_16
179#endif
180 ;
181
182 u_char font_8[256*8];
183 u_char font_14[256*14];
184#ifdef STD8X16FONT
185extern
186#endif
187 u_char font_16[256*16];
188 u_char palette[256*3];
189static u_char *cut_buffer = NULL;
190static int cut_buffer_size = 0;
191static int mouse_level = 0; /* sysmouse protocol level */
192static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 };
193static u_short mouse_and_mask[16] = {
194 0xc000, 0xe000, 0xf000, 0xf800,
195 0xfc00, 0xfe00, 0xff00, 0xff80,
196 0xfe00, 0x1e00, 0x1f00, 0x0f00,
197 0x0f00, 0x0000, 0x0000, 0x0000
198 };
199static u_short mouse_or_mask[16] = {
200 0x0000, 0x4000, 0x6000, 0x7000,
201 0x7800, 0x7c00, 0x7e00, 0x6800,
202 0x0c00, 0x0c00, 0x0600, 0x0600,
203 0x0000, 0x0000, 0x0000, 0x0000
204 };
205
206 int sc_history_size = SC_HISTORY_SIZE;
207static int extra_history_size =
208 SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS;
209
210static void none_saver(int blank) { }
211static void (*current_saver)(int blank) = none_saver;
212static void (*default_saver)(int blank) = none_saver;
213 int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data,
214 int flag, struct proc *p) = NULL;
215
216static int sticky_splash = FALSE;
217
218/* OS specific stuff */
219#ifdef not_yet_done
220#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x]))
221struct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS]))
222struct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1]))
223struct tty *sccons[MAXCONS+2];
224#else
225#define VIRTUAL_TTY(x) &sccons[x]
226#define CONSOLE_TTY &sccons[MAXCONS]
227#define MOUSE_TTY &sccons[MAXCONS+1]
228static struct tty sccons[MAXCONS+2];
229#endif
230#define SC_MOUSE 128
231#define SC_CONSOLE 255
232u_short *Crtat;
233static const int nsccons = MAXCONS+2;
234
235#define WRAPHIST(scp, pointer, offset)\
236 ((scp->history) + ((((pointer) - (scp->history)) + (scp->history_size)\
237 + (offset)) % (scp->history_size)))
238#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
239
240/* prototypes */
241static int scattach(struct isa_device *dev);
242static int scparam(struct tty *tp, struct termios *t);
243static int scprobe(struct isa_device *dev);
244static int scvidprobe(int unit, int flags);
245static int sckbdprobe(int unit, int flags);
246static void scstart(struct tty *tp);
247static void scmousestart(struct tty *tp);
248static void scinit(void);
249static void scshutdown(int howto, void *arg);
250static u_int scgetc(u_int flags);
251#define SCGETC_CN 1
252#define SCGETC_NONBLOCK 2
253static void sccnupdate(scr_stat *scp);
254static scr_stat *alloc_scp(void);
255static void init_scp(scr_stat *scp);
256static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark);
257static int get_scr_num(void);
258static timeout_t scrn_timer;
259static void scrn_update(scr_stat *scp, int show_cursor);
260static void scrn_saver(void (*saver)(int), int blank);
261static void stop_scrn_saver(void (*saver)(int));
262static int wait_scrn_saver_stop(void);
263static int switch_scr(scr_stat *scp, u_int next_scr);
264static void exchange_scr(void);
265static void scan_esc(scr_stat *scp, u_char c);
266static void ansi_put(scr_stat *scp, u_char *buf, int len);
267static void draw_cursor_image(scr_stat *scp);
268static void remove_cursor_image(scr_stat *scp);
269static void move_crsr(scr_stat *scp, int x, int y);
270static u_char *get_fstr(u_int c, u_int *len);
271static void history_to_screen(scr_stat *scp);
272static int history_up_line(scr_stat *scp);
273static int history_down_line(scr_stat *scp);
274static int mask2attr(struct term_stat *term);
275static void set_keyboard(int command, int data);
276static void update_leds(int which);
277static void set_destructive_cursor(scr_stat *scp);
278static void set_mouse_pos(scr_stat *scp);
279static int skip_spc_right(scr_stat *scp, u_short *p);
280static int skip_spc_left(scr_stat *scp, u_short *p);
281static void mouse_cut(scr_stat *scp);
282static void mouse_cut_start(scr_stat *scp);
283static void mouse_cut_end(scr_stat *scp);
284static void mouse_cut_word(scr_stat *scp);
285static void mouse_cut_line(scr_stat *scp);
286static void mouse_cut_extend(scr_stat *scp);
287static void mouse_paste(scr_stat *scp);
288static void draw_mouse_image(scr_stat *scp);
289static void remove_mouse_image(scr_stat *scp);
290static void draw_cutmarking(scr_stat *scp);
291static void remove_cutmarking(scr_stat *scp);
292static void do_bell(scr_stat *scp, int pitch, int duration);
293static timeout_t blink_screen;
294#ifdef SC_SPLASH_SCREEN
295static void scsplash_init(scr_stat *scp);
125
126static default_attr user_default = {
127 (FG_LIGHTGREY | BG_BLACK) << 8,
128 (FG_BLACK | BG_LIGHTGREY) << 8
129};
130
131static default_attr kernel_default = {
132 (FG_WHITE | BG_BLACK) << 8,
133 (FG_BLACK | BG_LIGHTGREY) << 8
134};
135
136static scr_stat main_console;
137static scr_stat *console[MAXCONS];
138#ifdef DEVFS
139static void *sc_devfs_token[MAXCONS];
140static void *sc_mouse_devfs_token;
141static void *sc_console_devfs_token;
142#endif
143 scr_stat *cur_console;
144static scr_stat *new_scp, *old_scp;
145static term_stat kernel_console;
146static default_attr *current_default;
147static int flags = 0;
148static int sc_port = IO_KBD;
149static KBDC sc_kbdc = NULL;
150static char init_done = COLD;
151static u_short sc_buffer[ROW*COL];
152static char shutdown_in_progress = FALSE;
153static char font_loading_in_progress = FALSE;
154static char switch_in_progress = FALSE;
155static char write_in_progress = FALSE;
156static char blink_in_progress = FALSE;
157static int blinkrate = 0;
158 u_int crtc_addr = MONO_BASE;
159 char crtc_type = KD_MONO;
160 char crtc_vga = FALSE;
161static int adp_flags = 0;
162static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0;
163static u_char accents = 0;
164static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0;
165static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab);
166static int delayed_next_scr = FALSE;
167static long scrn_blank_time = 0; /* screen saver timeout value */
168 int scrn_blanked = 0; /* screen saver active flag */
169static long scrn_time_stamp;
170static int saver_mode = CONS_LKM_SAVER; /* LKM/user saver */
171static int run_scrn_saver = FALSE; /* should run the saver? */
172static int scrn_idle = FALSE; /* about to run the saver */
173 u_char scr_map[256];
174 u_char scr_rmap[256];
175static int initial_video_mode; /* initial video mode # */
176static int bios_video_mode; /* video mode # set by BIOS */
177 int fonts_loaded = 0
178#ifdef STD8X16FONT
179 | FONT_16
180#endif
181 ;
182
183 u_char font_8[256*8];
184 u_char font_14[256*14];
185#ifdef STD8X16FONT
186extern
187#endif
188 u_char font_16[256*16];
189 u_char palette[256*3];
190static u_char *cut_buffer = NULL;
191static int cut_buffer_size = 0;
192static int mouse_level = 0; /* sysmouse protocol level */
193static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 };
194static u_short mouse_and_mask[16] = {
195 0xc000, 0xe000, 0xf000, 0xf800,
196 0xfc00, 0xfe00, 0xff00, 0xff80,
197 0xfe00, 0x1e00, 0x1f00, 0x0f00,
198 0x0f00, 0x0000, 0x0000, 0x0000
199 };
200static u_short mouse_or_mask[16] = {
201 0x0000, 0x4000, 0x6000, 0x7000,
202 0x7800, 0x7c00, 0x7e00, 0x6800,
203 0x0c00, 0x0c00, 0x0600, 0x0600,
204 0x0000, 0x0000, 0x0000, 0x0000
205 };
206
207 int sc_history_size = SC_HISTORY_SIZE;
208static int extra_history_size =
209 SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS;
210
211static void none_saver(int blank) { }
212static void (*current_saver)(int blank) = none_saver;
213static void (*default_saver)(int blank) = none_saver;
214 int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data,
215 int flag, struct proc *p) = NULL;
216
217static int sticky_splash = FALSE;
218
219/* OS specific stuff */
220#ifdef not_yet_done
221#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x]))
222struct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS]))
223struct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1]))
224struct tty *sccons[MAXCONS+2];
225#else
226#define VIRTUAL_TTY(x) &sccons[x]
227#define CONSOLE_TTY &sccons[MAXCONS]
228#define MOUSE_TTY &sccons[MAXCONS+1]
229static struct tty sccons[MAXCONS+2];
230#endif
231#define SC_MOUSE 128
232#define SC_CONSOLE 255
233u_short *Crtat;
234static const int nsccons = MAXCONS+2;
235
236#define WRAPHIST(scp, pointer, offset)\
237 ((scp->history) + ((((pointer) - (scp->history)) + (scp->history_size)\
238 + (offset)) % (scp->history_size)))
239#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
240
241/* prototypes */
242static int scattach(struct isa_device *dev);
243static int scparam(struct tty *tp, struct termios *t);
244static int scprobe(struct isa_device *dev);
245static int scvidprobe(int unit, int flags);
246static int sckbdprobe(int unit, int flags);
247static void scstart(struct tty *tp);
248static void scmousestart(struct tty *tp);
249static void scinit(void);
250static void scshutdown(int howto, void *arg);
251static u_int scgetc(u_int flags);
252#define SCGETC_CN 1
253#define SCGETC_NONBLOCK 2
254static void sccnupdate(scr_stat *scp);
255static scr_stat *alloc_scp(void);
256static void init_scp(scr_stat *scp);
257static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark);
258static int get_scr_num(void);
259static timeout_t scrn_timer;
260static void scrn_update(scr_stat *scp, int show_cursor);
261static void scrn_saver(void (*saver)(int), int blank);
262static void stop_scrn_saver(void (*saver)(int));
263static int wait_scrn_saver_stop(void);
264static int switch_scr(scr_stat *scp, u_int next_scr);
265static void exchange_scr(void);
266static void scan_esc(scr_stat *scp, u_char c);
267static void ansi_put(scr_stat *scp, u_char *buf, int len);
268static void draw_cursor_image(scr_stat *scp);
269static void remove_cursor_image(scr_stat *scp);
270static void move_crsr(scr_stat *scp, int x, int y);
271static u_char *get_fstr(u_int c, u_int *len);
272static void history_to_screen(scr_stat *scp);
273static int history_up_line(scr_stat *scp);
274static int history_down_line(scr_stat *scp);
275static int mask2attr(struct term_stat *term);
276static void set_keyboard(int command, int data);
277static void update_leds(int which);
278static void set_destructive_cursor(scr_stat *scp);
279static void set_mouse_pos(scr_stat *scp);
280static int skip_spc_right(scr_stat *scp, u_short *p);
281static int skip_spc_left(scr_stat *scp, u_short *p);
282static void mouse_cut(scr_stat *scp);
283static void mouse_cut_start(scr_stat *scp);
284static void mouse_cut_end(scr_stat *scp);
285static void mouse_cut_word(scr_stat *scp);
286static void mouse_cut_line(scr_stat *scp);
287static void mouse_cut_extend(scr_stat *scp);
288static void mouse_paste(scr_stat *scp);
289static void draw_mouse_image(scr_stat *scp);
290static void remove_mouse_image(scr_stat *scp);
291static void draw_cutmarking(scr_stat *scp);
292static void remove_cutmarking(scr_stat *scp);
293static void do_bell(scr_stat *scp, int pitch, int duration);
294static timeout_t blink_screen;
295#ifdef SC_SPLASH_SCREEN
296static void scsplash_init(scr_stat *scp);
297static void scsplash_term(scr_stat *scp);
296static void scsplash_saver(int show);
297#define scsplash_stick(stick) (sticky_splash = (stick))
298#else
299#define scsplash_stick(stick)
300#endif
301
302struct isa_driver scdriver = {
303 scprobe, scattach, "sc", 1
304};
305
306static d_open_t scopen;
307static d_close_t scclose;
308static d_read_t scread;
309static d_write_t scwrite;
310static d_ioctl_t scioctl;
311 d_devtotty_t scdevtotty;
312static d_mmap_t scmmap;
313
314#define CDEV_MAJOR 12
315static struct cdevsw sc_cdevsw = {
316 scopen, scclose, scread, scwrite,
317 scioctl, nullstop, noreset, scdevtotty,
318 ttpoll, scmmap, nostrategy, "sc",
319 NULL, -1, nodump, nopsize,
320 D_TTY,
321};
322
323/*
324 * These functions need to be before calls to them so they can be inlined.
325 */
326static void
327draw_cursor_image(scr_stat *scp)
328{
298static void scsplash_saver(int show);
299#define scsplash_stick(stick) (sticky_splash = (stick))
300#else
301#define scsplash_stick(stick)
302#endif
303
304struct isa_driver scdriver = {
305 scprobe, scattach, "sc", 1
306};
307
308static d_open_t scopen;
309static d_close_t scclose;
310static d_read_t scread;
311static d_write_t scwrite;
312static d_ioctl_t scioctl;
313 d_devtotty_t scdevtotty;
314static d_mmap_t scmmap;
315
316#define CDEV_MAJOR 12
317static struct cdevsw sc_cdevsw = {
318 scopen, scclose, scread, scwrite,
319 scioctl, nullstop, noreset, scdevtotty,
320 ttpoll, scmmap, nostrategy, "sc",
321 NULL, -1, nodump, nopsize,
322 D_TTY,
323};
324
325/*
326 * These functions need to be before calls to them so they can be inlined.
327 */
328static void
329draw_cursor_image(scr_stat *scp)
330{
329 u_short cursor_image, *ptr = Crtat + (scp->cursor_pos - scp->scr_buf);
331 u_short cursor_image;
332 u_short *ptr;
330 u_short prev_image;
331
332 if (ISPIXELSC(scp)) {
333 sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf,
334 scp->cursor_pos - scp->scr_buf, 1);
335 return;
336 }
337
333 u_short prev_image;
334
335 if (ISPIXELSC(scp)) {
336 sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf,
337 scp->cursor_pos - scp->scr_buf, 1);
338 return;
339 }
340
341 ptr = (u_short *)(get_adapter(scp)->va_window)
342 + (scp->cursor_pos - scp->scr_buf);
343
338 /* do we have a destructive cursor ? */
339 if (flags & CHAR_CURSOR) {
340 prev_image = scp->cursor_saveunder;
341 cursor_image = *ptr & 0x00ff;
342 if (cursor_image == DEAD_CHAR)
343 cursor_image = prev_image & 0x00ff;
344 cursor_image |= *(scp->cursor_pos) & 0xff00;
345 scp->cursor_saveunder = cursor_image;
346 /* update the cursor bitmap if the char under the cursor has changed */
347 if (prev_image != cursor_image)
348 set_destructive_cursor(scp);
349 /* modify cursor_image */
350 if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){
351 /*
352 * When the mouse pointer is at the same position as the cursor,
353 * the cursor bitmap needs to be updated even if the char under
354 * the cursor hasn't changed, because the mouse pionter may
355 * have moved by a few dots within the cursor cel.
356 */
357 if ((prev_image == cursor_image)
358 && (cursor_image != *(scp->cursor_pos)))
359 set_destructive_cursor(scp);
360 cursor_image &= 0xff00;
361 cursor_image |= DEAD_CHAR;
362 }
363 } else {
364 cursor_image = (*(ptr) & 0x00ff) | *(scp->cursor_pos) & 0xff00;
365 scp->cursor_saveunder = cursor_image;
366 if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){
367 if ((cursor_image & 0x7000) == 0x7000) {
368 cursor_image &= 0x8fff;
369 if(!(cursor_image & 0x0700))
370 cursor_image |= 0x0700;
371 } else {
372 cursor_image |= 0x7000;
373 if ((cursor_image & 0x0700) == 0x0700)
374 cursor_image &= 0xf0ff;
375 }
376 }
377 }
378 *ptr = cursor_image;
379}
380
381static void
382remove_cursor_image(scr_stat *scp)
383{
384 if (ISPIXELSC(scp))
385 sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf,
344 /* do we have a destructive cursor ? */
345 if (flags & CHAR_CURSOR) {
346 prev_image = scp->cursor_saveunder;
347 cursor_image = *ptr & 0x00ff;
348 if (cursor_image == DEAD_CHAR)
349 cursor_image = prev_image & 0x00ff;
350 cursor_image |= *(scp->cursor_pos) & 0xff00;
351 scp->cursor_saveunder = cursor_image;
352 /* update the cursor bitmap if the char under the cursor has changed */
353 if (prev_image != cursor_image)
354 set_destructive_cursor(scp);
355 /* modify cursor_image */
356 if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){
357 /*
358 * When the mouse pointer is at the same position as the cursor,
359 * the cursor bitmap needs to be updated even if the char under
360 * the cursor hasn't changed, because the mouse pionter may
361 * have moved by a few dots within the cursor cel.
362 */
363 if ((prev_image == cursor_image)
364 && (cursor_image != *(scp->cursor_pos)))
365 set_destructive_cursor(scp);
366 cursor_image &= 0xff00;
367 cursor_image |= DEAD_CHAR;
368 }
369 } else {
370 cursor_image = (*(ptr) & 0x00ff) | *(scp->cursor_pos) & 0xff00;
371 scp->cursor_saveunder = cursor_image;
372 if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){
373 if ((cursor_image & 0x7000) == 0x7000) {
374 cursor_image &= 0x8fff;
375 if(!(cursor_image & 0x0700))
376 cursor_image |= 0x0700;
377 } else {
378 cursor_image |= 0x7000;
379 if ((cursor_image & 0x0700) == 0x0700)
380 cursor_image &= 0xf0ff;
381 }
382 }
383 }
384 *ptr = cursor_image;
385}
386
387static void
388remove_cursor_image(scr_stat *scp)
389{
390 if (ISPIXELSC(scp))
391 sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf,
386 scp->cursor_oldpos - scp->scr_buf, 0);
392 scp->cursor_oldpos - scp->scr_buf, 0);
387 else
393 else
388 *(Crtat + (scp->cursor_oldpos - scp->scr_buf)) = scp->cursor_saveunder;
394 *((u_short *)(get_adapter(scp)->va_window)
395 + (scp->cursor_oldpos - scp->scr_buf))
396 = scp->cursor_saveunder;
389}
390
391static void
392move_crsr(scr_stat *scp, int x, int y)
393{
394 if (x < 0)
395 x = 0;
396 if (y < 0)
397 y = 0;
398 if (x >= scp->xsize)
399 x = scp->xsize-1;
400 if (y >= scp->ysize)
401 y = scp->ysize-1;
402 scp->xpos = x;
403 scp->ypos = y;
404 scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos;
405}
406
407static int
408scprobe(struct isa_device *dev)
409{
410 if (!scvidprobe(dev->id_unit, dev->id_flags)) {
411 if (bootverbose)
412 printf("sc%d: no video adapter is found.\n", dev->id_unit);
413 return (0);
414 }
397}
398
399static void
400move_crsr(scr_stat *scp, int x, int y)
401{
402 if (x < 0)
403 x = 0;
404 if (y < 0)
405 y = 0;
406 if (x >= scp->xsize)
407 x = scp->xsize-1;
408 if (y >= scp->ysize)
409 y = scp->ysize-1;
410 scp->xpos = x;
411 scp->ypos = y;
412 scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos;
413}
414
415static int
416scprobe(struct isa_device *dev)
417{
418 if (!scvidprobe(dev->id_unit, dev->id_flags)) {
419 if (bootverbose)
420 printf("sc%d: no video adapter is found.\n", dev->id_unit);
421 return (0);
422 }
415 (*biosvidsw.diag)(bootverbose);
423
416#if defined(VESA) && defined(VM86)
417 if (vesa_load())
418 return FALSE;
424#if defined(VESA) && defined(VM86)
425 if (vesa_load())
426 return FALSE;
419 (*biosvidsw.diag)(bootverbose);
420#endif
421
427#endif
428
429 (*biosvidsw.diag)(bootverbose);
430
422 sc_port = dev->id_iobase;
423 if (sckbdprobe(dev->id_unit, dev->id_flags))
424 return (IO_KBDSIZE);
425 else
426 return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE);
427}
428
429/* probe video adapters, return TRUE if found */
430static int
431scvidprobe(int unit, int flags)
432{
433 video_adapter_t *adp;
434
435 /* do this test only once */
436 if (init_done != COLD)
437 return (crtc_type != -1);
438
439 if ((*biosvidsw.init)() <= 0)
440 return FALSE;
441 if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL)
442 return FALSE;
443
444 crtc_type = adp->va_type;
445 crtc_vga = (crtc_type == KD_VGA);
446 crtc_addr = adp->va_crtc_addr;
447 Crtat = (u_short *)adp->va_window;
448 adp_flags = adp->va_flags;
449 initial_video_mode = adp->va_initial_mode;
450 bios_video_mode = adp->va_initial_bios_mode;
451
452 return TRUE;
453}
454
455/* probe the keyboard, return TRUE if found */
456static int
457sckbdprobe(int unit, int flags)
458{
459 int codeset;
460 int c = -1;
461 int m;
462 int res, id;
463
464 sc_kbdc = kbdc_open(sc_port);
465
466 if (!kbdc_lock(sc_kbdc, TRUE)) {
467 /* driver error? */
468 printf("sc%d: unable to lock the controller.\n", unit);
469 return ((flags & DETECT_KBD) ? FALSE : TRUE);
470 }
471
472 /* discard anything left after UserConfig */
473 empty_both_buffers(sc_kbdc, 10);
474
475 /* save the current keyboard controller command byte */
476 m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS;
477 c = get_controller_command_byte(sc_kbdc);
478 if (c == -1) {
479 /* CONTROLLER ERROR */
480 printf("sc%d: unable to get the current command byte value.\n", unit);
481 goto fail;
482 }
483 if (bootverbose)
484 printf("sc%d: the current keyboard controller command byte %04x\n",
485 unit, c);
486#if 0
487 /* override the keyboard lock switch */
488 c |= KBD_OVERRIDE_KBD_LOCK;
489#endif
490
491 /*
492 * The keyboard may have been screwed up by the boot block.
493 * We may just be able to recover from error by testing the controller
494 * and the keyboard port. The controller command byte needs to be saved
495 * before this recovery operation, as some controllers seem to set
496 * the command byte to particular values.
497 */
498 test_controller(sc_kbdc);
499 test_kbd_port(sc_kbdc);
500
501 /* enable the keyboard port, but disable the keyboard intr. */
502 if (!set_controller_command_byte(sc_kbdc,
503 KBD_KBD_CONTROL_BITS,
504 KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) {
505 /* CONTROLLER ERROR
506 * there is very little we can do...
507 */
508 printf("sc%d: unable to set the command byte.\n", unit);
509 goto fail;
510 }
511
512 /*
513 * Check if we have an XT keyboard before we attempt to reset it.
514 * The procedure assumes that the keyboard and the controller have
515 * been set up properly by BIOS and have not been messed up
516 * during the boot process.
517 */
518 codeset = -1;
519 if (flags & XT_KEYBD)
520 /* the user says there is a XT keyboard */
521 codeset = 1;
522#ifdef DETECT_XT_KEYBOARD
523 else if ((c & KBD_TRANSLATION) == 0) {
524 /* SET_SCANCODE_SET is not always supported; ignore error */
525 if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0)
526 == KBD_ACK)
527 codeset = read_kbd_data(sc_kbdc);
528 }
529 if (bootverbose)
530 printf("sc%d: keyboard scancode set %d\n", unit, codeset);
531#endif /* DETECT_XT_KEYBOARD */
532
533 if (flags & KBD_NORESET) {
534 write_kbd_command(sc_kbdc, KBDC_ECHO);
535 if (read_kbd_data(sc_kbdc) != KBD_ECHO) {
536 empty_both_buffers(sc_kbdc, 10);
537 test_controller(sc_kbdc);
538 test_kbd_port(sc_kbdc);
539 if (bootverbose)
540 printf("sc%d: failed to get response from the keyboard.\n",
541 unit);
542 goto fail;
543 }
544 } else {
545 /* reset keyboard hardware */
546 if (!reset_kbd(sc_kbdc)) {
547 /* KEYBOARD ERROR
548 * Keyboard reset may fail either because the keyboard doen't
549 * exist, or because the keyboard doesn't pass the self-test,
550 * or the keyboard controller on the motherboard and the keyboard
551 * somehow fail to shake hands. It is just possible, particularly
552 * in the last case, that the keyoard controller may be left
553 * in a hung state. test_controller() and test_kbd_port() appear
554 * to bring the keyboard controller back (I don't know why and
555 * how, though.)
556 */
557 empty_both_buffers(sc_kbdc, 10);
558 test_controller(sc_kbdc);
559 test_kbd_port(sc_kbdc);
560 /* We could disable the keyboard port and interrupt... but,
561 * the keyboard may still exist (see above).
562 */
563 if (bootverbose)
564 printf("sc%d: failed to reset the keyboard.\n", unit);
565 goto fail;
566 }
567 }
568
569 /*
570 * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards
571 * such as those on the IBM ThinkPad laptop computers can be used
572 * with the standard console driver.
573 */
574 if (codeset == 1) {
575 if (send_kbd_command_and_data(
576 sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) {
577 /* XT kbd doesn't need scan code translation */
578 c &= ~KBD_TRANSLATION;
579 } else {
580 /* KEYBOARD ERROR
581 * The XT kbd isn't usable unless the proper scan code set
582 * is selected.
583 */
584 printf("sc%d: unable to set the XT keyboard mode.\n", unit);
585 goto fail;
586 }
587 }
588 /* enable the keyboard port and intr. */
589 if (!set_controller_command_byte(sc_kbdc,
590 KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK,
591 (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK))
592 | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) {
593 /* CONTROLLER ERROR
594 * This is serious; we are left with the disabled keyboard intr.
595 */
596 printf("sc%d: unable to enable the keyboard port and intr.\n", unit);
597 goto fail;
598 }
599
600 /* Get the ID of the keyboard, if any */
601 empty_kbd_buffer(sc_kbdc, 5);
602 res = send_kbd_command(sc_kbdc, KBDC_SEND_DEV_ID);
603 if (res == KBD_ACK) {
604 /* 10ms delay */
605 DELAY(10000);
606 id = (read_kbd_data(sc_kbdc) << 8) | read_kbd_data(sc_kbdc);
607 if (bootverbose)
608 printf("sc%d: keyboard device ID: %04x\n", unit, id);
609 }
610
611 kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS),
612 kbdc_lock(sc_kbdc, FALSE);
613 return TRUE;
614
615fail:
616 if (c != -1)
617 /* try to restore the command byte as before, if possible */
618 set_controller_command_byte(sc_kbdc, 0xff, c);
619 kbdc_set_device_mask(sc_kbdc,
620 (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS);
621 kbdc_lock(sc_kbdc, FALSE);
622 return FALSE;
623}
624
625#if NAPM > 0
626static int
627scresume(void *dummy)
628{
629 shfts = ctls = alts = agrs = metas = accents = 0;
630 return 0;
631}
632#endif
633
634static int
635scattach(struct isa_device *dev)
636{
637 scr_stat *scp;
638 video_info_t info;
639 dev_t cdev = makedev(CDEV_MAJOR, 0);
640#ifdef DEVFS
641 int vc;
642#endif
643
644 scinit();
645 flags = dev->id_flags;
646 if (!ISFONTAVAIL(adp_flags))
647 flags &= ~CHAR_CURSOR;
648
649 scp = console[0];
650
651 /* copy temporary buffer to final buffer */
652 scp->scr_buf = NULL;
653 sc_alloc_scr_buffer(scp, FALSE, FALSE);
654 bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short));
655
656 /* cut buffer is available only when the mouse pointer is used */
657 if (ISMOUSEAVAIL(adp_flags))
658 sc_alloc_cut_buffer(scp, FALSE);
659
660 /* initialize history buffer & pointers */
661 sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE);
662
663#if defined(VESA) && defined(VM86)
664 if ((flags & VESA800X600)
665 && ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) {
431 sc_port = dev->id_iobase;
432 if (sckbdprobe(dev->id_unit, dev->id_flags))
433 return (IO_KBDSIZE);
434 else
435 return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE);
436}
437
438/* probe video adapters, return TRUE if found */
439static int
440scvidprobe(int unit, int flags)
441{
442 video_adapter_t *adp;
443
444 /* do this test only once */
445 if (init_done != COLD)
446 return (crtc_type != -1);
447
448 if ((*biosvidsw.init)() <= 0)
449 return FALSE;
450 if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL)
451 return FALSE;
452
453 crtc_type = adp->va_type;
454 crtc_vga = (crtc_type == KD_VGA);
455 crtc_addr = adp->va_crtc_addr;
456 Crtat = (u_short *)adp->va_window;
457 adp_flags = adp->va_flags;
458 initial_video_mode = adp->va_initial_mode;
459 bios_video_mode = adp->va_initial_bios_mode;
460
461 return TRUE;
462}
463
464/* probe the keyboard, return TRUE if found */
465static int
466sckbdprobe(int unit, int flags)
467{
468 int codeset;
469 int c = -1;
470 int m;
471 int res, id;
472
473 sc_kbdc = kbdc_open(sc_port);
474
475 if (!kbdc_lock(sc_kbdc, TRUE)) {
476 /* driver error? */
477 printf("sc%d: unable to lock the controller.\n", unit);
478 return ((flags & DETECT_KBD) ? FALSE : TRUE);
479 }
480
481 /* discard anything left after UserConfig */
482 empty_both_buffers(sc_kbdc, 10);
483
484 /* save the current keyboard controller command byte */
485 m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS;
486 c = get_controller_command_byte(sc_kbdc);
487 if (c == -1) {
488 /* CONTROLLER ERROR */
489 printf("sc%d: unable to get the current command byte value.\n", unit);
490 goto fail;
491 }
492 if (bootverbose)
493 printf("sc%d: the current keyboard controller command byte %04x\n",
494 unit, c);
495#if 0
496 /* override the keyboard lock switch */
497 c |= KBD_OVERRIDE_KBD_LOCK;
498#endif
499
500 /*
501 * The keyboard may have been screwed up by the boot block.
502 * We may just be able to recover from error by testing the controller
503 * and the keyboard port. The controller command byte needs to be saved
504 * before this recovery operation, as some controllers seem to set
505 * the command byte to particular values.
506 */
507 test_controller(sc_kbdc);
508 test_kbd_port(sc_kbdc);
509
510 /* enable the keyboard port, but disable the keyboard intr. */
511 if (!set_controller_command_byte(sc_kbdc,
512 KBD_KBD_CONTROL_BITS,
513 KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) {
514 /* CONTROLLER ERROR
515 * there is very little we can do...
516 */
517 printf("sc%d: unable to set the command byte.\n", unit);
518 goto fail;
519 }
520
521 /*
522 * Check if we have an XT keyboard before we attempt to reset it.
523 * The procedure assumes that the keyboard and the controller have
524 * been set up properly by BIOS and have not been messed up
525 * during the boot process.
526 */
527 codeset = -1;
528 if (flags & XT_KEYBD)
529 /* the user says there is a XT keyboard */
530 codeset = 1;
531#ifdef DETECT_XT_KEYBOARD
532 else if ((c & KBD_TRANSLATION) == 0) {
533 /* SET_SCANCODE_SET is not always supported; ignore error */
534 if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0)
535 == KBD_ACK)
536 codeset = read_kbd_data(sc_kbdc);
537 }
538 if (bootverbose)
539 printf("sc%d: keyboard scancode set %d\n", unit, codeset);
540#endif /* DETECT_XT_KEYBOARD */
541
542 if (flags & KBD_NORESET) {
543 write_kbd_command(sc_kbdc, KBDC_ECHO);
544 if (read_kbd_data(sc_kbdc) != KBD_ECHO) {
545 empty_both_buffers(sc_kbdc, 10);
546 test_controller(sc_kbdc);
547 test_kbd_port(sc_kbdc);
548 if (bootverbose)
549 printf("sc%d: failed to get response from the keyboard.\n",
550 unit);
551 goto fail;
552 }
553 } else {
554 /* reset keyboard hardware */
555 if (!reset_kbd(sc_kbdc)) {
556 /* KEYBOARD ERROR
557 * Keyboard reset may fail either because the keyboard doen't
558 * exist, or because the keyboard doesn't pass the self-test,
559 * or the keyboard controller on the motherboard and the keyboard
560 * somehow fail to shake hands. It is just possible, particularly
561 * in the last case, that the keyoard controller may be left
562 * in a hung state. test_controller() and test_kbd_port() appear
563 * to bring the keyboard controller back (I don't know why and
564 * how, though.)
565 */
566 empty_both_buffers(sc_kbdc, 10);
567 test_controller(sc_kbdc);
568 test_kbd_port(sc_kbdc);
569 /* We could disable the keyboard port and interrupt... but,
570 * the keyboard may still exist (see above).
571 */
572 if (bootverbose)
573 printf("sc%d: failed to reset the keyboard.\n", unit);
574 goto fail;
575 }
576 }
577
578 /*
579 * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards
580 * such as those on the IBM ThinkPad laptop computers can be used
581 * with the standard console driver.
582 */
583 if (codeset == 1) {
584 if (send_kbd_command_and_data(
585 sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) {
586 /* XT kbd doesn't need scan code translation */
587 c &= ~KBD_TRANSLATION;
588 } else {
589 /* KEYBOARD ERROR
590 * The XT kbd isn't usable unless the proper scan code set
591 * is selected.
592 */
593 printf("sc%d: unable to set the XT keyboard mode.\n", unit);
594 goto fail;
595 }
596 }
597 /* enable the keyboard port and intr. */
598 if (!set_controller_command_byte(sc_kbdc,
599 KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK,
600 (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK))
601 | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) {
602 /* CONTROLLER ERROR
603 * This is serious; we are left with the disabled keyboard intr.
604 */
605 printf("sc%d: unable to enable the keyboard port and intr.\n", unit);
606 goto fail;
607 }
608
609 /* Get the ID of the keyboard, if any */
610 empty_kbd_buffer(sc_kbdc, 5);
611 res = send_kbd_command(sc_kbdc, KBDC_SEND_DEV_ID);
612 if (res == KBD_ACK) {
613 /* 10ms delay */
614 DELAY(10000);
615 id = (read_kbd_data(sc_kbdc) << 8) | read_kbd_data(sc_kbdc);
616 if (bootverbose)
617 printf("sc%d: keyboard device ID: %04x\n", unit, id);
618 }
619
620 kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS),
621 kbdc_lock(sc_kbdc, FALSE);
622 return TRUE;
623
624fail:
625 if (c != -1)
626 /* try to restore the command byte as before, if possible */
627 set_controller_command_byte(sc_kbdc, 0xff, c);
628 kbdc_set_device_mask(sc_kbdc,
629 (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS);
630 kbdc_lock(sc_kbdc, FALSE);
631 return FALSE;
632}
633
634#if NAPM > 0
635static int
636scresume(void *dummy)
637{
638 shfts = ctls = alts = agrs = metas = accents = 0;
639 return 0;
640}
641#endif
642
643static int
644scattach(struct isa_device *dev)
645{
646 scr_stat *scp;
647 video_info_t info;
648 dev_t cdev = makedev(CDEV_MAJOR, 0);
649#ifdef DEVFS
650 int vc;
651#endif
652
653 scinit();
654 flags = dev->id_flags;
655 if (!ISFONTAVAIL(adp_flags))
656 flags &= ~CHAR_CURSOR;
657
658 scp = console[0];
659
660 /* copy temporary buffer to final buffer */
661 scp->scr_buf = NULL;
662 sc_alloc_scr_buffer(scp, FALSE, FALSE);
663 bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short));
664
665 /* cut buffer is available only when the mouse pointer is used */
666 if (ISMOUSEAVAIL(adp_flags))
667 sc_alloc_cut_buffer(scp, FALSE);
668
669 /* initialize history buffer & pointers */
670 sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE);
671
672#if defined(VESA) && defined(VM86)
673 if ((flags & VESA800X600)
674 && ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) {
675#ifdef SC_SPLASH_SCREEN
676 scsplash_term(scp);
677#endif
666 sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
667 sc_set_pixel_mode(scp, NULL, COL, ROW, 16);
668 initial_video_mode = M_VESA_800x600;
678 sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
679 sc_set_pixel_mode(scp, NULL, COL, ROW, 16);
680 initial_video_mode = M_VESA_800x600;
681#ifdef SC_SPLASH_SCREEN
682 scsplash_init(scp);
683#endif
669 }
670#endif /* VESA && VM86 */
671
672 /* initialize cursor stuff */
673 if (!ISGRAPHSC(scp))
674 draw_cursor_image(scp);
675
676 /* get screen update going */
677 scrn_timer((void *)TRUE);
678
679 update_leds(scp->status);
680
681 printf("sc%d: ", dev->id_unit);
682 switch(crtc_type) {
683 case KD_VGA:
684 printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono");
685 break;
686 case KD_EGA:
687 printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono");
688 break;
689 case KD_CGA:
690 printf("CGA");
691 break;
692 case KD_MONO:
693 case KD_HERCULES:
694 default:
695 printf("MDA/Hercules");
696 break;
697 }
698 printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags);
699
700#if NAPM > 0
701 scp->r_hook.ah_fun = scresume;
702 scp->r_hook.ah_arg = NULL;
703 scp->r_hook.ah_name = "system keyboard";
704 scp->r_hook.ah_order = APM_MID_ORDER;
705 apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook);
706#endif
707
708 at_shutdown(scshutdown, NULL, SHUTDOWN_PRE_SYNC);
709
710 cdevsw_add(&cdev, &sc_cdevsw, NULL);
711
712#ifdef DEVFS
713 for (vc = 0; vc < MAXCONS; vc++)
714 sc_devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc, DV_CHR,
715 UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc);
716 sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE, DV_CHR,
717 UID_ROOT, GID_WHEEL, 0600, "sysmouse");
718 sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLE, DV_CHR,
719 UID_ROOT, GID_WHEEL, 0600, "consolectl");
720#endif
721 return 0;
722}
723
724struct tty
725*scdevtotty(dev_t dev)
726{
727 int unit = minor(dev);
728
729 if (init_done == COLD)
730 return(NULL);
731 if (unit == SC_CONSOLE)
732 return CONSOLE_TTY;
733 if (unit == SC_MOUSE)
734 return MOUSE_TTY;
735 if (unit >= MAXCONS || unit < 0)
736 return(NULL);
737 return VIRTUAL_TTY(unit);
738}
739
740int
741scopen(dev_t dev, int flag, int mode, struct proc *p)
742{
743 struct tty *tp = scdevtotty(dev);
744
745 if (!tp)
746 return(ENXIO);
747
748 tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart;
749 tp->t_param = scparam;
750 tp->t_dev = dev;
751 if (!(tp->t_state & TS_ISOPEN)) {
752 ttychars(tp);
753 /* Use the current setting of the <-- key as default VERASE. */
754 /* If the Delete key is preferable, an stty is necessary */
755 tp->t_cc[VERASE] = key_map.key[0x0e].map[0];
756 tp->t_iflag = TTYDEF_IFLAG;
757 tp->t_oflag = TTYDEF_OFLAG;
758 tp->t_cflag = TTYDEF_CFLAG;
759 tp->t_lflag = TTYDEF_LFLAG;
760 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
761 scparam(tp, &tp->t_termios);
762 (*linesw[tp->t_line].l_modem)(tp, 1);
763 if (minor(dev) == SC_MOUSE)
764 mouse_level = 0; /* XXX */
765 }
766 else
767 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
768 return(EBUSY);
769 if (minor(dev) < MAXCONS && !console[minor(dev)]) {
770 console[minor(dev)] = alloc_scp();
771 if (ISGRAPHSC(console[minor(dev)]))
772 sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16);
773 }
774 if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) {
775 tp->t_winsize.ws_col = console[minor(dev)]->xsize;
776 tp->t_winsize.ws_row = console[minor(dev)]->ysize;
777 }
778 return ((*linesw[tp->t_line].l_open)(dev, tp));
779}
780
781int
782scclose(dev_t dev, int flag, int mode, struct proc *p)
783{
784 struct tty *tp = scdevtotty(dev);
785 struct scr_stat *scp;
786
787 if (!tp)
788 return(ENXIO);
789 if (minor(dev) < MAXCONS) {
790 scp = sc_get_scr_stat(tp->t_dev);
791 if (scp->status & SWITCH_WAIT_ACQ)
792 wakeup((caddr_t)&scp->smode);
793#if not_yet_done
794 if (scp == &main_console) {
795 scp->pid = 0;
796 scp->proc = NULL;
797 scp->smode.mode = VT_AUTO;
798 }
799 else {
800 free(scp->scr_buf, M_DEVBUF);
801 if (scp->history != NULL) {
802 free(scp->history, M_DEVBUF);
803 if (scp->history_size / scp->xsize
804 > imax(sc_history_size, scp->ysize))
805 extra_history_size += scp->history_size / scp->xsize
806 - imax(sc_history_size, scp->ysize);
807 }
808 free(scp, M_DEVBUF);
809 console[minor(dev)] = NULL;
810 }
811#else
812 scp->pid = 0;
813 scp->proc = NULL;
814 scp->smode.mode = VT_AUTO;
815#endif
816 }
817 spltty();
818 (*linesw[tp->t_line].l_close)(tp, flag);
819 ttyclose(tp);
820 spl0();
821 return(0);
822}
823
824int
825scread(dev_t dev, struct uio *uio, int flag)
826{
827 struct tty *tp = scdevtotty(dev);
828
829 if (!tp)
830 return(ENXIO);
831 return((*linesw[tp->t_line].l_read)(tp, uio, flag));
832}
833
834int
835scwrite(dev_t dev, struct uio *uio, int flag)
836{
837 struct tty *tp = scdevtotty(dev);
838
839 if (!tp)
840 return(ENXIO);
841 return((*linesw[tp->t_line].l_write)(tp, uio, flag));
842}
843
844void
845scintr(int unit)
846{
847 static struct tty *cur_tty;
848 int c, len;
849 u_char *cp;
850
851 /*
852 * Loop while there is still input to get from the keyboard.
853 * I don't think this is nessesary, and it doesn't fix
854 * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX
855 */
856 while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) {
857
858 cur_tty = VIRTUAL_TTY(get_scr_num());
859 if (!(cur_tty->t_state & TS_ISOPEN))
860 if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN))
861 continue;
862
863 switch (c & 0xff00) {
864 case 0x0000: /* normal key */
865 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
866 break;
867 case FKEY: /* function key, return string */
868 if (cp = get_fstr((u_int)c, (u_int *)&len)) {
869 while (len-- > 0)
870 (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty);
871 }
872 break;
873 case MKEY: /* meta is active, prepend ESC */
874 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
875 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
876 break;
877 case BKEY: /* backtab fixed sequence (esc [ Z) */
878 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
879 (*linesw[cur_tty->t_line].l_rint)('[', cur_tty);
880 (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty);
881 break;
882 }
883 }
884
885#if 0
886 if (cur_console->status & MOUSE_ENABLED) {
887 cur_console->status &= ~MOUSE_VISIBLE;
888 remove_mouse_image(cur_console);
889 }
890#else
891 if (cur_console->status & MOUSE_VISIBLE) {
892 remove_mouse_image(cur_console);
893 cur_console->status &= ~MOUSE_VISIBLE;
894 }
895#endif
896}
897
898static int
899scparam(struct tty *tp, struct termios *t)
900{
901 tp->t_ispeed = t->c_ispeed;
902 tp->t_ospeed = t->c_ospeed;
903 tp->t_cflag = t->c_cflag;
904 return 0;
905}
906
907int
908scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
909{
910 int error;
911 u_int i;
912 struct tty *tp;
913 scr_stat *scp;
914 video_adapter_t *adp;
915 int s;
916
917 tp = scdevtotty(dev);
918 if (!tp)
919 return ENXIO;
920 scp = sc_get_scr_stat(tp->t_dev);
921
922 /* If there is a user_ioctl function call that first */
923 if (sc_user_ioctl) {
924 error = (*sc_user_ioctl)(dev, cmd, data, flag, p);
925 if (error != ENOIOCTL)
926 return error;
927 }
928
929 error = sc_vid_ioctl(tp, cmd, data, flag, p);
930 if (error != ENOIOCTL)
931 return error;
932
933 switch (cmd) { /* process console hardware related ioctl's */
934
935 case GIO_ATTR: /* get current attributes */
936 *(int*)data = (scp->term.cur_attr >> 8) & 0xFF;
937 return 0;
938
939 case GIO_COLOR: /* is this a color console ? */
940 *(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0;
941 return 0;
942
943 case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */
944 if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME)
945 return EINVAL;
946 s = spltty();
947 scrn_blank_time = *(int *)data;
948 run_scrn_saver = (scrn_blank_time != 0);
949 splx(s);
950 return 0;
951
952 case CONS_CURSORTYPE: /* set cursor type blink/noblink */
953 if ((*(int*)data) & 0x01)
954 flags |= BLINK_CURSOR;
955 else
956 flags &= ~BLINK_CURSOR;
957 if ((*(int*)data) & 0x02) {
958 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
959 return ENXIO;
960 flags |= CHAR_CURSOR;
961 } else
962 flags &= ~CHAR_CURSOR;
963 /*
964 * The cursor shape is global property; all virtual consoles
965 * are affected. Update the cursor in the current console...
966 */
967 if (!ISGRAPHSC(cur_console)) {
968 remove_cursor_image(cur_console);
969 if (flags & CHAR_CURSOR)
970 set_destructive_cursor(cur_console);
971 draw_cursor_image(cur_console);
972 }
973 return 0;
974
975 case CONS_BELLTYPE: /* set bell type sound/visual */
976 if ((*(int *)data) & 0x01)
977 flags |= VISUAL_BELL;
978 else
979 flags &= ~VISUAL_BELL;
980 if ((*(int *)data) & 0x02)
981 flags |= QUIET_BELL;
982 else
983 flags &= ~QUIET_BELL;
984 return 0;
985
986 case CONS_HISTORY: /* set history size */
987 if (*(int *)data > 0) {
988 int lines; /* buffer size to allocate */
989 int lines0; /* current buffer size */
990
991 lines = imax(*(int *)data, scp->ysize);
992 lines0 = (scp->history != NULL) ?
993 scp->history_size / scp->xsize : scp->ysize;
994 if (lines0 > imax(sc_history_size, scp->ysize))
995 i = lines0 - imax(sc_history_size, scp->ysize);
996 else
997 i = 0;
998 /*
999 * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE
1000 * lines or scp->ysize lines, whichever is larger. A value
1001 * greater than that is allowed, subject to extra_history_size.
1002 */
1003 if (lines > imax(sc_history_size, scp->ysize))
1004 if (lines - imax(sc_history_size, scp->ysize) >
1005 extra_history_size + i)
1006 return EINVAL;
1007 if (cur_console->status & BUFFER_SAVED)
1008 return EBUSY;
1009 sc_alloc_history_buffer(scp, lines, i, TRUE);
1010 return 0;
1011 }
1012 else
1013 return EINVAL;
1014
1015 case CONS_MOUSECTL: /* control mouse arrow */
1016 case OLD_CONS_MOUSECTL:
1017 {
1018 /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */
1019 static butmap[8] = {
1020 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP
1021 | MOUSE_MSC_BUTTON3UP,
1022 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
1023 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
1024 MOUSE_MSC_BUTTON3UP,
1025 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
1026 MOUSE_MSC_BUTTON2UP,
1027 MOUSE_MSC_BUTTON1UP,
1028 0,
1029 };
1030 mouse_info_t *mouse = (mouse_info_t*)data;
1031 mouse_info_t buf;
1032
1033 /* FIXME: */
1034 if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags))
1035 return ENODEV;
1036
1037 if (cmd == OLD_CONS_MOUSECTL) {
1038 static unsigned char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
1039 old_mouse_info_t *old_mouse = (old_mouse_info_t *)data;
1040
1041 mouse = &buf;
1042 mouse->operation = old_mouse->operation;
1043 switch (mouse->operation) {
1044 case MOUSE_MODE:
1045 mouse->u.mode = old_mouse->u.mode;
1046 break;
1047 case MOUSE_SHOW:
1048 case MOUSE_HIDE:
1049 break;
1050 case MOUSE_MOVEABS:
1051 case MOUSE_MOVEREL:
1052 case MOUSE_ACTION:
1053 mouse->u.data.x = old_mouse->u.data.x;
1054 mouse->u.data.y = old_mouse->u.data.y;
1055 mouse->u.data.z = 0;
1056 mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7];
1057 break;
1058 case MOUSE_GETINFO:
1059 old_mouse->u.data.x = scp->mouse_xpos;
1060 old_mouse->u.data.y = scp->mouse_ypos;
1061 old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7];
1062 break;
1063 default:
1064 return EINVAL;
1065 }
1066 }
1067
1068 switch (mouse->operation) {
1069 case MOUSE_MODE:
1070 if (ISSIGVALID(mouse->u.mode.signal)) {
1071 scp->mouse_signal = mouse->u.mode.signal;
1072 scp->mouse_proc = p;
1073 scp->mouse_pid = p->p_pid;
1074 }
1075 else {
1076 scp->mouse_signal = 0;
1077 scp->mouse_proc = NULL;
1078 scp->mouse_pid = 0;
1079 }
1080 return 0;
1081
1082 case MOUSE_SHOW:
1083 if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) {
1084 scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE);
1085 scp->mouse_oldpos = scp->mouse_pos;
1086 mark_all(scp);
1087 return 0;
1088 }
1089 else
1090 return EINVAL;
1091 break;
1092
1093 case MOUSE_HIDE:
1094 if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) {
1095 scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE);
1096 mark_all(scp);
1097 return 0;
1098 }
1099 else
1100 return EINVAL;
1101 break;
1102
1103 case MOUSE_MOVEABS:
1104 scp->mouse_xpos = mouse->u.data.x;
1105 scp->mouse_ypos = mouse->u.data.y;
1106 set_mouse_pos(scp);
1107 break;
1108
1109 case MOUSE_MOVEREL:
1110 scp->mouse_xpos += mouse->u.data.x;
1111 scp->mouse_ypos += mouse->u.data.y;
1112 set_mouse_pos(scp);
1113 break;
1114
1115 case MOUSE_GETINFO:
1116 mouse->u.data.x = scp->mouse_xpos;
1117 mouse->u.data.y = scp->mouse_ypos;
1118 mouse->u.data.z = 0;
1119 mouse->u.data.buttons = scp->mouse_buttons;
1120 return 0;
1121
1122 case MOUSE_ACTION:
1123 case MOUSE_MOTION_EVENT:
1124 /* this should maybe only be settable from /dev/consolectl SOS */
1125 /* send out mouse event on /dev/sysmouse */
1126
1127 mouse_status.dx += mouse->u.data.x;
1128 mouse_status.dy += mouse->u.data.y;
1129 mouse_status.dz += mouse->u.data.z;
1130 if (mouse->operation == MOUSE_ACTION)
1131 mouse_status.button = mouse->u.data.buttons;
1132 mouse_status.flags |=
1133 ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ?
1134 MOUSE_POSCHANGED : 0)
1135 | (mouse_status.obutton ^ mouse_status.button);
1136 if (mouse_status.flags == 0)
1137 return 0;
1138
1139 if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
1140 cur_console->status |= MOUSE_VISIBLE;
1141
1142 if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
1143 u_char buf[MOUSE_SYS_PACKETSIZE];
1144 int j;
1145
1146 /* the first five bytes are compatible with MouseSystems' */
1147 buf[0] = MOUSE_MSC_SYNC
1148 | butmap[mouse_status.button & MOUSE_STDBUTTONS];
1149 j = imax(imin(mouse->u.data.x, 255), -256);
1150 buf[1] = j >> 1;
1151 buf[3] = j - buf[1];
1152 j = -imax(imin(mouse->u.data.y, 255), -256);
1153 buf[2] = j >> 1;
1154 buf[4] = j - buf[2];
1155 for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++)
1156 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY);
1157 if (mouse_level >= 1) { /* extended part */
1158 j = imax(imin(mouse->u.data.z, 127), -128);
1159 buf[5] = (j >> 1) & 0x7f;
1160 buf[6] = (j - (j >> 1)) & 0x7f;
1161 /* buttons 4-10 */
1162 buf[7] = (~mouse_status.button >> 3) & 0x7f;
1163 for (j = MOUSE_MSC_PACKETSIZE;
1164 j < MOUSE_SYS_PACKETSIZE; j++)
1165 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY);
1166 }
1167 }
1168
1169 if (cur_console->mouse_signal) {
1170 cur_console->mouse_buttons = mouse->u.data.buttons;
1171 /* has controlling process died? */
1172 if (cur_console->mouse_proc &&
1173 (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){
1174 cur_console->mouse_signal = 0;
1175 cur_console->mouse_proc = NULL;
1176 cur_console->mouse_pid = 0;
1177 }
1178 else
1179 psignal(cur_console->mouse_proc, cur_console->mouse_signal);
1180 }
1181 else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) {
1182 /* process button presses */
1183 if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) &&
1184 ISTEXTSC(cur_console)) {
1185 cur_console->mouse_buttons = mouse->u.data.buttons;
1186 if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)
1187 mouse_cut_start(cur_console);
1188 else
1189 mouse_cut_end(cur_console);
1190 if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN ||
1191 cur_console->mouse_buttons & MOUSE_BUTTON3DOWN)
1192 mouse_paste(cur_console);
1193 }
1194 }
1195
1196 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) {
1197 cur_console->mouse_xpos += mouse->u.data.x;
1198 cur_console->mouse_ypos += mouse->u.data.y;
1199 set_mouse_pos(cur_console);
1200 }
1201
1202 break;
1203
1204 case MOUSE_BUTTON_EVENT:
1205 if ((mouse->u.event.id & MOUSE_BUTTONS) == 0)
1206 return EINVAL;
1207 if (mouse->u.event.value < 0)
1208 return EINVAL;
1209
1210 if (mouse->u.event.value > 0) {
1211 cur_console->mouse_buttons |= mouse->u.event.id;
1212 mouse_status.button |= mouse->u.event.id;
1213 } else {
1214 cur_console->mouse_buttons &= ~mouse->u.event.id;
1215 mouse_status.button &= ~mouse->u.event.id;
1216 }
1217 mouse_status.flags |= mouse_status.obutton ^ mouse_status.button;
1218 if (mouse_status.flags == 0)
1219 return 0;
1220
1221 if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
1222 cur_console->status |= MOUSE_VISIBLE;
1223
1224 if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
1225 u_char buf[8];
1226 int i;
1227
1228 buf[0] = MOUSE_MSC_SYNC
1229 | butmap[mouse_status.button & MOUSE_STDBUTTONS];
1230 buf[7] = (~mouse_status.button >> 3) & 0x7f;
1231 buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
1232 for (i = 0;
1233 i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE
1234 : MOUSE_MSC_PACKETSIZE); i++)
1235 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY);
1236 }
1237
1238 if (cur_console->mouse_signal) {
1239 if (cur_console->mouse_proc &&
1240 (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){
1241 cur_console->mouse_signal = 0;
1242 cur_console->mouse_proc = NULL;
1243 cur_console->mouse_pid = 0;
1244 }
1245 else
1246 psignal(cur_console->mouse_proc, cur_console->mouse_signal);
1247 break;
1248 }
1249
1250 if (!ISTEXTSC(cur_console) || (cut_buffer == NULL))
1251 break;
1252
1253 switch (mouse->u.event.id) {
1254 case MOUSE_BUTTON1DOWN:
1255 switch (mouse->u.event.value % 4) {
1256 case 0: /* up */
1257 mouse_cut_end(cur_console);
1258 break;
1259 case 1:
1260 mouse_cut_start(cur_console);
1261 break;
1262 case 2:
1263 mouse_cut_word(cur_console);
1264 break;
1265 case 3:
1266 mouse_cut_line(cur_console);
1267 break;
1268 }
1269 break;
1270 case MOUSE_BUTTON2DOWN:
1271 switch (mouse->u.event.value) {
1272 case 0: /* up */
1273 break;
1274 default:
1275 mouse_paste(cur_console);
1276 break;
1277 }
1278 break;
1279 case MOUSE_BUTTON3DOWN:
1280 switch (mouse->u.event.value) {
1281 case 0: /* up */
1282 if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN))
1283 mouse_cut_end(cur_console);
1284 break;
1285 default:
1286 mouse_cut_extend(cur_console);
1287 break;
1288 }
1289 break;
1290 }
1291 break;
1292
1293 default:
1294 return EINVAL;
1295 }
1296 /* make screensaver happy */
1297 scsplash_stick(FALSE);
1298 run_scrn_saver = FALSE;
1299 return 0;
1300 }
1301
1302 /* MOUSE_XXX: /dev/sysmouse ioctls */
1303 case MOUSE_GETHWINFO: /* get device information */
1304 {
1305 mousehw_t *hw = (mousehw_t *)data;
1306
1307 if (tp != MOUSE_TTY)
1308 return ENOTTY;
1309 hw->buttons = 10; /* XXX unknown */
1310 hw->iftype = MOUSE_IF_SYSMOUSE;
1311 hw->type = MOUSE_MOUSE;
1312 hw->model = MOUSE_MODEL_GENERIC;
1313 hw->hwid = 0;
1314 return 0;
1315 }
1316
1317 case MOUSE_GETMODE: /* get protocol/mode */
1318 {
1319 mousemode_t *mode = (mousemode_t *)data;
1320
1321 if (tp != MOUSE_TTY)
1322 return ENOTTY;
1323 mode->level = mouse_level;
1324 switch (mode->level) {
1325 case 0:
1326 /* at this level, sysmouse emulates MouseSystems protocol */
1327 mode->protocol = MOUSE_PROTO_MSC;
1328 mode->rate = -1; /* unknown */
1329 mode->resolution = -1; /* unknown */
1330 mode->accelfactor = 0; /* disabled */
1331 mode->packetsize = MOUSE_MSC_PACKETSIZE;
1332 mode->syncmask[0] = MOUSE_MSC_SYNCMASK;
1333 mode->syncmask[1] = MOUSE_MSC_SYNC;
1334 break;
1335
1336 case 1:
1337 /* at this level, sysmouse uses its own protocol */
1338 mode->protocol = MOUSE_PROTO_SYSMOUSE;
1339 mode->rate = -1;
1340 mode->resolution = -1;
1341 mode->accelfactor = 0;
1342 mode->packetsize = MOUSE_SYS_PACKETSIZE;
1343 mode->syncmask[0] = MOUSE_SYS_SYNCMASK;
1344 mode->syncmask[1] = MOUSE_SYS_SYNC;
1345 break;
1346 }
1347 return 0;
1348 }
1349
1350 case MOUSE_SETMODE: /* set protocol/mode */
1351 {
1352 mousemode_t *mode = (mousemode_t *)data;
1353
1354 if (tp != MOUSE_TTY)
1355 return ENOTTY;
1356 if ((mode->level < 0) || (mode->level > 1))
1357 return EINVAL;
1358 mouse_level = mode->level;
1359 return 0;
1360 }
1361
1362 case MOUSE_GETLEVEL: /* get operation level */
1363 if (tp != MOUSE_TTY)
1364 return ENOTTY;
1365 *(int *)data = mouse_level;
1366 return 0;
1367
1368 case MOUSE_SETLEVEL: /* set operation level */
1369 if (tp != MOUSE_TTY)
1370 return ENOTTY;
1371 if ((*(int *)data < 0) || (*(int *)data > 1))
1372 return EINVAL;
1373 mouse_level = *(int *)data;
1374 return 0;
1375
1376 case MOUSE_GETSTATUS: /* get accumulated mouse events */
1377 if (tp != MOUSE_TTY)
1378 return ENOTTY;
1379 s = spltty();
1380 *(mousestatus_t *)data = mouse_status;
1381 mouse_status.flags = 0;
1382 mouse_status.obutton = mouse_status.button;
1383 mouse_status.dx = 0;
1384 mouse_status.dy = 0;
1385 mouse_status.dz = 0;
1386 splx(s);
1387 return 0;
1388
1389#if notyet
1390 case MOUSE_GETVARS: /* get internal mouse variables */
1391 case MOUSE_SETVARS: /* set internal mouse variables */
1392 if (tp != MOUSE_TTY)
1393 return ENOTTY;
1394 return ENODEV;
1395#endif
1396
1397 case MOUSE_READSTATE: /* read status from the device */
1398 case MOUSE_READDATA: /* read data from the device */
1399 if (tp != MOUSE_TTY)
1400 return ENOTTY;
1401 return ENODEV;
1402
1403 case CONS_GETINFO: /* get current (virtual) console info */
1404 {
1405 vid_info_t *ptr = (vid_info_t*)data;
1406 if (ptr->size == sizeof(struct vid_info)) {
1407 ptr->m_num = get_scr_num();
1408 ptr->mv_col = scp->xpos;
1409 ptr->mv_row = scp->ypos;
1410 ptr->mv_csz = scp->xsize;
1411 ptr->mv_rsz = scp->ysize;
1412 ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8;
1413 ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12;
1414 ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8;
1415 ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12;
1416 ptr->mv_grfc.fore = 0; /* not supported */
1417 ptr->mv_grfc.back = 0; /* not supported */
1418 ptr->mv_ovscan = scp->border;
1419 ptr->mk_keylock = scp->status & LOCK_KEY_MASK;
1420 return 0;
1421 }
1422 return EINVAL;
1423 }
1424
1425 case CONS_GETVERS: /* get version number */
1426 *(int*)data = 0x200; /* version 2.0 */
1427 return 0;
1428
1429 case CONS_IDLE: /* see if the screen has been idle */
1430 /*
1431 * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE,
1432 * the user process may have been writing something on the
1433 * screen and syscons is not aware of it. Declare the screen
1434 * is NOT idle if it is in one of these modes. But there is
1435 * an exception to it; if a screen saver is running in the
1436 * graphics mode in the current screen, we should say that the
1437 * screen has been idle.
1438 */
1439 *(int *)data = scrn_idle
1440 && (!ISGRAPHSC(cur_console)
1441 || (cur_console->status & SAVER_RUNNING));
1442 return 0;
1443
1444 case CONS_SAVERMODE: /* set saver mode */
1445 switch(*(int *)data) {
1446 case CONS_USR_SAVER:
1447 /* if a LKM screen saver is running, stop it first. */
1448 scsplash_stick(FALSE);
1449 saver_mode = *(int *)data;
1450 s = spltty();
1451 if ((error = wait_scrn_saver_stop())) {
1452 splx(s);
1453 return error;
1454 }
1455 scp->status |= SAVER_RUNNING;
1456 scsplash_stick(TRUE);
1457 splx(s);
1458 break;
1459 case CONS_LKM_SAVER:
1460 s = spltty();
1461 if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING))
1462 scp->status &= ~SAVER_RUNNING;
1463 saver_mode = *(int *)data;
1464 splx(s);
1465 break;
1466 default:
1467 return EINVAL;
1468 }
1469 return 0;
1470
1471 case CONS_SAVERSTART: /* immediately start/stop the screen saver */
1472 /*
1473 * Note that this ioctl does not guarantee the screen saver
1474 * actually starts or stops. It merely attempts to do so...
1475 */
1476 s = spltty();
1477 run_scrn_saver = (*(int *)data != 0);
1478 if (run_scrn_saver)
1479 scrn_time_stamp -= scrn_blank_time;
1480 splx(s);
1481 return 0;
1482
1483 case VT_SETMODE: /* set screen switcher mode */
1484 {
1485 struct vt_mode *mode;
1486
1487 mode = (struct vt_mode *)data;
1488 if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) &&
1489 ISSIGVALID(mode->frsig)) {
1490 bcopy(data, &scp->smode, sizeof(struct vt_mode));
1491 if (scp->smode.mode == VT_PROCESS) {
1492 scp->proc = p;
1493 scp->pid = scp->proc->p_pid;
1494 }
1495 return 0;
1496 } else
1497 return EINVAL;
1498 }
1499
1500 case VT_GETMODE: /* get screen switcher mode */
1501 bcopy(&scp->smode, data, sizeof(struct vt_mode));
1502 return 0;
1503
1504 case VT_RELDISP: /* screen switcher ioctl */
1505 switch(*(int *)data) {
1506 case VT_FALSE: /* user refuses to release screen, abort */
1507 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
1508 old_scp->status &= ~SWITCH_WAIT_REL;
1509 switch_in_progress = FALSE;
1510 return 0;
1511 }
1512 return EINVAL;
1513
1514 case VT_TRUE: /* user has released screen, go on */
1515 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
1516 scp->status &= ~SWITCH_WAIT_REL;
1517 exchange_scr();
1518 if (new_scp->smode.mode == VT_PROCESS) {
1519 new_scp->status |= SWITCH_WAIT_ACQ;
1520 psignal(new_scp->proc, new_scp->smode.acqsig);
1521 }
1522 else
1523 switch_in_progress = FALSE;
1524 return 0;
1525 }
1526 return EINVAL;
1527
1528 case VT_ACKACQ: /* acquire acknowledged, switch completed */
1529 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) {
1530 scp->status &= ~SWITCH_WAIT_ACQ;
1531 switch_in_progress = FALSE;
1532 return 0;
1533 }
1534 return EINVAL;
1535
1536 default:
1537 return EINVAL;
1538 }
1539 /* NOT REACHED */
1540
1541 case VT_OPENQRY: /* return free virtual console */
1542 for (i = 0; i < MAXCONS; i++) {
1543 tp = VIRTUAL_TTY(i);
1544 if (!(tp->t_state & TS_ISOPEN)) {
1545 *(int *)data = i + 1;
1546 return 0;
1547 }
1548 }
1549 return EINVAL;
1550
1551 case VT_ACTIVATE: /* switch to screen *data */
1552 return switch_scr(scp, *(int *)data - 1);
1553
1554 case VT_WAITACTIVE: /* wait for switch to occur */
1555 if (*(int *)data > MAXCONS || *(int *)data < 0)
1556 return EINVAL;
1557 if (minor(dev) == *(int *)data - 1)
1558 return 0;
1559 if (*(int *)data == 0) {
1560 if (scp == cur_console)
1561 return 0;
1562 }
1563 else
1564 scp = console[*(int *)data - 1];
1565 while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH,
1566 "waitvt", 0)) == ERESTART) ;
1567 return error;
1568
1569 case VT_GETACTIVE:
1570 *(int *)data = get_scr_num()+1;
1571 return 0;
1572
1573 case KDENABIO: /* allow io operations */
1574 error = suser(p->p_ucred, &p->p_acflag);
1575 if (error != 0)
1576 return error;
1577 if (securelevel > 0)
1578 return EPERM;
1579 p->p_md.md_regs->tf_eflags |= PSL_IOPL;
1580 return 0;
1581
1582 case KDDISABIO: /* disallow io operations (default) */
1583 p->p_md.md_regs->tf_eflags &= ~PSL_IOPL;
1584 return 0;
1585
1586 case KDSKBSTATE: /* set keyboard state (locks) */
1587 if (*(int *)data & ~LOCK_KEY_MASK)
1588 return EINVAL;
1589 scp->status &= ~LOCK_KEY_MASK;
1590 scp->status |= *(int *)data;
1591 if (scp == cur_console)
1592 update_leds(scp->status);
1593 return 0;
1594
1595 case KDGKBSTATE: /* get keyboard state (locks) */
1596 *(int *)data = scp->status & LOCK_KEY_MASK;
1597 return 0;
1598
1599 case KDSETRAD: /* set keyboard repeat & delay rates */
1600 if (*(int *)data & ~0x7f)
1601 return EINVAL;
1602 if (sc_kbdc != NULL)
1603 set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data);
1604 return 0;
1605
1606 case KDSKBMODE: /* set keyboard mode */
1607 switch (*(int *)data) {
1608 case K_RAW: /* switch to RAW scancode mode */
1609 scp->status &= ~KBD_CODE_MODE;
1610 scp->status |= KBD_RAW_MODE;
1611 return 0;
1612
1613 case K_CODE: /* switch to CODE mode */
1614 scp->status &= ~KBD_RAW_MODE;
1615 scp->status |= KBD_CODE_MODE;
1616 return 0;
1617
1618 case K_XLATE: /* switch to XLT ascii mode */
1619 if (scp == cur_console && scp->status & KBD_RAW_MODE)
1620 shfts = ctls = alts = agrs = metas = accents = 0;
1621 scp->status &= ~(KBD_RAW_MODE | KBD_CODE_MODE);
1622 return 0;
1623 default:
1624 return EINVAL;
1625 }
1626 /* NOT REACHED */
1627
1628 case KDGKBMODE: /* get keyboard mode */
1629 *(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW :
1630 ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE);
1631 return 0;
1632
1633 case KDMKTONE: /* sound the bell */
1634 if (*(int*)data)
1635 do_bell(scp, (*(int*)data)&0xffff,
1636 (((*(int*)data)>>16)&0xffff)*hz/1000);
1637 else
1638 do_bell(scp, scp->bell_pitch, scp->bell_duration);
1639 return 0;
1640
1641 case KIOCSOUND: /* make tone (*data) hz */
1642 if (scp == cur_console) {
1643 if (*(int*)data) {
1644 int pitch = timer_freq / *(int*)data;
1645
1646 /* set command for counter 2, 2 byte write */
1647 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE))
1648 return EBUSY;
1649
1650 /* set pitch */
1651 outb(TIMER_CNTR2, pitch);
1652 outb(TIMER_CNTR2, (pitch>>8));
1653
1654 /* enable counter 2 output to speaker */
1655 outb(IO_PPI, inb(IO_PPI) | 3);
1656 }
1657 else {
1658 /* disable counter 2 output to speaker */
1659 outb(IO_PPI, inb(IO_PPI) & 0xFC);
1660 release_timer2();
1661 }
1662 }
1663 return 0;
1664
1665 case KDGKBTYPE: /* get keyboard type */
1666 *(int *)data = 0; /* type not known (yet) */
1667 return 0;
1668
1669 case KDSETLED: /* set keyboard LED status */
1670 if (*(int *)data & ~LED_MASK)
1671 return EINVAL;
1672 scp->status &= ~LED_MASK;
1673 scp->status |= *(int *)data;
1674 if (scp == cur_console)
1675 update_leds(scp->status);
1676 return 0;
1677
1678 case KDGETLED: /* get keyboard LED status */
1679 *(int *)data = scp->status & LED_MASK;
1680 return 0;
1681
1682 case GETFKEY: /* get functionkey string */
1683 if (*(u_short*)data < n_fkey_tab) {
1684 fkeyarg_t *ptr = (fkeyarg_t*)data;
1685 bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef,
1686 fkey_tab[ptr->keynum].len);
1687 ptr->flen = fkey_tab[ptr->keynum].len;
1688 return 0;
1689 }
1690 else
1691 return EINVAL;
1692
1693 case SETFKEY: /* set functionkey string */
1694 if (*(u_short*)data < n_fkey_tab) {
1695 fkeyarg_t *ptr = (fkeyarg_t*)data;
1696 bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str,
1697 min(ptr->flen, MAXFK));
1698 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK);
1699 return 0;
1700 }
1701 else
1702 return EINVAL;
1703
1704 case GIO_SCRNMAP: /* get output translation table */
1705 bcopy(&scr_map, data, sizeof(scr_map));
1706 return 0;
1707
1708 case PIO_SCRNMAP: /* set output translation table */
1709 bcopy(data, &scr_map, sizeof(scr_map));
1710 for (i=0; i<sizeof(scr_map); i++)
1711 scr_rmap[scr_map[i]] = i;
1712 return 0;
1713
1714 case GIO_KEYMAP: /* get keyboard translation table */
1715 bcopy(&key_map, data, sizeof(key_map));
1716 return 0;
1717
1718 case PIO_KEYMAP: /* set keyboard translation table */
1719 accents = 0;
1720 bzero(&accent_map, sizeof(accent_map));
1721 bcopy(data, &key_map, sizeof(key_map));
1722 return 0;
1723
1724 case GIO_DEADKEYMAP: /* get accent key translation table */
1725 bcopy(&accent_map, data, sizeof(accent_map));
1726 return 0;
1727
1728 case PIO_DEADKEYMAP: /* set accent key translation table */
1729 accents = 0;
1730 bcopy(data, &accent_map, sizeof(accent_map));
1731 return 0;
1732
1733 case PIO_FONT8x8: /* set 8x8 dot font */
1734 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1735 return ENXIO;
1736 bcopy(data, font_8, 8*256);
1737 fonts_loaded |= FONT_8;
1738 /*
1739 * FONT KLUDGE
1740 * Always use the font page #0. XXX
1741 * Don't load if the current font size is not 8x8.
1742 */
1743 if (ISTEXTSC(cur_console) && (cur_console->font_size < 14))
1744 copy_font(cur_console, LOAD, 8, font_8);
1745 return 0;
1746
1747 case GIO_FONT8x8: /* get 8x8 dot font */
1748 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1749 return ENXIO;
1750 if (fonts_loaded & FONT_8) {
1751 bcopy(font_8, data, 8*256);
1752 return 0;
1753 }
1754 else
1755 return ENXIO;
1756
1757 case PIO_FONT8x14: /* set 8x14 dot font */
1758 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1759 return ENXIO;
1760 bcopy(data, font_14, 14*256);
1761 fonts_loaded |= FONT_14;
1762 /*
1763 * FONT KLUDGE
1764 * Always use the font page #0. XXX
1765 * Don't load if the current font size is not 8x14.
1766 */
1767 if (ISTEXTSC(cur_console)
1768 && (cur_console->font_size >= 14) && (cur_console->font_size < 16))
1769 copy_font(cur_console, LOAD, 14, font_14);
1770 return 0;
1771
1772 case GIO_FONT8x14: /* get 8x14 dot font */
1773 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1774 return ENXIO;
1775 if (fonts_loaded & FONT_14) {
1776 bcopy(font_14, data, 14*256);
1777 return 0;
1778 }
1779 else
1780 return ENXIO;
1781
1782 case PIO_FONT8x16: /* set 8x16 dot font */
1783 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1784 return ENXIO;
1785 bcopy(data, font_16, 16*256);
1786 fonts_loaded |= FONT_16;
1787 /*
1788 * FONT KLUDGE
1789 * Always use the font page #0. XXX
1790 * Don't load if the current font size is not 8x16.
1791 */
1792 if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16))
1793 copy_font(cur_console, LOAD, 16, font_16);
1794 return 0;
1795
1796 case GIO_FONT8x16: /* get 8x16 dot font */
1797 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1798 return ENXIO;
1799 if (fonts_loaded & FONT_16) {
1800 bcopy(font_16, data, 16*256);
1801 return 0;
1802 }
1803 else
1804 return ENXIO;
1805 default:
1806 break;
1807 }
1808
1809 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1810 if (error != ENOIOCTL)
1811 return(error);
1812 error = ttioctl(tp, cmd, data, flag);
1813 if (error != ENOIOCTL)
1814 return(error);
1815 return(ENOTTY);
1816}
1817
1818static void
1819scstart(struct tty *tp)
1820{
1821 struct clist *rbp;
1822 int s, len;
1823 u_char buf[PCBURST];
1824 scr_stat *scp = sc_get_scr_stat(tp->t_dev);
1825
1826 if (scp->status & SLKED || blink_in_progress)
1827 return; /* XXX who repeats the call when the above flags are cleared? */
1828 s = spltty();
1829 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
1830 tp->t_state |= TS_BUSY;
1831 rbp = &tp->t_outq;
1832 while (rbp->c_cc) {
1833 len = q_to_b(rbp, buf, PCBURST);
1834 splx(s);
1835 ansi_put(scp, buf, len);
1836 s = spltty();
1837 }
1838 tp->t_state &= ~TS_BUSY;
1839 ttwwakeup(tp);
1840 }
1841 splx(s);
1842}
1843
1844static void
1845scmousestart(struct tty *tp)
1846{
1847 struct clist *rbp;
1848 int s;
1849 u_char buf[PCBURST];
1850
1851 s = spltty();
1852 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
1853 tp->t_state |= TS_BUSY;
1854 rbp = &tp->t_outq;
1855 while (rbp->c_cc) {
1856 q_to_b(rbp, buf, PCBURST);
1857 }
1858 tp->t_state &= ~TS_BUSY;
1859 ttwwakeup(tp);
1860 }
1861 splx(s);
1862}
1863
1864void
1865sccnprobe(struct consdev *cp)
1866{
1867 struct isa_device *dvp;
1868
1869 /*
1870 * Take control if we are the highest priority enabled display device.
1871 */
1872 dvp = find_display();
1873 if (dvp == NULL || dvp->id_driver != &scdriver) {
1874 cp->cn_pri = CN_DEAD;
1875 return;
1876 }
1877
1878 if (!scvidprobe(dvp->id_unit, dvp->id_flags)) {
1879 cp->cn_pri = CN_DEAD;
1880 return;
1881 }
1882
1883 /* initialize required fields */
1884 cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE);
1885 cp->cn_pri = CN_INTERNAL;
1886
1887 sc_kbdc = kbdc_open(sc_port);
1888}
1889
1890void
1891sccninit(struct consdev *cp)
1892{
1893 scinit();
1894}
1895
1896void
1897sccnputc(dev_t dev, int c)
1898{
1899 u_char buf[1];
1900 int s;
1901 scr_stat *scp = console[0];
1902 term_stat save = scp->term;
1903
1904 scp->term = kernel_console;
1905 current_default = &kernel_default;
1906 if (scp == cur_console && !ISGRAPHSC(scp))
1907 remove_cursor_image(scp);
1908 buf[0] = c;
1909 ansi_put(scp, buf, 1);
1910 kernel_console = scp->term;
1911 current_default = &user_default;
1912 scp->term = save;
1913
1914 s = spltty(); /* block scintr and scrn_timer */
1915 sccnupdate(scp);
1916 splx(s);
1917}
1918
1919int
1920sccngetc(dev_t dev)
1921{
1922 int s = spltty(); /* block scintr and scrn_timer while we poll */
1923 int c;
1924
1925 /*
1926 * Stop the screen saver and update the screen if necessary.
1927 * What if we have been running in the screen saver code... XXX
1928 */
1929 scsplash_stick(FALSE);
1930 run_scrn_saver = FALSE;
1931 sccnupdate(cur_console);
1932
1933 c = scgetc(SCGETC_CN);
1934 splx(s);
1935 return(c);
1936}
1937
1938int
1939sccncheckc(dev_t dev)
1940{
1941 int s = spltty(); /* block scintr and scrn_timer while we poll */
1942 int c;
1943
1944 scsplash_stick(FALSE);
1945 run_scrn_saver = FALSE;
1946 sccnupdate(cur_console);
1947
1948 c = scgetc(SCGETC_CN | SCGETC_NONBLOCK);
1949 splx(s);
1950 return(c == NOKEY ? -1 : c); /* c == -1 can't happen */
1951}
1952
1953static void
1954sccnupdate(scr_stat *scp)
1955{
1956 /* this is a cut-down version of scrn_timer()... */
1957
1958 if (font_loading_in_progress)
1959 return;
1960
1961 if (panicstr || shutdown_in_progress) {
1962 scsplash_stick(FALSE);
1963 run_scrn_saver = FALSE;
1964 } else if (scp != cur_console) {
1965 return;
1966 }
1967
1968 if (!run_scrn_saver)
1969 scrn_idle = FALSE;
1970 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
1971 if (scp->status & SAVER_RUNNING)
1972 stop_scrn_saver(current_saver);
1973
1974 if (scp != cur_console || blink_in_progress || switch_in_progress)
1975 return;
1976
1977 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
1978 scrn_update(scp, TRUE);
1979}
1980
1981scr_stat
1982*sc_get_scr_stat(dev_t dev)
1983{
1984 int unit = minor(dev);
1985
1986 if (unit == SC_CONSOLE)
1987 return console[0];
1988 if (unit >= MAXCONS || unit < 0)
1989 return(NULL);
1990 return console[unit];
1991}
1992
1993static int
1994get_scr_num()
1995{
1996 int i = 0;
1997
1998 while ((i < MAXCONS) && (cur_console != console[i]))
1999 i++;
2000 return i < MAXCONS ? i : 0;
2001}
2002
2003static void
2004scrn_timer(void *arg)
2005{
2006 struct timeval tv;
2007 scr_stat *scp;
2008 int s;
2009
2010 /* don't do anything when we are touching font */
2011 if (font_loading_in_progress) {
2012 if (arg)
2013 timeout(scrn_timer, (void *)TRUE, hz / 10);
2014 return;
2015 }
2016 s = spltty();
2017
2018 /*
2019 * With release 2.1 of the Xaccel server, the keyboard is left
2020 * hanging pretty often. Apparently an interrupt from the
2021 * keyboard is lost, and I don't know why (yet).
2022 * This ugly hack calls scintr if input is ready for the keyboard
2023 * and conveniently hides the problem. XXX
2024 */
2025 /* Try removing anything stuck in the keyboard controller; whether
2026 * it's a keyboard scan code or mouse data. `scintr()' doesn't
2027 * read the mouse data directly, but `kbdio' routines will, as a
2028 * side effect.
2029 */
2030 if (kbdc_lock(sc_kbdc, TRUE)) {
2031 /*
2032 * We have seen the lock flag is not set. Let's reset the flag early;
2033 * otherwise `update_led()' failes which may want the lock
2034 * during `scintr()'.
2035 */
2036 kbdc_lock(sc_kbdc, FALSE);
2037 if (kbdc_data_ready(sc_kbdc))
2038 scintr(0);
2039 }
2040
2041 scp = cur_console;
2042
2043 /* should we stop the screen saver? */
2044 getmicrouptime(&tv);
2045 if (panicstr || shutdown_in_progress) {
2046 scsplash_stick(FALSE);
2047 run_scrn_saver = FALSE;
2048 }
2049 if (run_scrn_saver) {
2050 scrn_idle = (tv.tv_sec > scrn_time_stamp + scrn_blank_time);
2051 } else {
2052 scrn_time_stamp = tv.tv_sec;
2053 scrn_idle = FALSE;
2054 if (scrn_blank_time > 0)
2055 run_scrn_saver = TRUE;
2056 }
2057 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
2058 if (scp->status & SAVER_RUNNING)
2059 stop_scrn_saver(current_saver);
2060
2061 /* should we just return ? */
2062 if (blink_in_progress || switch_in_progress) {
2063 if (arg)
2064 timeout(scrn_timer, (void *)TRUE, hz / 10);
2065 splx(s);
2066 return;
2067 }
2068
2069 /* Update the screen */
2070 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
2071 scrn_update(scp, TRUE);
2072
2073 /* should we activate the screen saver? */
2074 if ((saver_mode == CONS_LKM_SAVER) && scrn_idle)
2075 if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING))
2076 scrn_saver(current_saver, TRUE);
2077
2078 if (arg)
2079 timeout(scrn_timer, (void *)TRUE, hz / 25);
2080 splx(s);
2081}
2082
2083static void
2084scrn_update(scr_stat *scp, int show_cursor)
2085{
2086 /* update screen image */
2087 if (scp->start <= scp->end)
2088 sc_bcopy(scp, scp->scr_buf, scp->start, scp->end, 0);
2089
2090 /* we are not to show the cursor and the mouse pointer... */
2091 if (!show_cursor) {
2092 scp->end = 0;
2093 scp->start = scp->xsize*scp->ysize - 1;
2094 return;
2095 }
2096
2097 /* update "pseudo" mouse pointer image */
2098 if (scp->status & MOUSE_VISIBLE) {
2099 /* did mouse move since last time ? */
2100 if (scp->status & MOUSE_MOVED) {
2101 /* do we need to remove old mouse pointer image ? */
2102 if (scp->mouse_cut_start != NULL ||
2103 (scp->mouse_pos-scp->scr_buf) <= scp->start ||
2104 (scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->end) {
2105 remove_mouse_image(scp);
2106 }
2107 scp->status &= ~MOUSE_MOVED;
2108 draw_mouse_image(scp);
2109 }
2110 else {
2111 /* mouse didn't move, has it been overwritten ? */
2112 if ((scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->start &&
2113 (scp->mouse_pos - scp->scr_buf) <= scp->end) {
2114 draw_mouse_image(scp);
2115 }
2116 }
2117 }
2118
2119 /* update cursor image */
2120 if (scp->status & CURSOR_ENABLED) {
2121 /* did cursor move since last time ? */
2122 if (scp->cursor_pos != scp->cursor_oldpos) {
2123 /* do we need to remove old cursor image ? */
2124 if ((scp->cursor_oldpos - scp->scr_buf) < scp->start ||
2125 ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) {
2126 remove_cursor_image(scp);
2127 }
2128 scp->cursor_oldpos = scp->cursor_pos;
2129 draw_cursor_image(scp);
2130 }
2131 else {
2132 /* cursor didn't move, has it been overwritten ? */
2133 if (scp->cursor_pos - scp->scr_buf >= scp->start &&
2134 scp->cursor_pos - scp->scr_buf <= scp->end) {
2135 draw_cursor_image(scp);
2136 } else {
2137 /* if its a blinking cursor, we may have to update it */
2138 if (flags & BLINK_CURSOR)
2139 draw_cursor_image(scp);
2140 }
2141 }
2142 blinkrate++;
2143 }
2144
2145 if (scp->mouse_cut_start != NULL)
2146 draw_cutmarking(scp);
2147
2148 scp->end = 0;
2149 scp->start = scp->xsize*scp->ysize - 1;
2150}
2151
2152int
2153add_scrn_saver(void (*this_saver)(int))
2154{
2155#ifdef SC_SPLASH_SCREEN
2156 if (current_saver == scsplash) {
2157 scsplash_stick(FALSE);
2158 stop_scrn_saver(scsplash);
2159 }
2160#endif
2161
2162 if (current_saver != default_saver)
2163 return EBUSY;
2164 run_scrn_saver = FALSE;
2165 saver_mode = CONS_LKM_SAVER;
2166 current_saver = this_saver;
2167 return 0;
2168}
2169
2170int
2171remove_scrn_saver(void (*this_saver)(int))
2172{
2173 if (current_saver != this_saver)
2174 return EINVAL;
2175
2176 /*
2177 * In order to prevent `current_saver' from being called by
2178 * the timeout routine `scrn_timer()' while we manipulate
2179 * the saver list, we shall set `current_saver' to `none_saver'
2180 * before stopping the current saver, rather than blocking by `splXX()'.
2181 */
2182 current_saver = none_saver;
2183 if (scrn_blanked > 0)
2184 stop_scrn_saver(this_saver);
2185
2186 if (scrn_blanked > 0)
2187 return EBUSY; /* XXX */
2188
2189 current_saver = default_saver;
2190 return 0;
2191}
2192
2193static void
2194scrn_saver(void (*saver)(int), int blank)
2195{
2196 static int busy = FALSE;
2197
2198 if (busy)
2199 return;
2200 busy = TRUE;
2201 (*saver)(blank);
2202 busy = FALSE;
2203}
2204
2205static void
2206stop_scrn_saver(void (*saver)(int))
2207{
2208 scrn_saver(saver, FALSE);
2209 run_scrn_saver = FALSE;
2210 /* the screen saver may have chosen not to stop after all... */
2211 if (scrn_blanked > 0)
2212 return;
2213
2214 mark_all(cur_console);
2215 if (delayed_next_scr)
2216 switch_scr(cur_console, delayed_next_scr - 1);
2217 wakeup((caddr_t)&scrn_blanked);
2218}
2219
2220static int
2221wait_scrn_saver_stop(void)
2222{
2223 int error = 0;
2224
2225 while (scrn_blanked > 0) {
2226 run_scrn_saver = FALSE;
2227 error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0);
2228 run_scrn_saver = FALSE;
2229 if (error != ERESTART)
2230 break;
2231 }
2232 return error;
2233}
2234
2235void
2236sc_clear_screen(scr_stat *scp)
2237{
2238 move_crsr(scp, 0, 0);
2239 scp->cursor_oldpos = scp->cursor_pos;
2240 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf,
2241 scp->xsize * scp->ysize);
2242 mark_all(scp);
2243 remove_cutmarking(scp);
2244}
2245
2246static int
2247switch_scr(scr_stat *scp, u_int next_scr)
2248{
2249 /* delay switch if actively updating screen */
2250 if (scrn_blanked > 0 || write_in_progress || blink_in_progress) {
2251 scsplash_stick(FALSE);
2252 run_scrn_saver = FALSE;
2253 delayed_next_scr = next_scr+1;
2254 return 0;
2255 }
2256
2257 if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid)))
2258 switch_in_progress = FALSE;
2259
2260 if (next_scr >= MAXCONS || switch_in_progress ||
2261 (cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) {
2262 do_bell(scp, BELL_PITCH, BELL_DURATION);
2263 return EINVAL;
2264 }
2265
2266 /* is the wanted virtual console open ? */
2267 if (next_scr) {
2268 struct tty *tp = VIRTUAL_TTY(next_scr);
2269 if (!(tp->t_state & TS_ISOPEN)) {
2270 do_bell(scp, BELL_PITCH, BELL_DURATION);
2271 return EINVAL;
2272 }
2273 }
2274
2275 switch_in_progress = TRUE;
2276 old_scp = cur_console;
2277 new_scp = console[next_scr];
2278 wakeup((caddr_t)&new_scp->smode);
2279 if (new_scp == old_scp) {
2280 switch_in_progress = FALSE;
2281 delayed_next_scr = FALSE;
2282 return 0;
2283 }
2284
2285 /* has controlling process died? */
2286 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid)))
2287 old_scp->smode.mode = VT_AUTO;
2288 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid)))
2289 new_scp->smode.mode = VT_AUTO;
2290
2291 /* check the modes and switch appropriately */
2292 if (old_scp->smode.mode == VT_PROCESS) {
2293 old_scp->status |= SWITCH_WAIT_REL;
2294 psignal(old_scp->proc, old_scp->smode.relsig);
2295 }
2296 else {
2297 exchange_scr();
2298 if (new_scp->smode.mode == VT_PROCESS) {
2299 new_scp->status |= SWITCH_WAIT_ACQ;
2300 psignal(new_scp->proc, new_scp->smode.acqsig);
2301 }
2302 else
2303 switch_in_progress = FALSE;
2304 }
2305 return 0;
2306}
2307
2308static void
2309exchange_scr(void)
2310{
2311 move_crsr(old_scp, old_scp->xpos, old_scp->ypos);
2312 cur_console = new_scp;
684 }
685#endif /* VESA && VM86 */
686
687 /* initialize cursor stuff */
688 if (!ISGRAPHSC(scp))
689 draw_cursor_image(scp);
690
691 /* get screen update going */
692 scrn_timer((void *)TRUE);
693
694 update_leds(scp->status);
695
696 printf("sc%d: ", dev->id_unit);
697 switch(crtc_type) {
698 case KD_VGA:
699 printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono");
700 break;
701 case KD_EGA:
702 printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono");
703 break;
704 case KD_CGA:
705 printf("CGA");
706 break;
707 case KD_MONO:
708 case KD_HERCULES:
709 default:
710 printf("MDA/Hercules");
711 break;
712 }
713 printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags);
714
715#if NAPM > 0
716 scp->r_hook.ah_fun = scresume;
717 scp->r_hook.ah_arg = NULL;
718 scp->r_hook.ah_name = "system keyboard";
719 scp->r_hook.ah_order = APM_MID_ORDER;
720 apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook);
721#endif
722
723 at_shutdown(scshutdown, NULL, SHUTDOWN_PRE_SYNC);
724
725 cdevsw_add(&cdev, &sc_cdevsw, NULL);
726
727#ifdef DEVFS
728 for (vc = 0; vc < MAXCONS; vc++)
729 sc_devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc, DV_CHR,
730 UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc);
731 sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE, DV_CHR,
732 UID_ROOT, GID_WHEEL, 0600, "sysmouse");
733 sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLE, DV_CHR,
734 UID_ROOT, GID_WHEEL, 0600, "consolectl");
735#endif
736 return 0;
737}
738
739struct tty
740*scdevtotty(dev_t dev)
741{
742 int unit = minor(dev);
743
744 if (init_done == COLD)
745 return(NULL);
746 if (unit == SC_CONSOLE)
747 return CONSOLE_TTY;
748 if (unit == SC_MOUSE)
749 return MOUSE_TTY;
750 if (unit >= MAXCONS || unit < 0)
751 return(NULL);
752 return VIRTUAL_TTY(unit);
753}
754
755int
756scopen(dev_t dev, int flag, int mode, struct proc *p)
757{
758 struct tty *tp = scdevtotty(dev);
759
760 if (!tp)
761 return(ENXIO);
762
763 tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart;
764 tp->t_param = scparam;
765 tp->t_dev = dev;
766 if (!(tp->t_state & TS_ISOPEN)) {
767 ttychars(tp);
768 /* Use the current setting of the <-- key as default VERASE. */
769 /* If the Delete key is preferable, an stty is necessary */
770 tp->t_cc[VERASE] = key_map.key[0x0e].map[0];
771 tp->t_iflag = TTYDEF_IFLAG;
772 tp->t_oflag = TTYDEF_OFLAG;
773 tp->t_cflag = TTYDEF_CFLAG;
774 tp->t_lflag = TTYDEF_LFLAG;
775 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
776 scparam(tp, &tp->t_termios);
777 (*linesw[tp->t_line].l_modem)(tp, 1);
778 if (minor(dev) == SC_MOUSE)
779 mouse_level = 0; /* XXX */
780 }
781 else
782 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
783 return(EBUSY);
784 if (minor(dev) < MAXCONS && !console[minor(dev)]) {
785 console[minor(dev)] = alloc_scp();
786 if (ISGRAPHSC(console[minor(dev)]))
787 sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16);
788 }
789 if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) {
790 tp->t_winsize.ws_col = console[minor(dev)]->xsize;
791 tp->t_winsize.ws_row = console[minor(dev)]->ysize;
792 }
793 return ((*linesw[tp->t_line].l_open)(dev, tp));
794}
795
796int
797scclose(dev_t dev, int flag, int mode, struct proc *p)
798{
799 struct tty *tp = scdevtotty(dev);
800 struct scr_stat *scp;
801
802 if (!tp)
803 return(ENXIO);
804 if (minor(dev) < MAXCONS) {
805 scp = sc_get_scr_stat(tp->t_dev);
806 if (scp->status & SWITCH_WAIT_ACQ)
807 wakeup((caddr_t)&scp->smode);
808#if not_yet_done
809 if (scp == &main_console) {
810 scp->pid = 0;
811 scp->proc = NULL;
812 scp->smode.mode = VT_AUTO;
813 }
814 else {
815 free(scp->scr_buf, M_DEVBUF);
816 if (scp->history != NULL) {
817 free(scp->history, M_DEVBUF);
818 if (scp->history_size / scp->xsize
819 > imax(sc_history_size, scp->ysize))
820 extra_history_size += scp->history_size / scp->xsize
821 - imax(sc_history_size, scp->ysize);
822 }
823 free(scp, M_DEVBUF);
824 console[minor(dev)] = NULL;
825 }
826#else
827 scp->pid = 0;
828 scp->proc = NULL;
829 scp->smode.mode = VT_AUTO;
830#endif
831 }
832 spltty();
833 (*linesw[tp->t_line].l_close)(tp, flag);
834 ttyclose(tp);
835 spl0();
836 return(0);
837}
838
839int
840scread(dev_t dev, struct uio *uio, int flag)
841{
842 struct tty *tp = scdevtotty(dev);
843
844 if (!tp)
845 return(ENXIO);
846 return((*linesw[tp->t_line].l_read)(tp, uio, flag));
847}
848
849int
850scwrite(dev_t dev, struct uio *uio, int flag)
851{
852 struct tty *tp = scdevtotty(dev);
853
854 if (!tp)
855 return(ENXIO);
856 return((*linesw[tp->t_line].l_write)(tp, uio, flag));
857}
858
859void
860scintr(int unit)
861{
862 static struct tty *cur_tty;
863 int c, len;
864 u_char *cp;
865
866 /*
867 * Loop while there is still input to get from the keyboard.
868 * I don't think this is nessesary, and it doesn't fix
869 * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX
870 */
871 while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) {
872
873 cur_tty = VIRTUAL_TTY(get_scr_num());
874 if (!(cur_tty->t_state & TS_ISOPEN))
875 if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN))
876 continue;
877
878 switch (c & 0xff00) {
879 case 0x0000: /* normal key */
880 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
881 break;
882 case FKEY: /* function key, return string */
883 if (cp = get_fstr((u_int)c, (u_int *)&len)) {
884 while (len-- > 0)
885 (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty);
886 }
887 break;
888 case MKEY: /* meta is active, prepend ESC */
889 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
890 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
891 break;
892 case BKEY: /* backtab fixed sequence (esc [ Z) */
893 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
894 (*linesw[cur_tty->t_line].l_rint)('[', cur_tty);
895 (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty);
896 break;
897 }
898 }
899
900#if 0
901 if (cur_console->status & MOUSE_ENABLED) {
902 cur_console->status &= ~MOUSE_VISIBLE;
903 remove_mouse_image(cur_console);
904 }
905#else
906 if (cur_console->status & MOUSE_VISIBLE) {
907 remove_mouse_image(cur_console);
908 cur_console->status &= ~MOUSE_VISIBLE;
909 }
910#endif
911}
912
913static int
914scparam(struct tty *tp, struct termios *t)
915{
916 tp->t_ispeed = t->c_ispeed;
917 tp->t_ospeed = t->c_ospeed;
918 tp->t_cflag = t->c_cflag;
919 return 0;
920}
921
922int
923scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
924{
925 int error;
926 u_int i;
927 struct tty *tp;
928 scr_stat *scp;
929 video_adapter_t *adp;
930 int s;
931
932 tp = scdevtotty(dev);
933 if (!tp)
934 return ENXIO;
935 scp = sc_get_scr_stat(tp->t_dev);
936
937 /* If there is a user_ioctl function call that first */
938 if (sc_user_ioctl) {
939 error = (*sc_user_ioctl)(dev, cmd, data, flag, p);
940 if (error != ENOIOCTL)
941 return error;
942 }
943
944 error = sc_vid_ioctl(tp, cmd, data, flag, p);
945 if (error != ENOIOCTL)
946 return error;
947
948 switch (cmd) { /* process console hardware related ioctl's */
949
950 case GIO_ATTR: /* get current attributes */
951 *(int*)data = (scp->term.cur_attr >> 8) & 0xFF;
952 return 0;
953
954 case GIO_COLOR: /* is this a color console ? */
955 *(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0;
956 return 0;
957
958 case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */
959 if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME)
960 return EINVAL;
961 s = spltty();
962 scrn_blank_time = *(int *)data;
963 run_scrn_saver = (scrn_blank_time != 0);
964 splx(s);
965 return 0;
966
967 case CONS_CURSORTYPE: /* set cursor type blink/noblink */
968 if ((*(int*)data) & 0x01)
969 flags |= BLINK_CURSOR;
970 else
971 flags &= ~BLINK_CURSOR;
972 if ((*(int*)data) & 0x02) {
973 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
974 return ENXIO;
975 flags |= CHAR_CURSOR;
976 } else
977 flags &= ~CHAR_CURSOR;
978 /*
979 * The cursor shape is global property; all virtual consoles
980 * are affected. Update the cursor in the current console...
981 */
982 if (!ISGRAPHSC(cur_console)) {
983 remove_cursor_image(cur_console);
984 if (flags & CHAR_CURSOR)
985 set_destructive_cursor(cur_console);
986 draw_cursor_image(cur_console);
987 }
988 return 0;
989
990 case CONS_BELLTYPE: /* set bell type sound/visual */
991 if ((*(int *)data) & 0x01)
992 flags |= VISUAL_BELL;
993 else
994 flags &= ~VISUAL_BELL;
995 if ((*(int *)data) & 0x02)
996 flags |= QUIET_BELL;
997 else
998 flags &= ~QUIET_BELL;
999 return 0;
1000
1001 case CONS_HISTORY: /* set history size */
1002 if (*(int *)data > 0) {
1003 int lines; /* buffer size to allocate */
1004 int lines0; /* current buffer size */
1005
1006 lines = imax(*(int *)data, scp->ysize);
1007 lines0 = (scp->history != NULL) ?
1008 scp->history_size / scp->xsize : scp->ysize;
1009 if (lines0 > imax(sc_history_size, scp->ysize))
1010 i = lines0 - imax(sc_history_size, scp->ysize);
1011 else
1012 i = 0;
1013 /*
1014 * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE
1015 * lines or scp->ysize lines, whichever is larger. A value
1016 * greater than that is allowed, subject to extra_history_size.
1017 */
1018 if (lines > imax(sc_history_size, scp->ysize))
1019 if (lines - imax(sc_history_size, scp->ysize) >
1020 extra_history_size + i)
1021 return EINVAL;
1022 if (cur_console->status & BUFFER_SAVED)
1023 return EBUSY;
1024 sc_alloc_history_buffer(scp, lines, i, TRUE);
1025 return 0;
1026 }
1027 else
1028 return EINVAL;
1029
1030 case CONS_MOUSECTL: /* control mouse arrow */
1031 case OLD_CONS_MOUSECTL:
1032 {
1033 /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */
1034 static butmap[8] = {
1035 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP
1036 | MOUSE_MSC_BUTTON3UP,
1037 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
1038 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
1039 MOUSE_MSC_BUTTON3UP,
1040 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
1041 MOUSE_MSC_BUTTON2UP,
1042 MOUSE_MSC_BUTTON1UP,
1043 0,
1044 };
1045 mouse_info_t *mouse = (mouse_info_t*)data;
1046 mouse_info_t buf;
1047
1048 /* FIXME: */
1049 if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags))
1050 return ENODEV;
1051
1052 if (cmd == OLD_CONS_MOUSECTL) {
1053 static unsigned char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
1054 old_mouse_info_t *old_mouse = (old_mouse_info_t *)data;
1055
1056 mouse = &buf;
1057 mouse->operation = old_mouse->operation;
1058 switch (mouse->operation) {
1059 case MOUSE_MODE:
1060 mouse->u.mode = old_mouse->u.mode;
1061 break;
1062 case MOUSE_SHOW:
1063 case MOUSE_HIDE:
1064 break;
1065 case MOUSE_MOVEABS:
1066 case MOUSE_MOVEREL:
1067 case MOUSE_ACTION:
1068 mouse->u.data.x = old_mouse->u.data.x;
1069 mouse->u.data.y = old_mouse->u.data.y;
1070 mouse->u.data.z = 0;
1071 mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7];
1072 break;
1073 case MOUSE_GETINFO:
1074 old_mouse->u.data.x = scp->mouse_xpos;
1075 old_mouse->u.data.y = scp->mouse_ypos;
1076 old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7];
1077 break;
1078 default:
1079 return EINVAL;
1080 }
1081 }
1082
1083 switch (mouse->operation) {
1084 case MOUSE_MODE:
1085 if (ISSIGVALID(mouse->u.mode.signal)) {
1086 scp->mouse_signal = mouse->u.mode.signal;
1087 scp->mouse_proc = p;
1088 scp->mouse_pid = p->p_pid;
1089 }
1090 else {
1091 scp->mouse_signal = 0;
1092 scp->mouse_proc = NULL;
1093 scp->mouse_pid = 0;
1094 }
1095 return 0;
1096
1097 case MOUSE_SHOW:
1098 if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) {
1099 scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE);
1100 scp->mouse_oldpos = scp->mouse_pos;
1101 mark_all(scp);
1102 return 0;
1103 }
1104 else
1105 return EINVAL;
1106 break;
1107
1108 case MOUSE_HIDE:
1109 if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) {
1110 scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE);
1111 mark_all(scp);
1112 return 0;
1113 }
1114 else
1115 return EINVAL;
1116 break;
1117
1118 case MOUSE_MOVEABS:
1119 scp->mouse_xpos = mouse->u.data.x;
1120 scp->mouse_ypos = mouse->u.data.y;
1121 set_mouse_pos(scp);
1122 break;
1123
1124 case MOUSE_MOVEREL:
1125 scp->mouse_xpos += mouse->u.data.x;
1126 scp->mouse_ypos += mouse->u.data.y;
1127 set_mouse_pos(scp);
1128 break;
1129
1130 case MOUSE_GETINFO:
1131 mouse->u.data.x = scp->mouse_xpos;
1132 mouse->u.data.y = scp->mouse_ypos;
1133 mouse->u.data.z = 0;
1134 mouse->u.data.buttons = scp->mouse_buttons;
1135 return 0;
1136
1137 case MOUSE_ACTION:
1138 case MOUSE_MOTION_EVENT:
1139 /* this should maybe only be settable from /dev/consolectl SOS */
1140 /* send out mouse event on /dev/sysmouse */
1141
1142 mouse_status.dx += mouse->u.data.x;
1143 mouse_status.dy += mouse->u.data.y;
1144 mouse_status.dz += mouse->u.data.z;
1145 if (mouse->operation == MOUSE_ACTION)
1146 mouse_status.button = mouse->u.data.buttons;
1147 mouse_status.flags |=
1148 ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ?
1149 MOUSE_POSCHANGED : 0)
1150 | (mouse_status.obutton ^ mouse_status.button);
1151 if (mouse_status.flags == 0)
1152 return 0;
1153
1154 if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
1155 cur_console->status |= MOUSE_VISIBLE;
1156
1157 if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
1158 u_char buf[MOUSE_SYS_PACKETSIZE];
1159 int j;
1160
1161 /* the first five bytes are compatible with MouseSystems' */
1162 buf[0] = MOUSE_MSC_SYNC
1163 | butmap[mouse_status.button & MOUSE_STDBUTTONS];
1164 j = imax(imin(mouse->u.data.x, 255), -256);
1165 buf[1] = j >> 1;
1166 buf[3] = j - buf[1];
1167 j = -imax(imin(mouse->u.data.y, 255), -256);
1168 buf[2] = j >> 1;
1169 buf[4] = j - buf[2];
1170 for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++)
1171 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY);
1172 if (mouse_level >= 1) { /* extended part */
1173 j = imax(imin(mouse->u.data.z, 127), -128);
1174 buf[5] = (j >> 1) & 0x7f;
1175 buf[6] = (j - (j >> 1)) & 0x7f;
1176 /* buttons 4-10 */
1177 buf[7] = (~mouse_status.button >> 3) & 0x7f;
1178 for (j = MOUSE_MSC_PACKETSIZE;
1179 j < MOUSE_SYS_PACKETSIZE; j++)
1180 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY);
1181 }
1182 }
1183
1184 if (cur_console->mouse_signal) {
1185 cur_console->mouse_buttons = mouse->u.data.buttons;
1186 /* has controlling process died? */
1187 if (cur_console->mouse_proc &&
1188 (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){
1189 cur_console->mouse_signal = 0;
1190 cur_console->mouse_proc = NULL;
1191 cur_console->mouse_pid = 0;
1192 }
1193 else
1194 psignal(cur_console->mouse_proc, cur_console->mouse_signal);
1195 }
1196 else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) {
1197 /* process button presses */
1198 if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) &&
1199 ISTEXTSC(cur_console)) {
1200 cur_console->mouse_buttons = mouse->u.data.buttons;
1201 if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)
1202 mouse_cut_start(cur_console);
1203 else
1204 mouse_cut_end(cur_console);
1205 if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN ||
1206 cur_console->mouse_buttons & MOUSE_BUTTON3DOWN)
1207 mouse_paste(cur_console);
1208 }
1209 }
1210
1211 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) {
1212 cur_console->mouse_xpos += mouse->u.data.x;
1213 cur_console->mouse_ypos += mouse->u.data.y;
1214 set_mouse_pos(cur_console);
1215 }
1216
1217 break;
1218
1219 case MOUSE_BUTTON_EVENT:
1220 if ((mouse->u.event.id & MOUSE_BUTTONS) == 0)
1221 return EINVAL;
1222 if (mouse->u.event.value < 0)
1223 return EINVAL;
1224
1225 if (mouse->u.event.value > 0) {
1226 cur_console->mouse_buttons |= mouse->u.event.id;
1227 mouse_status.button |= mouse->u.event.id;
1228 } else {
1229 cur_console->mouse_buttons &= ~mouse->u.event.id;
1230 mouse_status.button &= ~mouse->u.event.id;
1231 }
1232 mouse_status.flags |= mouse_status.obutton ^ mouse_status.button;
1233 if (mouse_status.flags == 0)
1234 return 0;
1235
1236 if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
1237 cur_console->status |= MOUSE_VISIBLE;
1238
1239 if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
1240 u_char buf[8];
1241 int i;
1242
1243 buf[0] = MOUSE_MSC_SYNC
1244 | butmap[mouse_status.button & MOUSE_STDBUTTONS];
1245 buf[7] = (~mouse_status.button >> 3) & 0x7f;
1246 buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
1247 for (i = 0;
1248 i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE
1249 : MOUSE_MSC_PACKETSIZE); i++)
1250 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY);
1251 }
1252
1253 if (cur_console->mouse_signal) {
1254 if (cur_console->mouse_proc &&
1255 (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){
1256 cur_console->mouse_signal = 0;
1257 cur_console->mouse_proc = NULL;
1258 cur_console->mouse_pid = 0;
1259 }
1260 else
1261 psignal(cur_console->mouse_proc, cur_console->mouse_signal);
1262 break;
1263 }
1264
1265 if (!ISTEXTSC(cur_console) || (cut_buffer == NULL))
1266 break;
1267
1268 switch (mouse->u.event.id) {
1269 case MOUSE_BUTTON1DOWN:
1270 switch (mouse->u.event.value % 4) {
1271 case 0: /* up */
1272 mouse_cut_end(cur_console);
1273 break;
1274 case 1:
1275 mouse_cut_start(cur_console);
1276 break;
1277 case 2:
1278 mouse_cut_word(cur_console);
1279 break;
1280 case 3:
1281 mouse_cut_line(cur_console);
1282 break;
1283 }
1284 break;
1285 case MOUSE_BUTTON2DOWN:
1286 switch (mouse->u.event.value) {
1287 case 0: /* up */
1288 break;
1289 default:
1290 mouse_paste(cur_console);
1291 break;
1292 }
1293 break;
1294 case MOUSE_BUTTON3DOWN:
1295 switch (mouse->u.event.value) {
1296 case 0: /* up */
1297 if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN))
1298 mouse_cut_end(cur_console);
1299 break;
1300 default:
1301 mouse_cut_extend(cur_console);
1302 break;
1303 }
1304 break;
1305 }
1306 break;
1307
1308 default:
1309 return EINVAL;
1310 }
1311 /* make screensaver happy */
1312 scsplash_stick(FALSE);
1313 run_scrn_saver = FALSE;
1314 return 0;
1315 }
1316
1317 /* MOUSE_XXX: /dev/sysmouse ioctls */
1318 case MOUSE_GETHWINFO: /* get device information */
1319 {
1320 mousehw_t *hw = (mousehw_t *)data;
1321
1322 if (tp != MOUSE_TTY)
1323 return ENOTTY;
1324 hw->buttons = 10; /* XXX unknown */
1325 hw->iftype = MOUSE_IF_SYSMOUSE;
1326 hw->type = MOUSE_MOUSE;
1327 hw->model = MOUSE_MODEL_GENERIC;
1328 hw->hwid = 0;
1329 return 0;
1330 }
1331
1332 case MOUSE_GETMODE: /* get protocol/mode */
1333 {
1334 mousemode_t *mode = (mousemode_t *)data;
1335
1336 if (tp != MOUSE_TTY)
1337 return ENOTTY;
1338 mode->level = mouse_level;
1339 switch (mode->level) {
1340 case 0:
1341 /* at this level, sysmouse emulates MouseSystems protocol */
1342 mode->protocol = MOUSE_PROTO_MSC;
1343 mode->rate = -1; /* unknown */
1344 mode->resolution = -1; /* unknown */
1345 mode->accelfactor = 0; /* disabled */
1346 mode->packetsize = MOUSE_MSC_PACKETSIZE;
1347 mode->syncmask[0] = MOUSE_MSC_SYNCMASK;
1348 mode->syncmask[1] = MOUSE_MSC_SYNC;
1349 break;
1350
1351 case 1:
1352 /* at this level, sysmouse uses its own protocol */
1353 mode->protocol = MOUSE_PROTO_SYSMOUSE;
1354 mode->rate = -1;
1355 mode->resolution = -1;
1356 mode->accelfactor = 0;
1357 mode->packetsize = MOUSE_SYS_PACKETSIZE;
1358 mode->syncmask[0] = MOUSE_SYS_SYNCMASK;
1359 mode->syncmask[1] = MOUSE_SYS_SYNC;
1360 break;
1361 }
1362 return 0;
1363 }
1364
1365 case MOUSE_SETMODE: /* set protocol/mode */
1366 {
1367 mousemode_t *mode = (mousemode_t *)data;
1368
1369 if (tp != MOUSE_TTY)
1370 return ENOTTY;
1371 if ((mode->level < 0) || (mode->level > 1))
1372 return EINVAL;
1373 mouse_level = mode->level;
1374 return 0;
1375 }
1376
1377 case MOUSE_GETLEVEL: /* get operation level */
1378 if (tp != MOUSE_TTY)
1379 return ENOTTY;
1380 *(int *)data = mouse_level;
1381 return 0;
1382
1383 case MOUSE_SETLEVEL: /* set operation level */
1384 if (tp != MOUSE_TTY)
1385 return ENOTTY;
1386 if ((*(int *)data < 0) || (*(int *)data > 1))
1387 return EINVAL;
1388 mouse_level = *(int *)data;
1389 return 0;
1390
1391 case MOUSE_GETSTATUS: /* get accumulated mouse events */
1392 if (tp != MOUSE_TTY)
1393 return ENOTTY;
1394 s = spltty();
1395 *(mousestatus_t *)data = mouse_status;
1396 mouse_status.flags = 0;
1397 mouse_status.obutton = mouse_status.button;
1398 mouse_status.dx = 0;
1399 mouse_status.dy = 0;
1400 mouse_status.dz = 0;
1401 splx(s);
1402 return 0;
1403
1404#if notyet
1405 case MOUSE_GETVARS: /* get internal mouse variables */
1406 case MOUSE_SETVARS: /* set internal mouse variables */
1407 if (tp != MOUSE_TTY)
1408 return ENOTTY;
1409 return ENODEV;
1410#endif
1411
1412 case MOUSE_READSTATE: /* read status from the device */
1413 case MOUSE_READDATA: /* read data from the device */
1414 if (tp != MOUSE_TTY)
1415 return ENOTTY;
1416 return ENODEV;
1417
1418 case CONS_GETINFO: /* get current (virtual) console info */
1419 {
1420 vid_info_t *ptr = (vid_info_t*)data;
1421 if (ptr->size == sizeof(struct vid_info)) {
1422 ptr->m_num = get_scr_num();
1423 ptr->mv_col = scp->xpos;
1424 ptr->mv_row = scp->ypos;
1425 ptr->mv_csz = scp->xsize;
1426 ptr->mv_rsz = scp->ysize;
1427 ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8;
1428 ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12;
1429 ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8;
1430 ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12;
1431 ptr->mv_grfc.fore = 0; /* not supported */
1432 ptr->mv_grfc.back = 0; /* not supported */
1433 ptr->mv_ovscan = scp->border;
1434 ptr->mk_keylock = scp->status & LOCK_KEY_MASK;
1435 return 0;
1436 }
1437 return EINVAL;
1438 }
1439
1440 case CONS_GETVERS: /* get version number */
1441 *(int*)data = 0x200; /* version 2.0 */
1442 return 0;
1443
1444 case CONS_IDLE: /* see if the screen has been idle */
1445 /*
1446 * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE,
1447 * the user process may have been writing something on the
1448 * screen and syscons is not aware of it. Declare the screen
1449 * is NOT idle if it is in one of these modes. But there is
1450 * an exception to it; if a screen saver is running in the
1451 * graphics mode in the current screen, we should say that the
1452 * screen has been idle.
1453 */
1454 *(int *)data = scrn_idle
1455 && (!ISGRAPHSC(cur_console)
1456 || (cur_console->status & SAVER_RUNNING));
1457 return 0;
1458
1459 case CONS_SAVERMODE: /* set saver mode */
1460 switch(*(int *)data) {
1461 case CONS_USR_SAVER:
1462 /* if a LKM screen saver is running, stop it first. */
1463 scsplash_stick(FALSE);
1464 saver_mode = *(int *)data;
1465 s = spltty();
1466 if ((error = wait_scrn_saver_stop())) {
1467 splx(s);
1468 return error;
1469 }
1470 scp->status |= SAVER_RUNNING;
1471 scsplash_stick(TRUE);
1472 splx(s);
1473 break;
1474 case CONS_LKM_SAVER:
1475 s = spltty();
1476 if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING))
1477 scp->status &= ~SAVER_RUNNING;
1478 saver_mode = *(int *)data;
1479 splx(s);
1480 break;
1481 default:
1482 return EINVAL;
1483 }
1484 return 0;
1485
1486 case CONS_SAVERSTART: /* immediately start/stop the screen saver */
1487 /*
1488 * Note that this ioctl does not guarantee the screen saver
1489 * actually starts or stops. It merely attempts to do so...
1490 */
1491 s = spltty();
1492 run_scrn_saver = (*(int *)data != 0);
1493 if (run_scrn_saver)
1494 scrn_time_stamp -= scrn_blank_time;
1495 splx(s);
1496 return 0;
1497
1498 case VT_SETMODE: /* set screen switcher mode */
1499 {
1500 struct vt_mode *mode;
1501
1502 mode = (struct vt_mode *)data;
1503 if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) &&
1504 ISSIGVALID(mode->frsig)) {
1505 bcopy(data, &scp->smode, sizeof(struct vt_mode));
1506 if (scp->smode.mode == VT_PROCESS) {
1507 scp->proc = p;
1508 scp->pid = scp->proc->p_pid;
1509 }
1510 return 0;
1511 } else
1512 return EINVAL;
1513 }
1514
1515 case VT_GETMODE: /* get screen switcher mode */
1516 bcopy(&scp->smode, data, sizeof(struct vt_mode));
1517 return 0;
1518
1519 case VT_RELDISP: /* screen switcher ioctl */
1520 switch(*(int *)data) {
1521 case VT_FALSE: /* user refuses to release screen, abort */
1522 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
1523 old_scp->status &= ~SWITCH_WAIT_REL;
1524 switch_in_progress = FALSE;
1525 return 0;
1526 }
1527 return EINVAL;
1528
1529 case VT_TRUE: /* user has released screen, go on */
1530 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
1531 scp->status &= ~SWITCH_WAIT_REL;
1532 exchange_scr();
1533 if (new_scp->smode.mode == VT_PROCESS) {
1534 new_scp->status |= SWITCH_WAIT_ACQ;
1535 psignal(new_scp->proc, new_scp->smode.acqsig);
1536 }
1537 else
1538 switch_in_progress = FALSE;
1539 return 0;
1540 }
1541 return EINVAL;
1542
1543 case VT_ACKACQ: /* acquire acknowledged, switch completed */
1544 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) {
1545 scp->status &= ~SWITCH_WAIT_ACQ;
1546 switch_in_progress = FALSE;
1547 return 0;
1548 }
1549 return EINVAL;
1550
1551 default:
1552 return EINVAL;
1553 }
1554 /* NOT REACHED */
1555
1556 case VT_OPENQRY: /* return free virtual console */
1557 for (i = 0; i < MAXCONS; i++) {
1558 tp = VIRTUAL_TTY(i);
1559 if (!(tp->t_state & TS_ISOPEN)) {
1560 *(int *)data = i + 1;
1561 return 0;
1562 }
1563 }
1564 return EINVAL;
1565
1566 case VT_ACTIVATE: /* switch to screen *data */
1567 return switch_scr(scp, *(int *)data - 1);
1568
1569 case VT_WAITACTIVE: /* wait for switch to occur */
1570 if (*(int *)data > MAXCONS || *(int *)data < 0)
1571 return EINVAL;
1572 if (minor(dev) == *(int *)data - 1)
1573 return 0;
1574 if (*(int *)data == 0) {
1575 if (scp == cur_console)
1576 return 0;
1577 }
1578 else
1579 scp = console[*(int *)data - 1];
1580 while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH,
1581 "waitvt", 0)) == ERESTART) ;
1582 return error;
1583
1584 case VT_GETACTIVE:
1585 *(int *)data = get_scr_num()+1;
1586 return 0;
1587
1588 case KDENABIO: /* allow io operations */
1589 error = suser(p->p_ucred, &p->p_acflag);
1590 if (error != 0)
1591 return error;
1592 if (securelevel > 0)
1593 return EPERM;
1594 p->p_md.md_regs->tf_eflags |= PSL_IOPL;
1595 return 0;
1596
1597 case KDDISABIO: /* disallow io operations (default) */
1598 p->p_md.md_regs->tf_eflags &= ~PSL_IOPL;
1599 return 0;
1600
1601 case KDSKBSTATE: /* set keyboard state (locks) */
1602 if (*(int *)data & ~LOCK_KEY_MASK)
1603 return EINVAL;
1604 scp->status &= ~LOCK_KEY_MASK;
1605 scp->status |= *(int *)data;
1606 if (scp == cur_console)
1607 update_leds(scp->status);
1608 return 0;
1609
1610 case KDGKBSTATE: /* get keyboard state (locks) */
1611 *(int *)data = scp->status & LOCK_KEY_MASK;
1612 return 0;
1613
1614 case KDSETRAD: /* set keyboard repeat & delay rates */
1615 if (*(int *)data & ~0x7f)
1616 return EINVAL;
1617 if (sc_kbdc != NULL)
1618 set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data);
1619 return 0;
1620
1621 case KDSKBMODE: /* set keyboard mode */
1622 switch (*(int *)data) {
1623 case K_RAW: /* switch to RAW scancode mode */
1624 scp->status &= ~KBD_CODE_MODE;
1625 scp->status |= KBD_RAW_MODE;
1626 return 0;
1627
1628 case K_CODE: /* switch to CODE mode */
1629 scp->status &= ~KBD_RAW_MODE;
1630 scp->status |= KBD_CODE_MODE;
1631 return 0;
1632
1633 case K_XLATE: /* switch to XLT ascii mode */
1634 if (scp == cur_console && scp->status & KBD_RAW_MODE)
1635 shfts = ctls = alts = agrs = metas = accents = 0;
1636 scp->status &= ~(KBD_RAW_MODE | KBD_CODE_MODE);
1637 return 0;
1638 default:
1639 return EINVAL;
1640 }
1641 /* NOT REACHED */
1642
1643 case KDGKBMODE: /* get keyboard mode */
1644 *(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW :
1645 ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE);
1646 return 0;
1647
1648 case KDMKTONE: /* sound the bell */
1649 if (*(int*)data)
1650 do_bell(scp, (*(int*)data)&0xffff,
1651 (((*(int*)data)>>16)&0xffff)*hz/1000);
1652 else
1653 do_bell(scp, scp->bell_pitch, scp->bell_duration);
1654 return 0;
1655
1656 case KIOCSOUND: /* make tone (*data) hz */
1657 if (scp == cur_console) {
1658 if (*(int*)data) {
1659 int pitch = timer_freq / *(int*)data;
1660
1661 /* set command for counter 2, 2 byte write */
1662 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE))
1663 return EBUSY;
1664
1665 /* set pitch */
1666 outb(TIMER_CNTR2, pitch);
1667 outb(TIMER_CNTR2, (pitch>>8));
1668
1669 /* enable counter 2 output to speaker */
1670 outb(IO_PPI, inb(IO_PPI) | 3);
1671 }
1672 else {
1673 /* disable counter 2 output to speaker */
1674 outb(IO_PPI, inb(IO_PPI) & 0xFC);
1675 release_timer2();
1676 }
1677 }
1678 return 0;
1679
1680 case KDGKBTYPE: /* get keyboard type */
1681 *(int *)data = 0; /* type not known (yet) */
1682 return 0;
1683
1684 case KDSETLED: /* set keyboard LED status */
1685 if (*(int *)data & ~LED_MASK)
1686 return EINVAL;
1687 scp->status &= ~LED_MASK;
1688 scp->status |= *(int *)data;
1689 if (scp == cur_console)
1690 update_leds(scp->status);
1691 return 0;
1692
1693 case KDGETLED: /* get keyboard LED status */
1694 *(int *)data = scp->status & LED_MASK;
1695 return 0;
1696
1697 case GETFKEY: /* get functionkey string */
1698 if (*(u_short*)data < n_fkey_tab) {
1699 fkeyarg_t *ptr = (fkeyarg_t*)data;
1700 bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef,
1701 fkey_tab[ptr->keynum].len);
1702 ptr->flen = fkey_tab[ptr->keynum].len;
1703 return 0;
1704 }
1705 else
1706 return EINVAL;
1707
1708 case SETFKEY: /* set functionkey string */
1709 if (*(u_short*)data < n_fkey_tab) {
1710 fkeyarg_t *ptr = (fkeyarg_t*)data;
1711 bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str,
1712 min(ptr->flen, MAXFK));
1713 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK);
1714 return 0;
1715 }
1716 else
1717 return EINVAL;
1718
1719 case GIO_SCRNMAP: /* get output translation table */
1720 bcopy(&scr_map, data, sizeof(scr_map));
1721 return 0;
1722
1723 case PIO_SCRNMAP: /* set output translation table */
1724 bcopy(data, &scr_map, sizeof(scr_map));
1725 for (i=0; i<sizeof(scr_map); i++)
1726 scr_rmap[scr_map[i]] = i;
1727 return 0;
1728
1729 case GIO_KEYMAP: /* get keyboard translation table */
1730 bcopy(&key_map, data, sizeof(key_map));
1731 return 0;
1732
1733 case PIO_KEYMAP: /* set keyboard translation table */
1734 accents = 0;
1735 bzero(&accent_map, sizeof(accent_map));
1736 bcopy(data, &key_map, sizeof(key_map));
1737 return 0;
1738
1739 case GIO_DEADKEYMAP: /* get accent key translation table */
1740 bcopy(&accent_map, data, sizeof(accent_map));
1741 return 0;
1742
1743 case PIO_DEADKEYMAP: /* set accent key translation table */
1744 accents = 0;
1745 bcopy(data, &accent_map, sizeof(accent_map));
1746 return 0;
1747
1748 case PIO_FONT8x8: /* set 8x8 dot font */
1749 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1750 return ENXIO;
1751 bcopy(data, font_8, 8*256);
1752 fonts_loaded |= FONT_8;
1753 /*
1754 * FONT KLUDGE
1755 * Always use the font page #0. XXX
1756 * Don't load if the current font size is not 8x8.
1757 */
1758 if (ISTEXTSC(cur_console) && (cur_console->font_size < 14))
1759 copy_font(cur_console, LOAD, 8, font_8);
1760 return 0;
1761
1762 case GIO_FONT8x8: /* get 8x8 dot font */
1763 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1764 return ENXIO;
1765 if (fonts_loaded & FONT_8) {
1766 bcopy(font_8, data, 8*256);
1767 return 0;
1768 }
1769 else
1770 return ENXIO;
1771
1772 case PIO_FONT8x14: /* set 8x14 dot font */
1773 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1774 return ENXIO;
1775 bcopy(data, font_14, 14*256);
1776 fonts_loaded |= FONT_14;
1777 /*
1778 * FONT KLUDGE
1779 * Always use the font page #0. XXX
1780 * Don't load if the current font size is not 8x14.
1781 */
1782 if (ISTEXTSC(cur_console)
1783 && (cur_console->font_size >= 14) && (cur_console->font_size < 16))
1784 copy_font(cur_console, LOAD, 14, font_14);
1785 return 0;
1786
1787 case GIO_FONT8x14: /* get 8x14 dot font */
1788 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1789 return ENXIO;
1790 if (fonts_loaded & FONT_14) {
1791 bcopy(font_14, data, 14*256);
1792 return 0;
1793 }
1794 else
1795 return ENXIO;
1796
1797 case PIO_FONT8x16: /* set 8x16 dot font */
1798 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1799 return ENXIO;
1800 bcopy(data, font_16, 16*256);
1801 fonts_loaded |= FONT_16;
1802 /*
1803 * FONT KLUDGE
1804 * Always use the font page #0. XXX
1805 * Don't load if the current font size is not 8x16.
1806 */
1807 if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16))
1808 copy_font(cur_console, LOAD, 16, font_16);
1809 return 0;
1810
1811 case GIO_FONT8x16: /* get 8x16 dot font */
1812 if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1813 return ENXIO;
1814 if (fonts_loaded & FONT_16) {
1815 bcopy(font_16, data, 16*256);
1816 return 0;
1817 }
1818 else
1819 return ENXIO;
1820 default:
1821 break;
1822 }
1823
1824 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1825 if (error != ENOIOCTL)
1826 return(error);
1827 error = ttioctl(tp, cmd, data, flag);
1828 if (error != ENOIOCTL)
1829 return(error);
1830 return(ENOTTY);
1831}
1832
1833static void
1834scstart(struct tty *tp)
1835{
1836 struct clist *rbp;
1837 int s, len;
1838 u_char buf[PCBURST];
1839 scr_stat *scp = sc_get_scr_stat(tp->t_dev);
1840
1841 if (scp->status & SLKED || blink_in_progress)
1842 return; /* XXX who repeats the call when the above flags are cleared? */
1843 s = spltty();
1844 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
1845 tp->t_state |= TS_BUSY;
1846 rbp = &tp->t_outq;
1847 while (rbp->c_cc) {
1848 len = q_to_b(rbp, buf, PCBURST);
1849 splx(s);
1850 ansi_put(scp, buf, len);
1851 s = spltty();
1852 }
1853 tp->t_state &= ~TS_BUSY;
1854 ttwwakeup(tp);
1855 }
1856 splx(s);
1857}
1858
1859static void
1860scmousestart(struct tty *tp)
1861{
1862 struct clist *rbp;
1863 int s;
1864 u_char buf[PCBURST];
1865
1866 s = spltty();
1867 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
1868 tp->t_state |= TS_BUSY;
1869 rbp = &tp->t_outq;
1870 while (rbp->c_cc) {
1871 q_to_b(rbp, buf, PCBURST);
1872 }
1873 tp->t_state &= ~TS_BUSY;
1874 ttwwakeup(tp);
1875 }
1876 splx(s);
1877}
1878
1879void
1880sccnprobe(struct consdev *cp)
1881{
1882 struct isa_device *dvp;
1883
1884 /*
1885 * Take control if we are the highest priority enabled display device.
1886 */
1887 dvp = find_display();
1888 if (dvp == NULL || dvp->id_driver != &scdriver) {
1889 cp->cn_pri = CN_DEAD;
1890 return;
1891 }
1892
1893 if (!scvidprobe(dvp->id_unit, dvp->id_flags)) {
1894 cp->cn_pri = CN_DEAD;
1895 return;
1896 }
1897
1898 /* initialize required fields */
1899 cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE);
1900 cp->cn_pri = CN_INTERNAL;
1901
1902 sc_kbdc = kbdc_open(sc_port);
1903}
1904
1905void
1906sccninit(struct consdev *cp)
1907{
1908 scinit();
1909}
1910
1911void
1912sccnputc(dev_t dev, int c)
1913{
1914 u_char buf[1];
1915 int s;
1916 scr_stat *scp = console[0];
1917 term_stat save = scp->term;
1918
1919 scp->term = kernel_console;
1920 current_default = &kernel_default;
1921 if (scp == cur_console && !ISGRAPHSC(scp))
1922 remove_cursor_image(scp);
1923 buf[0] = c;
1924 ansi_put(scp, buf, 1);
1925 kernel_console = scp->term;
1926 current_default = &user_default;
1927 scp->term = save;
1928
1929 s = spltty(); /* block scintr and scrn_timer */
1930 sccnupdate(scp);
1931 splx(s);
1932}
1933
1934int
1935sccngetc(dev_t dev)
1936{
1937 int s = spltty(); /* block scintr and scrn_timer while we poll */
1938 int c;
1939
1940 /*
1941 * Stop the screen saver and update the screen if necessary.
1942 * What if we have been running in the screen saver code... XXX
1943 */
1944 scsplash_stick(FALSE);
1945 run_scrn_saver = FALSE;
1946 sccnupdate(cur_console);
1947
1948 c = scgetc(SCGETC_CN);
1949 splx(s);
1950 return(c);
1951}
1952
1953int
1954sccncheckc(dev_t dev)
1955{
1956 int s = spltty(); /* block scintr and scrn_timer while we poll */
1957 int c;
1958
1959 scsplash_stick(FALSE);
1960 run_scrn_saver = FALSE;
1961 sccnupdate(cur_console);
1962
1963 c = scgetc(SCGETC_CN | SCGETC_NONBLOCK);
1964 splx(s);
1965 return(c == NOKEY ? -1 : c); /* c == -1 can't happen */
1966}
1967
1968static void
1969sccnupdate(scr_stat *scp)
1970{
1971 /* this is a cut-down version of scrn_timer()... */
1972
1973 if (font_loading_in_progress)
1974 return;
1975
1976 if (panicstr || shutdown_in_progress) {
1977 scsplash_stick(FALSE);
1978 run_scrn_saver = FALSE;
1979 } else if (scp != cur_console) {
1980 return;
1981 }
1982
1983 if (!run_scrn_saver)
1984 scrn_idle = FALSE;
1985 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
1986 if (scp->status & SAVER_RUNNING)
1987 stop_scrn_saver(current_saver);
1988
1989 if (scp != cur_console || blink_in_progress || switch_in_progress)
1990 return;
1991
1992 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
1993 scrn_update(scp, TRUE);
1994}
1995
1996scr_stat
1997*sc_get_scr_stat(dev_t dev)
1998{
1999 int unit = minor(dev);
2000
2001 if (unit == SC_CONSOLE)
2002 return console[0];
2003 if (unit >= MAXCONS || unit < 0)
2004 return(NULL);
2005 return console[unit];
2006}
2007
2008static int
2009get_scr_num()
2010{
2011 int i = 0;
2012
2013 while ((i < MAXCONS) && (cur_console != console[i]))
2014 i++;
2015 return i < MAXCONS ? i : 0;
2016}
2017
2018static void
2019scrn_timer(void *arg)
2020{
2021 struct timeval tv;
2022 scr_stat *scp;
2023 int s;
2024
2025 /* don't do anything when we are touching font */
2026 if (font_loading_in_progress) {
2027 if (arg)
2028 timeout(scrn_timer, (void *)TRUE, hz / 10);
2029 return;
2030 }
2031 s = spltty();
2032
2033 /*
2034 * With release 2.1 of the Xaccel server, the keyboard is left
2035 * hanging pretty often. Apparently an interrupt from the
2036 * keyboard is lost, and I don't know why (yet).
2037 * This ugly hack calls scintr if input is ready for the keyboard
2038 * and conveniently hides the problem. XXX
2039 */
2040 /* Try removing anything stuck in the keyboard controller; whether
2041 * it's a keyboard scan code or mouse data. `scintr()' doesn't
2042 * read the mouse data directly, but `kbdio' routines will, as a
2043 * side effect.
2044 */
2045 if (kbdc_lock(sc_kbdc, TRUE)) {
2046 /*
2047 * We have seen the lock flag is not set. Let's reset the flag early;
2048 * otherwise `update_led()' failes which may want the lock
2049 * during `scintr()'.
2050 */
2051 kbdc_lock(sc_kbdc, FALSE);
2052 if (kbdc_data_ready(sc_kbdc))
2053 scintr(0);
2054 }
2055
2056 scp = cur_console;
2057
2058 /* should we stop the screen saver? */
2059 getmicrouptime(&tv);
2060 if (panicstr || shutdown_in_progress) {
2061 scsplash_stick(FALSE);
2062 run_scrn_saver = FALSE;
2063 }
2064 if (run_scrn_saver) {
2065 scrn_idle = (tv.tv_sec > scrn_time_stamp + scrn_blank_time);
2066 } else {
2067 scrn_time_stamp = tv.tv_sec;
2068 scrn_idle = FALSE;
2069 if (scrn_blank_time > 0)
2070 run_scrn_saver = TRUE;
2071 }
2072 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
2073 if (scp->status & SAVER_RUNNING)
2074 stop_scrn_saver(current_saver);
2075
2076 /* should we just return ? */
2077 if (blink_in_progress || switch_in_progress) {
2078 if (arg)
2079 timeout(scrn_timer, (void *)TRUE, hz / 10);
2080 splx(s);
2081 return;
2082 }
2083
2084 /* Update the screen */
2085 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
2086 scrn_update(scp, TRUE);
2087
2088 /* should we activate the screen saver? */
2089 if ((saver_mode == CONS_LKM_SAVER) && scrn_idle)
2090 if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING))
2091 scrn_saver(current_saver, TRUE);
2092
2093 if (arg)
2094 timeout(scrn_timer, (void *)TRUE, hz / 25);
2095 splx(s);
2096}
2097
2098static void
2099scrn_update(scr_stat *scp, int show_cursor)
2100{
2101 /* update screen image */
2102 if (scp->start <= scp->end)
2103 sc_bcopy(scp, scp->scr_buf, scp->start, scp->end, 0);
2104
2105 /* we are not to show the cursor and the mouse pointer... */
2106 if (!show_cursor) {
2107 scp->end = 0;
2108 scp->start = scp->xsize*scp->ysize - 1;
2109 return;
2110 }
2111
2112 /* update "pseudo" mouse pointer image */
2113 if (scp->status & MOUSE_VISIBLE) {
2114 /* did mouse move since last time ? */
2115 if (scp->status & MOUSE_MOVED) {
2116 /* do we need to remove old mouse pointer image ? */
2117 if (scp->mouse_cut_start != NULL ||
2118 (scp->mouse_pos-scp->scr_buf) <= scp->start ||
2119 (scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->end) {
2120 remove_mouse_image(scp);
2121 }
2122 scp->status &= ~MOUSE_MOVED;
2123 draw_mouse_image(scp);
2124 }
2125 else {
2126 /* mouse didn't move, has it been overwritten ? */
2127 if ((scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->start &&
2128 (scp->mouse_pos - scp->scr_buf) <= scp->end) {
2129 draw_mouse_image(scp);
2130 }
2131 }
2132 }
2133
2134 /* update cursor image */
2135 if (scp->status & CURSOR_ENABLED) {
2136 /* did cursor move since last time ? */
2137 if (scp->cursor_pos != scp->cursor_oldpos) {
2138 /* do we need to remove old cursor image ? */
2139 if ((scp->cursor_oldpos - scp->scr_buf) < scp->start ||
2140 ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) {
2141 remove_cursor_image(scp);
2142 }
2143 scp->cursor_oldpos = scp->cursor_pos;
2144 draw_cursor_image(scp);
2145 }
2146 else {
2147 /* cursor didn't move, has it been overwritten ? */
2148 if (scp->cursor_pos - scp->scr_buf >= scp->start &&
2149 scp->cursor_pos - scp->scr_buf <= scp->end) {
2150 draw_cursor_image(scp);
2151 } else {
2152 /* if its a blinking cursor, we may have to update it */
2153 if (flags & BLINK_CURSOR)
2154 draw_cursor_image(scp);
2155 }
2156 }
2157 blinkrate++;
2158 }
2159
2160 if (scp->mouse_cut_start != NULL)
2161 draw_cutmarking(scp);
2162
2163 scp->end = 0;
2164 scp->start = scp->xsize*scp->ysize - 1;
2165}
2166
2167int
2168add_scrn_saver(void (*this_saver)(int))
2169{
2170#ifdef SC_SPLASH_SCREEN
2171 if (current_saver == scsplash) {
2172 scsplash_stick(FALSE);
2173 stop_scrn_saver(scsplash);
2174 }
2175#endif
2176
2177 if (current_saver != default_saver)
2178 return EBUSY;
2179 run_scrn_saver = FALSE;
2180 saver_mode = CONS_LKM_SAVER;
2181 current_saver = this_saver;
2182 return 0;
2183}
2184
2185int
2186remove_scrn_saver(void (*this_saver)(int))
2187{
2188 if (current_saver != this_saver)
2189 return EINVAL;
2190
2191 /*
2192 * In order to prevent `current_saver' from being called by
2193 * the timeout routine `scrn_timer()' while we manipulate
2194 * the saver list, we shall set `current_saver' to `none_saver'
2195 * before stopping the current saver, rather than blocking by `splXX()'.
2196 */
2197 current_saver = none_saver;
2198 if (scrn_blanked > 0)
2199 stop_scrn_saver(this_saver);
2200
2201 if (scrn_blanked > 0)
2202 return EBUSY; /* XXX */
2203
2204 current_saver = default_saver;
2205 return 0;
2206}
2207
2208static void
2209scrn_saver(void (*saver)(int), int blank)
2210{
2211 static int busy = FALSE;
2212
2213 if (busy)
2214 return;
2215 busy = TRUE;
2216 (*saver)(blank);
2217 busy = FALSE;
2218}
2219
2220static void
2221stop_scrn_saver(void (*saver)(int))
2222{
2223 scrn_saver(saver, FALSE);
2224 run_scrn_saver = FALSE;
2225 /* the screen saver may have chosen not to stop after all... */
2226 if (scrn_blanked > 0)
2227 return;
2228
2229 mark_all(cur_console);
2230 if (delayed_next_scr)
2231 switch_scr(cur_console, delayed_next_scr - 1);
2232 wakeup((caddr_t)&scrn_blanked);
2233}
2234
2235static int
2236wait_scrn_saver_stop(void)
2237{
2238 int error = 0;
2239
2240 while (scrn_blanked > 0) {
2241 run_scrn_saver = FALSE;
2242 error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0);
2243 run_scrn_saver = FALSE;
2244 if (error != ERESTART)
2245 break;
2246 }
2247 return error;
2248}
2249
2250void
2251sc_clear_screen(scr_stat *scp)
2252{
2253 move_crsr(scp, 0, 0);
2254 scp->cursor_oldpos = scp->cursor_pos;
2255 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf,
2256 scp->xsize * scp->ysize);
2257 mark_all(scp);
2258 remove_cutmarking(scp);
2259}
2260
2261static int
2262switch_scr(scr_stat *scp, u_int next_scr)
2263{
2264 /* delay switch if actively updating screen */
2265 if (scrn_blanked > 0 || write_in_progress || blink_in_progress) {
2266 scsplash_stick(FALSE);
2267 run_scrn_saver = FALSE;
2268 delayed_next_scr = next_scr+1;
2269 return 0;
2270 }
2271
2272 if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid)))
2273 switch_in_progress = FALSE;
2274
2275 if (next_scr >= MAXCONS || switch_in_progress ||
2276 (cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) {
2277 do_bell(scp, BELL_PITCH, BELL_DURATION);
2278 return EINVAL;
2279 }
2280
2281 /* is the wanted virtual console open ? */
2282 if (next_scr) {
2283 struct tty *tp = VIRTUAL_TTY(next_scr);
2284 if (!(tp->t_state & TS_ISOPEN)) {
2285 do_bell(scp, BELL_PITCH, BELL_DURATION);
2286 return EINVAL;
2287 }
2288 }
2289
2290 switch_in_progress = TRUE;
2291 old_scp = cur_console;
2292 new_scp = console[next_scr];
2293 wakeup((caddr_t)&new_scp->smode);
2294 if (new_scp == old_scp) {
2295 switch_in_progress = FALSE;
2296 delayed_next_scr = FALSE;
2297 return 0;
2298 }
2299
2300 /* has controlling process died? */
2301 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid)))
2302 old_scp->smode.mode = VT_AUTO;
2303 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid)))
2304 new_scp->smode.mode = VT_AUTO;
2305
2306 /* check the modes and switch appropriately */
2307 if (old_scp->smode.mode == VT_PROCESS) {
2308 old_scp->status |= SWITCH_WAIT_REL;
2309 psignal(old_scp->proc, old_scp->smode.relsig);
2310 }
2311 else {
2312 exchange_scr();
2313 if (new_scp->smode.mode == VT_PROCESS) {
2314 new_scp->status |= SWITCH_WAIT_ACQ;
2315 psignal(new_scp->proc, new_scp->smode.acqsig);
2316 }
2317 else
2318 switch_in_progress = FALSE;
2319 }
2320 return 0;
2321}
2322
2323static void
2324exchange_scr(void)
2325{
2326 move_crsr(old_scp, old_scp->xpos, old_scp->ypos);
2327 cur_console = new_scp;
2313 if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) {
2314 if (adp_flags & V_ADP_MODECHANGE)
2315 set_mode(new_scp);
2316 }
2328 if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp))
2329 set_mode(new_scp);
2317 move_crsr(new_scp, new_scp->xpos, new_scp->ypos);
2318 if (ISTEXTSC(new_scp) && (flags & CHAR_CURSOR))
2319 set_destructive_cursor(new_scp);
2320 if (ISGRAPHSC(old_scp))
2321 load_palette(new_scp, palette);
2322 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE ||
2323 old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE)
2324 shfts = ctls = alts = agrs = metas = accents = 0;
2325 set_border(new_scp, new_scp->border);
2326 update_leds(new_scp->status);
2327 delayed_next_scr = FALSE;
2328 mark_all(new_scp);
2330 move_crsr(new_scp, new_scp->xpos, new_scp->ypos);
2331 if (ISTEXTSC(new_scp) && (flags & CHAR_CURSOR))
2332 set_destructive_cursor(new_scp);
2333 if (ISGRAPHSC(old_scp))
2334 load_palette(new_scp, palette);
2335 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE ||
2336 old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE)
2337 shfts = ctls = alts = agrs = metas = accents = 0;
2338 set_border(new_scp, new_scp->border);
2339 update_leds(new_scp->status);
2340 delayed_next_scr = FALSE;
2341 mark_all(new_scp);
2329
2330 /* FIXME: the screen size may be larger than a 64K segment. */
2331 if (ISPIXELSC(new_scp))
2332 bzero(Crtat, new_scp->xpixel*new_scp->ypixel/8);
2333}
2334
2335static void
2336scan_esc(scr_stat *scp, u_char c)
2337{
2338 static u_char ansi_col[16] =
2339 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15};
2340 int i, n;
2341 u_short *src, *dst, count;
2342
2343 if (scp->term.esc == 1) { /* seen ESC */
2344 switch (c) {
2345
2346 case '7': /* Save cursor position */
2347 scp->saved_xpos = scp->xpos;
2348 scp->saved_ypos = scp->ypos;
2349 break;
2350
2351 case '8': /* Restore saved cursor position */
2352 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0)
2353 move_crsr(scp, scp->saved_xpos, scp->saved_ypos);
2354 break;
2355
2356 case '[': /* Start ESC [ sequence */
2357 scp->term.esc = 2;
2358 scp->term.last_param = -1;
2359 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
2360 scp->term.param[i] = 1;
2361 scp->term.num_param = 0;
2362 return;
2363
2364 case 'M': /* Move cursor up 1 line, scroll if at top */
2365 if (scp->ypos > 0)
2366 move_crsr(scp, scp->xpos, scp->ypos - 1);
2367 else {
2368 bcopy(scp->scr_buf, scp->scr_buf + scp->xsize,
2369 (scp->ysize - 1) * scp->xsize * sizeof(u_short));
2370 fillw(scp->term.cur_color | scr_map[0x20],
2371 scp->scr_buf, scp->xsize);
2372 mark_all(scp);
2373 }
2374 break;
2375#if notyet
2376 case 'Q':
2377 scp->term.esc = 4;
2378 return;
2379#endif
2380 case 'c': /* Clear screen & home */
2381 sc_clear_screen(scp);
2382 break;
2383
2384 case '(': /* iso-2022: designate 94 character set to G0 */
2385 scp->term.esc = 5;
2386 return;
2387 }
2388 }
2389 else if (scp->term.esc == 2) { /* seen ESC [ */
2390 if (c >= '0' && c <= '9') {
2391 if (scp->term.num_param < MAX_ESC_PAR) {
2392 if (scp->term.last_param != scp->term.num_param) {
2393 scp->term.last_param = scp->term.num_param;
2394 scp->term.param[scp->term.num_param] = 0;
2395 }
2396 else
2397 scp->term.param[scp->term.num_param] *= 10;
2398 scp->term.param[scp->term.num_param] += c - '0';
2399 return;
2400 }
2401 }
2402 scp->term.num_param = scp->term.last_param + 1;
2403 switch (c) {
2404
2405 case ';':
2406 if (scp->term.num_param < MAX_ESC_PAR)
2407 return;
2408 break;
2409
2410 case '=':
2411 scp->term.esc = 3;
2412 scp->term.last_param = -1;
2413 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
2414 scp->term.param[i] = 1;
2415 scp->term.num_param = 0;
2416 return;
2417
2418 case 'A': /* up n rows */
2419 n = scp->term.param[0]; if (n < 1) n = 1;
2420 move_crsr(scp, scp->xpos, scp->ypos - n);
2421 break;
2422
2423 case 'B': /* down n rows */
2424 n = scp->term.param[0]; if (n < 1) n = 1;
2425 move_crsr(scp, scp->xpos, scp->ypos + n);
2426 break;
2427
2428 case 'C': /* right n columns */
2429 n = scp->term.param[0]; if (n < 1) n = 1;
2430 move_crsr(scp, scp->xpos + n, scp->ypos);
2431 break;
2432
2433 case 'D': /* left n columns */
2434 n = scp->term.param[0]; if (n < 1) n = 1;
2435 move_crsr(scp, scp->xpos - n, scp->ypos);
2436 break;
2437
2438 case 'E': /* cursor to start of line n lines down */
2439 n = scp->term.param[0]; if (n < 1) n = 1;
2440 move_crsr(scp, 0, scp->ypos + n);
2441 break;
2442
2443 case 'F': /* cursor to start of line n lines up */
2444 n = scp->term.param[0]; if (n < 1) n = 1;
2445 move_crsr(scp, 0, scp->ypos - n);
2446 break;
2447
2448 case 'f': /* Cursor move */
2449 case 'H':
2450 if (scp->term.num_param == 0)
2451 move_crsr(scp, 0, 0);
2452 else if (scp->term.num_param == 2)
2453 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1);
2454 break;
2455
2456 case 'J': /* Clear all or part of display */
2457 if (scp->term.num_param == 0)
2458 n = 0;
2459 else
2460 n = scp->term.param[0];
2461 switch (n) {
2462 case 0: /* clear form cursor to end of display */
2463 fillw(scp->term.cur_color | scr_map[0x20],
2464 scp->cursor_pos,
2465 scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos);
2466 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2467 mark_for_update(scp, scp->xsize * scp->ysize - 1);
2468 remove_cutmarking(scp);
2469 break;
2470 case 1: /* clear from beginning of display to cursor */
2471 fillw(scp->term.cur_color | scr_map[0x20],
2472 scp->scr_buf,
2473 scp->cursor_pos - scp->scr_buf);
2474 mark_for_update(scp, 0);
2475 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2476 remove_cutmarking(scp);
2477 break;
2478 case 2: /* clear entire display */
2479 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf,
2480 scp->xsize * scp->ysize);
2481 mark_all(scp);
2482 remove_cutmarking(scp);
2483 break;
2484 }
2485 break;
2486
2487 case 'K': /* Clear all or part of line */
2488 if (scp->term.num_param == 0)
2489 n = 0;
2490 else
2491 n = scp->term.param[0];
2492 switch (n) {
2493 case 0: /* clear form cursor to end of line */
2494 fillw(scp->term.cur_color | scr_map[0x20],
2495 scp->cursor_pos,
2496 scp->xsize - scp->xpos);
2497 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2498 mark_for_update(scp, scp->cursor_pos - scp->scr_buf +
2342}
2343
2344static void
2345scan_esc(scr_stat *scp, u_char c)
2346{
2347 static u_char ansi_col[16] =
2348 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15};
2349 int i, n;
2350 u_short *src, *dst, count;
2351
2352 if (scp->term.esc == 1) { /* seen ESC */
2353 switch (c) {
2354
2355 case '7': /* Save cursor position */
2356 scp->saved_xpos = scp->xpos;
2357 scp->saved_ypos = scp->ypos;
2358 break;
2359
2360 case '8': /* Restore saved cursor position */
2361 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0)
2362 move_crsr(scp, scp->saved_xpos, scp->saved_ypos);
2363 break;
2364
2365 case '[': /* Start ESC [ sequence */
2366 scp->term.esc = 2;
2367 scp->term.last_param = -1;
2368 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
2369 scp->term.param[i] = 1;
2370 scp->term.num_param = 0;
2371 return;
2372
2373 case 'M': /* Move cursor up 1 line, scroll if at top */
2374 if (scp->ypos > 0)
2375 move_crsr(scp, scp->xpos, scp->ypos - 1);
2376 else {
2377 bcopy(scp->scr_buf, scp->scr_buf + scp->xsize,
2378 (scp->ysize - 1) * scp->xsize * sizeof(u_short));
2379 fillw(scp->term.cur_color | scr_map[0x20],
2380 scp->scr_buf, scp->xsize);
2381 mark_all(scp);
2382 }
2383 break;
2384#if notyet
2385 case 'Q':
2386 scp->term.esc = 4;
2387 return;
2388#endif
2389 case 'c': /* Clear screen & home */
2390 sc_clear_screen(scp);
2391 break;
2392
2393 case '(': /* iso-2022: designate 94 character set to G0 */
2394 scp->term.esc = 5;
2395 return;
2396 }
2397 }
2398 else if (scp->term.esc == 2) { /* seen ESC [ */
2399 if (c >= '0' && c <= '9') {
2400 if (scp->term.num_param < MAX_ESC_PAR) {
2401 if (scp->term.last_param != scp->term.num_param) {
2402 scp->term.last_param = scp->term.num_param;
2403 scp->term.param[scp->term.num_param] = 0;
2404 }
2405 else
2406 scp->term.param[scp->term.num_param] *= 10;
2407 scp->term.param[scp->term.num_param] += c - '0';
2408 return;
2409 }
2410 }
2411 scp->term.num_param = scp->term.last_param + 1;
2412 switch (c) {
2413
2414 case ';':
2415 if (scp->term.num_param < MAX_ESC_PAR)
2416 return;
2417 break;
2418
2419 case '=':
2420 scp->term.esc = 3;
2421 scp->term.last_param = -1;
2422 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
2423 scp->term.param[i] = 1;
2424 scp->term.num_param = 0;
2425 return;
2426
2427 case 'A': /* up n rows */
2428 n = scp->term.param[0]; if (n < 1) n = 1;
2429 move_crsr(scp, scp->xpos, scp->ypos - n);
2430 break;
2431
2432 case 'B': /* down n rows */
2433 n = scp->term.param[0]; if (n < 1) n = 1;
2434 move_crsr(scp, scp->xpos, scp->ypos + n);
2435 break;
2436
2437 case 'C': /* right n columns */
2438 n = scp->term.param[0]; if (n < 1) n = 1;
2439 move_crsr(scp, scp->xpos + n, scp->ypos);
2440 break;
2441
2442 case 'D': /* left n columns */
2443 n = scp->term.param[0]; if (n < 1) n = 1;
2444 move_crsr(scp, scp->xpos - n, scp->ypos);
2445 break;
2446
2447 case 'E': /* cursor to start of line n lines down */
2448 n = scp->term.param[0]; if (n < 1) n = 1;
2449 move_crsr(scp, 0, scp->ypos + n);
2450 break;
2451
2452 case 'F': /* cursor to start of line n lines up */
2453 n = scp->term.param[0]; if (n < 1) n = 1;
2454 move_crsr(scp, 0, scp->ypos - n);
2455 break;
2456
2457 case 'f': /* Cursor move */
2458 case 'H':
2459 if (scp->term.num_param == 0)
2460 move_crsr(scp, 0, 0);
2461 else if (scp->term.num_param == 2)
2462 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1);
2463 break;
2464
2465 case 'J': /* Clear all or part of display */
2466 if (scp->term.num_param == 0)
2467 n = 0;
2468 else
2469 n = scp->term.param[0];
2470 switch (n) {
2471 case 0: /* clear form cursor to end of display */
2472 fillw(scp->term.cur_color | scr_map[0x20],
2473 scp->cursor_pos,
2474 scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos);
2475 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2476 mark_for_update(scp, scp->xsize * scp->ysize - 1);
2477 remove_cutmarking(scp);
2478 break;
2479 case 1: /* clear from beginning of display to cursor */
2480 fillw(scp->term.cur_color | scr_map[0x20],
2481 scp->scr_buf,
2482 scp->cursor_pos - scp->scr_buf);
2483 mark_for_update(scp, 0);
2484 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2485 remove_cutmarking(scp);
2486 break;
2487 case 2: /* clear entire display */
2488 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf,
2489 scp->xsize * scp->ysize);
2490 mark_all(scp);
2491 remove_cutmarking(scp);
2492 break;
2493 }
2494 break;
2495
2496 case 'K': /* Clear all or part of line */
2497 if (scp->term.num_param == 0)
2498 n = 0;
2499 else
2500 n = scp->term.param[0];
2501 switch (n) {
2502 case 0: /* clear form cursor to end of line */
2503 fillw(scp->term.cur_color | scr_map[0x20],
2504 scp->cursor_pos,
2505 scp->xsize - scp->xpos);
2506 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2507 mark_for_update(scp, scp->cursor_pos - scp->scr_buf +
2499 scp->xsize - scp->xpos);
2508 scp->xsize - 1 - scp->xpos);
2500 break;
2501 case 1: /* clear from beginning of line to cursor */
2502 fillw(scp->term.cur_color | scr_map[0x20],
2503 scp->cursor_pos - scp->xpos,
2504 scp->xpos + 1);
2505 mark_for_update(scp, scp->ypos * scp->xsize);
2506 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2507 break;
2508 case 2: /* clear entire line */
2509 fillw(scp->term.cur_color | scr_map[0x20],
2510 scp->cursor_pos - scp->xpos,
2511 scp->xsize);
2512 mark_for_update(scp, scp->ypos * scp->xsize);
2509 break;
2510 case 1: /* clear from beginning of line to cursor */
2511 fillw(scp->term.cur_color | scr_map[0x20],
2512 scp->cursor_pos - scp->xpos,
2513 scp->xpos + 1);
2514 mark_for_update(scp, scp->ypos * scp->xsize);
2515 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2516 break;
2517 case 2: /* clear entire line */
2518 fillw(scp->term.cur_color | scr_map[0x20],
2519 scp->cursor_pos - scp->xpos,
2520 scp->xsize);
2521 mark_for_update(scp, scp->ypos * scp->xsize);
2513 mark_for_update(scp, (scp->ypos + 1) * scp->xsize);
2522 mark_for_update(scp, (scp->ypos + 1) * scp->xsize - 1);
2514 break;
2515 }
2516 break;
2517
2518 case 'L': /* Insert n lines */
2519 n = scp->term.param[0]; if (n < 1) n = 1;
2520 if (n > scp->ysize - scp->ypos)
2521 n = scp->ysize - scp->ypos;
2522 src = scp->scr_buf + scp->ypos * scp->xsize;
2523 dst = src + n * scp->xsize;
2524 count = scp->ysize - (scp->ypos + n);
2525 bcopy(src, dst, count * scp->xsize * sizeof(u_short));
2526 fillw(scp->term.cur_color | scr_map[0x20], src,
2527 n * scp->xsize);
2528 mark_for_update(scp, scp->ypos * scp->xsize);
2529 mark_for_update(scp, scp->xsize * scp->ysize - 1);
2530 break;
2531
2532 case 'M': /* Delete n lines */
2533 n = scp->term.param[0]; if (n < 1) n = 1;
2534 if (n > scp->ysize - scp->ypos)
2535 n = scp->ysize - scp->ypos;
2536 dst = scp->scr_buf + scp->ypos * scp->xsize;
2537 src = dst + n * scp->xsize;
2538 count = scp->ysize - (scp->ypos + n);
2539 bcopy(src, dst, count * scp->xsize * sizeof(u_short));
2540 src = dst + count * scp->xsize;
2541 fillw(scp->term.cur_color | scr_map[0x20], src,
2542 n * scp->xsize);
2543 mark_for_update(scp, scp->ypos * scp->xsize);
2544 mark_for_update(scp, scp->xsize * scp->ysize - 1);
2545 break;
2546
2547 case 'P': /* Delete n chars */
2548 n = scp->term.param[0]; if (n < 1) n = 1;
2549 if (n > scp->xsize - scp->xpos)
2550 n = scp->xsize - scp->xpos;
2551 dst = scp->cursor_pos;
2552 src = dst + n;
2553 count = scp->xsize - (scp->xpos + n);
2554 bcopy(src, dst, count * sizeof(u_short));
2555 src = dst + count;
2556 fillw(scp->term.cur_color | scr_map[0x20], src, n);
2557 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2523 break;
2524 }
2525 break;
2526
2527 case 'L': /* Insert n lines */
2528 n = scp->term.param[0]; if (n < 1) n = 1;
2529 if (n > scp->ysize - scp->ypos)
2530 n = scp->ysize - scp->ypos;
2531 src = scp->scr_buf + scp->ypos * scp->xsize;
2532 dst = src + n * scp->xsize;
2533 count = scp->ysize - (scp->ypos + n);
2534 bcopy(src, dst, count * scp->xsize * sizeof(u_short));
2535 fillw(scp->term.cur_color | scr_map[0x20], src,
2536 n * scp->xsize);
2537 mark_for_update(scp, scp->ypos * scp->xsize);
2538 mark_for_update(scp, scp->xsize * scp->ysize - 1);
2539 break;
2540
2541 case 'M': /* Delete n lines */
2542 n = scp->term.param[0]; if (n < 1) n = 1;
2543 if (n > scp->ysize - scp->ypos)
2544 n = scp->ysize - scp->ypos;
2545 dst = scp->scr_buf + scp->ypos * scp->xsize;
2546 src = dst + n * scp->xsize;
2547 count = scp->ysize - (scp->ypos + n);
2548 bcopy(src, dst, count * scp->xsize * sizeof(u_short));
2549 src = dst + count * scp->xsize;
2550 fillw(scp->term.cur_color | scr_map[0x20], src,
2551 n * scp->xsize);
2552 mark_for_update(scp, scp->ypos * scp->xsize);
2553 mark_for_update(scp, scp->xsize * scp->ysize - 1);
2554 break;
2555
2556 case 'P': /* Delete n chars */
2557 n = scp->term.param[0]; if (n < 1) n = 1;
2558 if (n > scp->xsize - scp->xpos)
2559 n = scp->xsize - scp->xpos;
2560 dst = scp->cursor_pos;
2561 src = dst + n;
2562 count = scp->xsize - (scp->xpos + n);
2563 bcopy(src, dst, count * sizeof(u_short));
2564 src = dst + count;
2565 fillw(scp->term.cur_color | scr_map[0x20], src, n);
2566 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2558 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count);
2567 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1);
2559 break;
2560
2561 case '@': /* Insert n chars */
2562 n = scp->term.param[0]; if (n < 1) n = 1;
2563 if (n > scp->xsize - scp->xpos)
2564 n = scp->xsize - scp->xpos;
2565 src = scp->cursor_pos;
2566 dst = src + n;
2567 count = scp->xsize - (scp->xpos + n);
2568 bcopy(src, dst, count * sizeof(u_short));
2569 fillw(scp->term.cur_color | scr_map[0x20], src, n);
2570 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2568 break;
2569
2570 case '@': /* Insert n chars */
2571 n = scp->term.param[0]; if (n < 1) n = 1;
2572 if (n > scp->xsize - scp->xpos)
2573 n = scp->xsize - scp->xpos;
2574 src = scp->cursor_pos;
2575 dst = src + n;
2576 count = scp->xsize - (scp->xpos + n);
2577 bcopy(src, dst, count * sizeof(u_short));
2578 fillw(scp->term.cur_color | scr_map[0x20], src, n);
2579 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2571 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count);
2580 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1);
2572 break;
2573
2574 case 'S': /* scroll up n lines */
2575 n = scp->term.param[0]; if (n < 1) n = 1;
2576 if (n > scp->ysize)
2577 n = scp->ysize;
2578 bcopy(scp->scr_buf + (scp->xsize * n),
2579 scp->scr_buf,
2580 scp->xsize * (scp->ysize - n) * sizeof(u_short));
2581 fillw(scp->term.cur_color | scr_map[0x20],
2582 scp->scr_buf + scp->xsize * (scp->ysize - n),
2583 scp->xsize * n);
2584 mark_all(scp);
2585 break;
2586
2587 case 'T': /* scroll down n lines */
2588 n = scp->term.param[0]; if (n < 1) n = 1;
2589 if (n > scp->ysize)
2590 n = scp->ysize;
2591 bcopy(scp->scr_buf,
2592 scp->scr_buf + (scp->xsize * n),
2593 scp->xsize * (scp->ysize - n) *
2594 sizeof(u_short));
2595 fillw(scp->term.cur_color | scr_map[0x20],
2596 scp->scr_buf, scp->xsize * n);
2597 mark_all(scp);
2598 break;
2599
2600 case 'X': /* erase n characters in line */
2601 n = scp->term.param[0]; if (n < 1) n = 1;
2602 if (n > scp->xsize - scp->xpos)
2603 n = scp->xsize - scp->xpos;
2604 fillw(scp->term.cur_color | scr_map[0x20],
2605 scp->cursor_pos, n);
2606 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2581 break;
2582
2583 case 'S': /* scroll up n lines */
2584 n = scp->term.param[0]; if (n < 1) n = 1;
2585 if (n > scp->ysize)
2586 n = scp->ysize;
2587 bcopy(scp->scr_buf + (scp->xsize * n),
2588 scp->scr_buf,
2589 scp->xsize * (scp->ysize - n) * sizeof(u_short));
2590 fillw(scp->term.cur_color | scr_map[0x20],
2591 scp->scr_buf + scp->xsize * (scp->ysize - n),
2592 scp->xsize * n);
2593 mark_all(scp);
2594 break;
2595
2596 case 'T': /* scroll down n lines */
2597 n = scp->term.param[0]; if (n < 1) n = 1;
2598 if (n > scp->ysize)
2599 n = scp->ysize;
2600 bcopy(scp->scr_buf,
2601 scp->scr_buf + (scp->xsize * n),
2602 scp->xsize * (scp->ysize - n) *
2603 sizeof(u_short));
2604 fillw(scp->term.cur_color | scr_map[0x20],
2605 scp->scr_buf, scp->xsize * n);
2606 mark_all(scp);
2607 break;
2608
2609 case 'X': /* erase n characters in line */
2610 n = scp->term.param[0]; if (n < 1) n = 1;
2611 if (n > scp->xsize - scp->xpos)
2612 n = scp->xsize - scp->xpos;
2613 fillw(scp->term.cur_color | scr_map[0x20],
2614 scp->cursor_pos, n);
2615 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2607 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n);
2616 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n - 1);
2608 break;
2609
2610 case 'Z': /* move n tabs backwards */
2611 n = scp->term.param[0]; if (n < 1) n = 1;
2612 if ((i = scp->xpos & 0xf8) == scp->xpos)
2613 i -= 8*n;
2614 else
2615 i -= 8*(n-1);
2616 if (i < 0)
2617 i = 0;
2618 move_crsr(scp, i, scp->ypos);
2619 break;
2620
2621 case '`': /* move cursor to column n */
2622 n = scp->term.param[0]; if (n < 1) n = 1;
2623 move_crsr(scp, n - 1, scp->ypos);
2624 break;
2625
2626 case 'a': /* move cursor n columns to the right */
2627 n = scp->term.param[0]; if (n < 1) n = 1;
2628 move_crsr(scp, scp->xpos + n, scp->ypos);
2629 break;
2630
2631 case 'd': /* move cursor to row n */
2632 n = scp->term.param[0]; if (n < 1) n = 1;
2633 move_crsr(scp, scp->xpos, n - 1);
2634 break;
2635
2636 case 'e': /* move cursor n rows down */
2637 n = scp->term.param[0]; if (n < 1) n = 1;
2638 move_crsr(scp, scp->xpos, scp->ypos + n);
2639 break;
2640
2641 case 'm': /* change attribute */
2642 if (scp->term.num_param == 0) {
2643 scp->term.attr_mask = NORMAL_ATTR;
2644 scp->term.cur_attr =
2645 scp->term.cur_color = scp->term.std_color;
2646 break;
2647 }
2648 for (i = 0; i < scp->term.num_param; i++) {
2649 switch (n = scp->term.param[i]) {
2650 case 0: /* back to normal */
2651 scp->term.attr_mask = NORMAL_ATTR;
2652 scp->term.cur_attr =
2653 scp->term.cur_color = scp->term.std_color;
2654 break;
2655 case 1: /* bold */
2656 scp->term.attr_mask |= BOLD_ATTR;
2657 scp->term.cur_attr = mask2attr(&scp->term);
2658 break;
2659 case 4: /* underline */
2660 scp->term.attr_mask |= UNDERLINE_ATTR;
2661 scp->term.cur_attr = mask2attr(&scp->term);
2662 break;
2663 case 5: /* blink */
2664 scp->term.attr_mask |= BLINK_ATTR;
2665 scp->term.cur_attr = mask2attr(&scp->term);
2666 break;
2667 case 7: /* reverse video */
2668 scp->term.attr_mask |= REVERSE_ATTR;
2669 scp->term.cur_attr = mask2attr(&scp->term);
2670 break;
2671 case 30: case 31: /* set fg color */
2672 case 32: case 33: case 34:
2673 case 35: case 36: case 37:
2674 scp->term.attr_mask |= FOREGROUND_CHANGED;
2675 scp->term.cur_color =
2676 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8);
2677 scp->term.cur_attr = mask2attr(&scp->term);
2678 break;
2679 case 40: case 41: /* set bg color */
2680 case 42: case 43: case 44:
2681 case 45: case 46: case 47:
2682 scp->term.attr_mask |= BACKGROUND_CHANGED;
2683 scp->term.cur_color =
2684 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12);
2685 scp->term.cur_attr = mask2attr(&scp->term);
2686 break;
2687 }
2688 }
2689 break;
2690
2691 case 's': /* Save cursor position */
2692 scp->saved_xpos = scp->xpos;
2693 scp->saved_ypos = scp->ypos;
2694 break;
2695
2696 case 'u': /* Restore saved cursor position */
2697 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0)
2698 move_crsr(scp, scp->saved_xpos, scp->saved_ypos);
2699 break;
2700
2701 case 'x':
2702 if (scp->term.num_param == 0)
2703 n = 0;
2704 else
2705 n = scp->term.param[0];
2706 switch (n) {
2707 case 0: /* reset attributes */
2708 scp->term.attr_mask = NORMAL_ATTR;
2709 scp->term.cur_attr =
2710 scp->term.cur_color = scp->term.std_color =
2711 current_default->std_color;
2712 scp->term.rev_color = current_default->rev_color;
2713 break;
2714 case 1: /* set ansi background */
2715 scp->term.attr_mask &= ~BACKGROUND_CHANGED;
2716 scp->term.cur_color = scp->term.std_color =
2717 (scp->term.std_color & 0x0F00) |
2718 (ansi_col[(scp->term.param[1])&0x0F]<<12);
2719 scp->term.cur_attr = mask2attr(&scp->term);
2720 break;
2721 case 2: /* set ansi foreground */
2722 scp->term.attr_mask &= ~FOREGROUND_CHANGED;
2723 scp->term.cur_color = scp->term.std_color =
2724 (scp->term.std_color & 0xF000) |
2725 (ansi_col[(scp->term.param[1])&0x0F]<<8);
2726 scp->term.cur_attr = mask2attr(&scp->term);
2727 break;
2728 case 3: /* set ansi attribute directly */
2729 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED);
2730 scp->term.cur_color = scp->term.std_color =
2731 (scp->term.param[1]&0xFF)<<8;
2732 scp->term.cur_attr = mask2attr(&scp->term);
2733 break;
2734 case 5: /* set ansi reverse video background */
2735 scp->term.rev_color =
2736 (scp->term.rev_color & 0x0F00) |
2737 (ansi_col[(scp->term.param[1])&0x0F]<<12);
2738 scp->term.cur_attr = mask2attr(&scp->term);
2739 break;
2740 case 6: /* set ansi reverse video foreground */
2741 scp->term.rev_color =
2742 (scp->term.rev_color & 0xF000) |
2743 (ansi_col[(scp->term.param[1])&0x0F]<<8);
2744 scp->term.cur_attr = mask2attr(&scp->term);
2745 break;
2746 case 7: /* set ansi reverse video directly */
2747 scp->term.rev_color =
2748 (scp->term.param[1]&0xFF)<<8;
2749 scp->term.cur_attr = mask2attr(&scp->term);
2750 break;
2751 }
2752 break;
2753
2754 case 'z': /* switch to (virtual) console n */
2755 if (scp->term.num_param == 1)
2756 switch_scr(scp, scp->term.param[0]);
2757 break;
2758 }
2759 }
2760 else if (scp->term.esc == 3) { /* seen ESC [0-9]+ = */
2761 if (c >= '0' && c <= '9') {
2762 if (scp->term.num_param < MAX_ESC_PAR) {
2763 if (scp->term.last_param != scp->term.num_param) {
2764 scp->term.last_param = scp->term.num_param;
2765 scp->term.param[scp->term.num_param] = 0;
2766 }
2767 else
2768 scp->term.param[scp->term.num_param] *= 10;
2769 scp->term.param[scp->term.num_param] += c - '0';
2770 return;
2771 }
2772 }
2773 scp->term.num_param = scp->term.last_param + 1;
2774 switch (c) {
2775
2776 case ';':
2777 if (scp->term.num_param < MAX_ESC_PAR)
2778 return;
2779 break;
2780
2781 case 'A': /* set display border color */
2782 if (scp->term.num_param == 1) {
2783 scp->border=scp->term.param[0] & 0xff;
2784 if (scp == cur_console)
2785 set_border(cur_console, scp->border);
2786 }
2787 break;
2788
2789 case 'B': /* set bell pitch and duration */
2790 if (scp->term.num_param == 2) {
2791 scp->bell_pitch = scp->term.param[0];
2792 scp->bell_duration = scp->term.param[1];
2793 }
2794 break;
2795
2796 case 'C': /* set cursor type & shape */
2797 if (scp->term.num_param == 1) {
2798 if (scp->term.param[0] & 0x01)
2799 flags |= BLINK_CURSOR;
2800 else
2801 flags &= ~BLINK_CURSOR;
2802 if ((scp->term.param[0] & 0x02)
2803 && ISFONTAVAIL(get_adapter(scp)->va_flags))
2804 flags |= CHAR_CURSOR;
2805 else
2806 flags &= ~CHAR_CURSOR;
2807 }
2808 else if (scp->term.num_param == 2) {
2809 scp->cursor_start = scp->term.param[0] & 0x1F;
2810 scp->cursor_end = scp->term.param[1] & 0x1F;
2811 }
2812 /*
2813 * The cursor shape is global property; all virtual consoles
2814 * are affected. Update the cursor in the current console...
2815 */
2816 if (!ISGRAPHSC(cur_console)) {
2817 remove_cursor_image(cur_console);
2818 if (flags & CHAR_CURSOR)
2819 set_destructive_cursor(cur_console);
2820 draw_cursor_image(cur_console);
2821 }
2822 break;
2823
2824 case 'F': /* set ansi foreground */
2825 if (scp->term.num_param == 1) {
2826 scp->term.attr_mask &= ~FOREGROUND_CHANGED;
2827 scp->term.cur_color = scp->term.std_color =
2828 (scp->term.std_color & 0xF000)
2829 | ((scp->term.param[0] & 0x0F) << 8);
2830 scp->term.cur_attr = mask2attr(&scp->term);
2831 }
2832 break;
2833
2834 case 'G': /* set ansi background */
2835 if (scp->term.num_param == 1) {
2836 scp->term.attr_mask &= ~BACKGROUND_CHANGED;
2837 scp->term.cur_color = scp->term.std_color =
2838 (scp->term.std_color & 0x0F00)
2839 | ((scp->term.param[0] & 0x0F) << 12);
2840 scp->term.cur_attr = mask2attr(&scp->term);
2841 }
2842 break;
2843
2844 case 'H': /* set ansi reverse video foreground */
2845 if (scp->term.num_param == 1) {
2846 scp->term.rev_color =
2847 (scp->term.rev_color & 0xF000)
2848 | ((scp->term.param[0] & 0x0F) << 8);
2849 scp->term.cur_attr = mask2attr(&scp->term);
2850 }
2851 break;
2852
2853 case 'I': /* set ansi reverse video background */
2854 if (scp->term.num_param == 1) {
2855 scp->term.rev_color =
2856 (scp->term.rev_color & 0x0F00)
2857 | ((scp->term.param[0] & 0x0F) << 12);
2858 scp->term.cur_attr = mask2attr(&scp->term);
2859 }
2860 break;
2861 }
2862 }
2863#if notyet
2864 else if (scp->term.esc == 4) { /* seen ESC Q */
2865 /* to be filled */
2866 }
2867#endif
2868 else if (scp->term.esc == 5) { /* seen ESC ( */
2869 switch (c) {
2870 case 'B': /* iso-2022: desginate ASCII into G0 */
2871 break;
2872 /* other items to be filled */
2873 default:
2874 break;
2875 }
2876 }
2877 scp->term.esc = 0;
2878}
2879
2880static void
2881ansi_put(scr_stat *scp, u_char *buf, int len)
2882{
2883 u_char *ptr = buf;
2884
2885 /* make screensaver happy */
2886 if (!sticky_splash && scp == cur_console)
2887 run_scrn_saver = FALSE;
2888
2889 write_in_progress++;
2890outloop:
2891 if (scp->term.esc) {
2892 scan_esc(scp, *ptr++);
2893 len--;
2894 }
2895 else if (PRINTABLE(*ptr)) { /* Print only printables */
2896 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos);
2897 u_short cur_attr = scp->term.cur_attr;
2898 u_short *cursor_pos = scp->cursor_pos;
2899 do {
2900 /*
2901 * gcc-2.6.3 generates poor (un)sign extension code. Casting the
2902 * pointers in the following to volatile should have no effect,
2903 * but in fact speeds up this inner loop from 26 to 18 cycles
2904 * (+ cache misses) on i486's.
2905 */
2906#define UCVP(ucp) ((u_char volatile *)(ucp))
2907 *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr;
2908 ptr++;
2909 cnt--;
2910 } while (cnt && PRINTABLE(*ptr));
2911 len -= (cursor_pos - scp->cursor_pos);
2912 scp->xpos += (cursor_pos - scp->cursor_pos);
2913 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2914 mark_for_update(scp, cursor_pos - scp->scr_buf);
2915 scp->cursor_pos = cursor_pos;
2916 if (scp->xpos >= scp->xsize) {
2917 scp->xpos = 0;
2918 scp->ypos++;
2919 }
2920 }
2921 else {
2922 switch(*ptr) {
2923 case 0x07:
2924 do_bell(scp, scp->bell_pitch, scp->bell_duration);
2925 break;
2926
2927 case 0x08: /* non-destructive backspace */
2928 if (scp->cursor_pos > scp->scr_buf) {
2929 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2930 scp->cursor_pos--;
2931 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2932 if (scp->xpos > 0)
2933 scp->xpos--;
2934 else {
2935 scp->xpos += scp->xsize - 1;
2936 scp->ypos--;
2937 }
2938 }
2939 break;
2940
2941 case 0x09: /* non-destructive tab */
2942 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2943 scp->cursor_pos += (8 - scp->xpos % 8u);
2944 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2945 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) {
2946 scp->xpos = 0;
2947 scp->ypos++;
2948 }
2949 break;
2950
2951 case 0x0a: /* newline, same pos */
2952 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2953 scp->cursor_pos += scp->xsize;
2954 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2955 scp->ypos++;
2956 break;
2957
2958 case 0x0c: /* form feed, clears screen */
2959 sc_clear_screen(scp);
2960 break;
2961
2962 case 0x0d: /* return, return to pos 0 */
2963 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2964 scp->cursor_pos -= scp->xpos;
2965 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2966 scp->xpos = 0;
2967 break;
2968
2969 case 0x1b: /* start escape sequence */
2970 scp->term.esc = 1;
2971 scp->term.num_param = 0;
2972 break;
2973 }
2974 ptr++; len--;
2975 }
2976 /* do we have to scroll ?? */
2977 if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) {
2978 remove_cutmarking(scp);
2979 if (scp->history) {
2980 bcopy(scp->scr_buf, scp->history_head,
2981 scp->xsize * sizeof(u_short));
2982 scp->history_head += scp->xsize;
2983 if (scp->history_head + scp->xsize >
2984 scp->history + scp->history_size)
2985 scp->history_head = scp->history;
2986 }
2987 bcopy(scp->scr_buf + scp->xsize, scp->scr_buf,
2988 scp->xsize * (scp->ysize - 1) * sizeof(u_short));
2989 fillw(scp->term.cur_color | scr_map[0x20],
2990 scp->scr_buf + scp->xsize * (scp->ysize - 1),
2991 scp->xsize);
2992 scp->cursor_pos -= scp->xsize;
2993 scp->ypos--;
2994 mark_all(scp);
2995 }
2996 if (len)
2997 goto outloop;
2998 write_in_progress--;
2999 if (delayed_next_scr)
3000 switch_scr(scp, delayed_next_scr - 1);
3001}
3002
3003static void
3004scinit(void)
3005{
3006 int col;
3007 int row;
3008 u_int i;
3009
3010 if (init_done != COLD)
3011 return;
3012 init_done = WARM;
3013
3014 /* extract the hardware cursor location and move it out of the way */
3015 (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row);
3016 (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1);
3017
3018 /* set up the first console */
3019 current_default = &user_default;
3020 console[0] = &main_console;
3021 init_scp(console[0]);
3022 cur_console = console[0];
3023
3024 /* copy screen to temporary buffer */
3025 if (ISTEXTSC(console[0]))
2617 break;
2618
2619 case 'Z': /* move n tabs backwards */
2620 n = scp->term.param[0]; if (n < 1) n = 1;
2621 if ((i = scp->xpos & 0xf8) == scp->xpos)
2622 i -= 8*n;
2623 else
2624 i -= 8*(n-1);
2625 if (i < 0)
2626 i = 0;
2627 move_crsr(scp, i, scp->ypos);
2628 break;
2629
2630 case '`': /* move cursor to column n */
2631 n = scp->term.param[0]; if (n < 1) n = 1;
2632 move_crsr(scp, n - 1, scp->ypos);
2633 break;
2634
2635 case 'a': /* move cursor n columns to the right */
2636 n = scp->term.param[0]; if (n < 1) n = 1;
2637 move_crsr(scp, scp->xpos + n, scp->ypos);
2638 break;
2639
2640 case 'd': /* move cursor to row n */
2641 n = scp->term.param[0]; if (n < 1) n = 1;
2642 move_crsr(scp, scp->xpos, n - 1);
2643 break;
2644
2645 case 'e': /* move cursor n rows down */
2646 n = scp->term.param[0]; if (n < 1) n = 1;
2647 move_crsr(scp, scp->xpos, scp->ypos + n);
2648 break;
2649
2650 case 'm': /* change attribute */
2651 if (scp->term.num_param == 0) {
2652 scp->term.attr_mask = NORMAL_ATTR;
2653 scp->term.cur_attr =
2654 scp->term.cur_color = scp->term.std_color;
2655 break;
2656 }
2657 for (i = 0; i < scp->term.num_param; i++) {
2658 switch (n = scp->term.param[i]) {
2659 case 0: /* back to normal */
2660 scp->term.attr_mask = NORMAL_ATTR;
2661 scp->term.cur_attr =
2662 scp->term.cur_color = scp->term.std_color;
2663 break;
2664 case 1: /* bold */
2665 scp->term.attr_mask |= BOLD_ATTR;
2666 scp->term.cur_attr = mask2attr(&scp->term);
2667 break;
2668 case 4: /* underline */
2669 scp->term.attr_mask |= UNDERLINE_ATTR;
2670 scp->term.cur_attr = mask2attr(&scp->term);
2671 break;
2672 case 5: /* blink */
2673 scp->term.attr_mask |= BLINK_ATTR;
2674 scp->term.cur_attr = mask2attr(&scp->term);
2675 break;
2676 case 7: /* reverse video */
2677 scp->term.attr_mask |= REVERSE_ATTR;
2678 scp->term.cur_attr = mask2attr(&scp->term);
2679 break;
2680 case 30: case 31: /* set fg color */
2681 case 32: case 33: case 34:
2682 case 35: case 36: case 37:
2683 scp->term.attr_mask |= FOREGROUND_CHANGED;
2684 scp->term.cur_color =
2685 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8);
2686 scp->term.cur_attr = mask2attr(&scp->term);
2687 break;
2688 case 40: case 41: /* set bg color */
2689 case 42: case 43: case 44:
2690 case 45: case 46: case 47:
2691 scp->term.attr_mask |= BACKGROUND_CHANGED;
2692 scp->term.cur_color =
2693 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12);
2694 scp->term.cur_attr = mask2attr(&scp->term);
2695 break;
2696 }
2697 }
2698 break;
2699
2700 case 's': /* Save cursor position */
2701 scp->saved_xpos = scp->xpos;
2702 scp->saved_ypos = scp->ypos;
2703 break;
2704
2705 case 'u': /* Restore saved cursor position */
2706 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0)
2707 move_crsr(scp, scp->saved_xpos, scp->saved_ypos);
2708 break;
2709
2710 case 'x':
2711 if (scp->term.num_param == 0)
2712 n = 0;
2713 else
2714 n = scp->term.param[0];
2715 switch (n) {
2716 case 0: /* reset attributes */
2717 scp->term.attr_mask = NORMAL_ATTR;
2718 scp->term.cur_attr =
2719 scp->term.cur_color = scp->term.std_color =
2720 current_default->std_color;
2721 scp->term.rev_color = current_default->rev_color;
2722 break;
2723 case 1: /* set ansi background */
2724 scp->term.attr_mask &= ~BACKGROUND_CHANGED;
2725 scp->term.cur_color = scp->term.std_color =
2726 (scp->term.std_color & 0x0F00) |
2727 (ansi_col[(scp->term.param[1])&0x0F]<<12);
2728 scp->term.cur_attr = mask2attr(&scp->term);
2729 break;
2730 case 2: /* set ansi foreground */
2731 scp->term.attr_mask &= ~FOREGROUND_CHANGED;
2732 scp->term.cur_color = scp->term.std_color =
2733 (scp->term.std_color & 0xF000) |
2734 (ansi_col[(scp->term.param[1])&0x0F]<<8);
2735 scp->term.cur_attr = mask2attr(&scp->term);
2736 break;
2737 case 3: /* set ansi attribute directly */
2738 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED);
2739 scp->term.cur_color = scp->term.std_color =
2740 (scp->term.param[1]&0xFF)<<8;
2741 scp->term.cur_attr = mask2attr(&scp->term);
2742 break;
2743 case 5: /* set ansi reverse video background */
2744 scp->term.rev_color =
2745 (scp->term.rev_color & 0x0F00) |
2746 (ansi_col[(scp->term.param[1])&0x0F]<<12);
2747 scp->term.cur_attr = mask2attr(&scp->term);
2748 break;
2749 case 6: /* set ansi reverse video foreground */
2750 scp->term.rev_color =
2751 (scp->term.rev_color & 0xF000) |
2752 (ansi_col[(scp->term.param[1])&0x0F]<<8);
2753 scp->term.cur_attr = mask2attr(&scp->term);
2754 break;
2755 case 7: /* set ansi reverse video directly */
2756 scp->term.rev_color =
2757 (scp->term.param[1]&0xFF)<<8;
2758 scp->term.cur_attr = mask2attr(&scp->term);
2759 break;
2760 }
2761 break;
2762
2763 case 'z': /* switch to (virtual) console n */
2764 if (scp->term.num_param == 1)
2765 switch_scr(scp, scp->term.param[0]);
2766 break;
2767 }
2768 }
2769 else if (scp->term.esc == 3) { /* seen ESC [0-9]+ = */
2770 if (c >= '0' && c <= '9') {
2771 if (scp->term.num_param < MAX_ESC_PAR) {
2772 if (scp->term.last_param != scp->term.num_param) {
2773 scp->term.last_param = scp->term.num_param;
2774 scp->term.param[scp->term.num_param] = 0;
2775 }
2776 else
2777 scp->term.param[scp->term.num_param] *= 10;
2778 scp->term.param[scp->term.num_param] += c - '0';
2779 return;
2780 }
2781 }
2782 scp->term.num_param = scp->term.last_param + 1;
2783 switch (c) {
2784
2785 case ';':
2786 if (scp->term.num_param < MAX_ESC_PAR)
2787 return;
2788 break;
2789
2790 case 'A': /* set display border color */
2791 if (scp->term.num_param == 1) {
2792 scp->border=scp->term.param[0] & 0xff;
2793 if (scp == cur_console)
2794 set_border(cur_console, scp->border);
2795 }
2796 break;
2797
2798 case 'B': /* set bell pitch and duration */
2799 if (scp->term.num_param == 2) {
2800 scp->bell_pitch = scp->term.param[0];
2801 scp->bell_duration = scp->term.param[1];
2802 }
2803 break;
2804
2805 case 'C': /* set cursor type & shape */
2806 if (scp->term.num_param == 1) {
2807 if (scp->term.param[0] & 0x01)
2808 flags |= BLINK_CURSOR;
2809 else
2810 flags &= ~BLINK_CURSOR;
2811 if ((scp->term.param[0] & 0x02)
2812 && ISFONTAVAIL(get_adapter(scp)->va_flags))
2813 flags |= CHAR_CURSOR;
2814 else
2815 flags &= ~CHAR_CURSOR;
2816 }
2817 else if (scp->term.num_param == 2) {
2818 scp->cursor_start = scp->term.param[0] & 0x1F;
2819 scp->cursor_end = scp->term.param[1] & 0x1F;
2820 }
2821 /*
2822 * The cursor shape is global property; all virtual consoles
2823 * are affected. Update the cursor in the current console...
2824 */
2825 if (!ISGRAPHSC(cur_console)) {
2826 remove_cursor_image(cur_console);
2827 if (flags & CHAR_CURSOR)
2828 set_destructive_cursor(cur_console);
2829 draw_cursor_image(cur_console);
2830 }
2831 break;
2832
2833 case 'F': /* set ansi foreground */
2834 if (scp->term.num_param == 1) {
2835 scp->term.attr_mask &= ~FOREGROUND_CHANGED;
2836 scp->term.cur_color = scp->term.std_color =
2837 (scp->term.std_color & 0xF000)
2838 | ((scp->term.param[0] & 0x0F) << 8);
2839 scp->term.cur_attr = mask2attr(&scp->term);
2840 }
2841 break;
2842
2843 case 'G': /* set ansi background */
2844 if (scp->term.num_param == 1) {
2845 scp->term.attr_mask &= ~BACKGROUND_CHANGED;
2846 scp->term.cur_color = scp->term.std_color =
2847 (scp->term.std_color & 0x0F00)
2848 | ((scp->term.param[0] & 0x0F) << 12);
2849 scp->term.cur_attr = mask2attr(&scp->term);
2850 }
2851 break;
2852
2853 case 'H': /* set ansi reverse video foreground */
2854 if (scp->term.num_param == 1) {
2855 scp->term.rev_color =
2856 (scp->term.rev_color & 0xF000)
2857 | ((scp->term.param[0] & 0x0F) << 8);
2858 scp->term.cur_attr = mask2attr(&scp->term);
2859 }
2860 break;
2861
2862 case 'I': /* set ansi reverse video background */
2863 if (scp->term.num_param == 1) {
2864 scp->term.rev_color =
2865 (scp->term.rev_color & 0x0F00)
2866 | ((scp->term.param[0] & 0x0F) << 12);
2867 scp->term.cur_attr = mask2attr(&scp->term);
2868 }
2869 break;
2870 }
2871 }
2872#if notyet
2873 else if (scp->term.esc == 4) { /* seen ESC Q */
2874 /* to be filled */
2875 }
2876#endif
2877 else if (scp->term.esc == 5) { /* seen ESC ( */
2878 switch (c) {
2879 case 'B': /* iso-2022: desginate ASCII into G0 */
2880 break;
2881 /* other items to be filled */
2882 default:
2883 break;
2884 }
2885 }
2886 scp->term.esc = 0;
2887}
2888
2889static void
2890ansi_put(scr_stat *scp, u_char *buf, int len)
2891{
2892 u_char *ptr = buf;
2893
2894 /* make screensaver happy */
2895 if (!sticky_splash && scp == cur_console)
2896 run_scrn_saver = FALSE;
2897
2898 write_in_progress++;
2899outloop:
2900 if (scp->term.esc) {
2901 scan_esc(scp, *ptr++);
2902 len--;
2903 }
2904 else if (PRINTABLE(*ptr)) { /* Print only printables */
2905 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos);
2906 u_short cur_attr = scp->term.cur_attr;
2907 u_short *cursor_pos = scp->cursor_pos;
2908 do {
2909 /*
2910 * gcc-2.6.3 generates poor (un)sign extension code. Casting the
2911 * pointers in the following to volatile should have no effect,
2912 * but in fact speeds up this inner loop from 26 to 18 cycles
2913 * (+ cache misses) on i486's.
2914 */
2915#define UCVP(ucp) ((u_char volatile *)(ucp))
2916 *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr;
2917 ptr++;
2918 cnt--;
2919 } while (cnt && PRINTABLE(*ptr));
2920 len -= (cursor_pos - scp->cursor_pos);
2921 scp->xpos += (cursor_pos - scp->cursor_pos);
2922 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2923 mark_for_update(scp, cursor_pos - scp->scr_buf);
2924 scp->cursor_pos = cursor_pos;
2925 if (scp->xpos >= scp->xsize) {
2926 scp->xpos = 0;
2927 scp->ypos++;
2928 }
2929 }
2930 else {
2931 switch(*ptr) {
2932 case 0x07:
2933 do_bell(scp, scp->bell_pitch, scp->bell_duration);
2934 break;
2935
2936 case 0x08: /* non-destructive backspace */
2937 if (scp->cursor_pos > scp->scr_buf) {
2938 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2939 scp->cursor_pos--;
2940 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2941 if (scp->xpos > 0)
2942 scp->xpos--;
2943 else {
2944 scp->xpos += scp->xsize - 1;
2945 scp->ypos--;
2946 }
2947 }
2948 break;
2949
2950 case 0x09: /* non-destructive tab */
2951 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2952 scp->cursor_pos += (8 - scp->xpos % 8u);
2953 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2954 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) {
2955 scp->xpos = 0;
2956 scp->ypos++;
2957 }
2958 break;
2959
2960 case 0x0a: /* newline, same pos */
2961 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2962 scp->cursor_pos += scp->xsize;
2963 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2964 scp->ypos++;
2965 break;
2966
2967 case 0x0c: /* form feed, clears screen */
2968 sc_clear_screen(scp);
2969 break;
2970
2971 case 0x0d: /* return, return to pos 0 */
2972 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2973 scp->cursor_pos -= scp->xpos;
2974 mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2975 scp->xpos = 0;
2976 break;
2977
2978 case 0x1b: /* start escape sequence */
2979 scp->term.esc = 1;
2980 scp->term.num_param = 0;
2981 break;
2982 }
2983 ptr++; len--;
2984 }
2985 /* do we have to scroll ?? */
2986 if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) {
2987 remove_cutmarking(scp);
2988 if (scp->history) {
2989 bcopy(scp->scr_buf, scp->history_head,
2990 scp->xsize * sizeof(u_short));
2991 scp->history_head += scp->xsize;
2992 if (scp->history_head + scp->xsize >
2993 scp->history + scp->history_size)
2994 scp->history_head = scp->history;
2995 }
2996 bcopy(scp->scr_buf + scp->xsize, scp->scr_buf,
2997 scp->xsize * (scp->ysize - 1) * sizeof(u_short));
2998 fillw(scp->term.cur_color | scr_map[0x20],
2999 scp->scr_buf + scp->xsize * (scp->ysize - 1),
3000 scp->xsize);
3001 scp->cursor_pos -= scp->xsize;
3002 scp->ypos--;
3003 mark_all(scp);
3004 }
3005 if (len)
3006 goto outloop;
3007 write_in_progress--;
3008 if (delayed_next_scr)
3009 switch_scr(scp, delayed_next_scr - 1);
3010}
3011
3012static void
3013scinit(void)
3014{
3015 int col;
3016 int row;
3017 u_int i;
3018
3019 if (init_done != COLD)
3020 return;
3021 init_done = WARM;
3022
3023 /* extract the hardware cursor location and move it out of the way */
3024 (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row);
3025 (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1);
3026
3027 /* set up the first console */
3028 current_default = &user_default;
3029 console[0] = &main_console;
3030 init_scp(console[0]);
3031 cur_console = console[0];
3032
3033 /* copy screen to temporary buffer */
3034 if (ISTEXTSC(console[0]))
3026 generic_bcopy(Crtat, sc_buffer,
3027 console[0]->xsize * console[0]->ysize * sizeof(u_short));
3035 generic_bcopy((ushort *)(get_adapter(console[0])->va_window), sc_buffer,
3036 console[0]->xsize * console[0]->ysize * sizeof(u_short));
3028
3029 console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos
3030 = sc_buffer;
3031 if (col >= console[0]->xsize)
3032 col = 0;
3033 if (row >= console[0]->ysize)
3034 row = console[0]->ysize - 1;
3035 console[0]->xpos = col;
3036 console[0]->ypos = row;
3037 console[0]->cursor_pos = console[0]->cursor_oldpos =
3038 sc_buffer + row*console[0]->xsize + col;
3039 console[0]->cursor_saveunder = *console[0]->cursor_pos;
3040 for (i=1; i<MAXCONS; i++)
3041 console[i] = NULL;
3042 kernel_console.esc = 0;
3043 kernel_console.attr_mask = NORMAL_ATTR;
3044 kernel_console.cur_attr =
3045 kernel_console.cur_color = kernel_console.std_color =
3046 kernel_default.std_color;
3047 kernel_console.rev_color = kernel_default.rev_color;
3048
3049 /* initialize mapscrn arrays to a one to one map */
3050 for (i=0; i<sizeof(scr_map); i++) {
3051 scr_map[i] = scr_rmap[i] = i;
3052 }
3053
3054 /* Save font and palette */
3055 if (ISFONTAVAIL(get_adapter(cur_console)->va_flags)) {
3056 if (fonts_loaded & FONT_16) {
3057 copy_font(cur_console, LOAD, 16, font_16);
3058 } else {
3059 copy_font(cur_console, SAVE, 16, font_16);
3060 fonts_loaded = FONT_16;
3061 set_destructive_cursor(cur_console);
3062 }
3063 /*
3064 * FONT KLUDGE
3065 * Always use the font page #0. XXX
3066 */
3067 (*biosvidsw.show_font)(cur_console->adp, 0);
3068 }
3069 save_palette(cur_console, palette);
3070
3071#ifdef SC_SPLASH_SCREEN
3072 /* put up the splash. */
3073 scsplash_init(cur_console);
3074#endif
3075}
3076
3077static void
3078scshutdown(int howto, void *arg)
3079{
3080 scsplash_stick(FALSE);
3081 run_scrn_saver = FALSE;
3082 if (!cold && cur_console->smode.mode == VT_AUTO
3083 && console[0]->smode.mode == VT_AUTO)
3084 switch_scr(cur_console, 0);
3085 shutdown_in_progress = TRUE;
3086}
3087
3088int
3089sc_clean_up(scr_stat *scp)
3090{
3091 int error;
3092
3093 if ((error = wait_scrn_saver_stop()))
3094 return error;
3095 scp->status &= ~MOUSE_VISIBLE;
3096 remove_cutmarking(scp);
3097 return 0;
3098}
3099
3100void
3101sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear)
3102{
3103 if (scp->scr_buf)
3104 free(scp->scr_buf, M_DEVBUF);
3105 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short),
3106 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
3107
3108 if (clear) {
3109 /* clear the screen and move the text cursor to the top-left position */
3110 sc_clear_screen(scp);
3111 } else {
3112 /* retain the current cursor position, but adjust pointers */
3113 move_crsr(scp, scp->xpos, scp->ypos);
3114 scp->cursor_oldpos = scp->cursor_pos;
3115 }
3116
3117 /* move the mouse cursor at the center of the screen */
3118 sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2);
3119}
3120
3121void
3122sc_alloc_cut_buffer(scr_stat *scp, int wait)
3123{
3124 if ((cut_buffer == NULL)
3125 || (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
3126 if (cut_buffer != NULL)
3127 free(cut_buffer, M_DEVBUF);
3128 cut_buffer_size = scp->xsize * scp->ysize + 1;
3129 cut_buffer = (u_char *)malloc(cut_buffer_size,
3130 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
3131 if (cut_buffer != NULL)
3132 cut_buffer[0] = '\0';
3133 }
3134}
3135
3136void
3137sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait)
3138{
3139 u_short *usp;
3140
3141 if (lines < scp->ysize)
3142 lines = scp->ysize;
3143
3144 usp = scp->history;
3145 scp->history = NULL;
3146 if (usp != NULL) {
3147 free(usp, M_DEVBUF);
3148 if (extra > 0)
3149 extra_history_size += extra;
3150 }
3151
3152 scp->history_size = lines * scp->xsize;
3153 if (lines > imax(sc_history_size, scp->ysize))
3154 extra_history_size -= lines - imax(sc_history_size, scp->ysize);
3155 usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
3156 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
3157 if (usp != NULL)
3158 bzero(usp, scp->history_size * sizeof(u_short));
3159 scp->history_head = scp->history_pos = usp;
3160 scp->history = usp;
3161}
3162
3163static scr_stat
3164*alloc_scp()
3165{
3166 scr_stat *scp;
3167
3168 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK);
3169 init_scp(scp);
3170 sc_alloc_scr_buffer(scp, TRUE, TRUE);
3171 if (ISMOUSEAVAIL(get_adapter(scp)->va_flags))
3172 sc_alloc_cut_buffer(scp, TRUE);
3173 sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE);
3174/* SOS
3175 if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE)
3176 set_mode(scp);
3177*/
3178 sc_clear_screen(scp);
3179 scp->cursor_saveunder = *scp->cursor_pos;
3180 return scp;
3181}
3182
3183static void
3184init_scp(scr_stat *scp)
3185{
3186 video_info_t info;
3187
3188 scp->adp = V_ADP_PRIMARY;
3189 (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info);
3190
3191 scp->status = 0;
3192 scp->mode = scp->initial_mode = initial_video_mode;
3193 scp->scr_buf = NULL;
3194 if (info.vi_flags & V_INFO_GRAPHICS) {
3195 scp->status |= GRAPHICS_MODE;
3196 scp->xpixel = info.vi_width;
3197 scp->ypixel = info.vi_height;
3198 scp->xsize = info.vi_width/8;
3199 scp->ysize = info.vi_height/info.vi_cheight;
3200 scp->font_size = FONT_NONE;
3201 } else {
3202 scp->xsize = info.vi_width;
3203 scp->ysize = info.vi_height;
3204 scp->xpixel = scp->xsize*8;
3205 scp->ypixel = scp->ysize*info.vi_cheight;
3206 scp->font_size = info.vi_cheight;
3207 }
3208 scp->xoff = scp->yoff = 0;
3209 scp->xpos = scp->ypos = 0;
3210 scp->saved_xpos = scp->saved_ypos = -1;
3211 scp->start = scp->xsize * scp->ysize;
3212 scp->end = 0;
3213 scp->term.esc = 0;
3214 scp->term.attr_mask = NORMAL_ATTR;
3215 scp->term.cur_attr =
3216 scp->term.cur_color = scp->term.std_color =
3217 current_default->std_color;
3218 scp->term.rev_color = current_default->rev_color;
3219 scp->border = BG_BLACK;
3220 scp->cursor_start = *(u_int8_t *)pa_to_va(0x461);
3221 scp->cursor_end = *(u_int8_t *)pa_to_va(0x460);
3222 scp->mouse_xpos = scp->xsize*8/2;
3223 scp->mouse_ypos = scp->ysize*scp->font_size/2;
3224 scp->mouse_cut_start = scp->mouse_cut_end = NULL;
3225 scp->mouse_signal = 0;
3226 scp->mouse_pid = 0;
3227 scp->mouse_proc = NULL;
3228 scp->bell_pitch = BELL_PITCH;
3229 scp->bell_duration = BELL_DURATION;
3230 scp->status |= (*(u_int8_t *)pa_to_va(0x417) & 0x20) ? NLKED : 0;
3231 scp->status |= CURSOR_ENABLED;
3232 scp->pid = 0;
3233 scp->proc = NULL;
3234 scp->smode.mode = VT_AUTO;
3235 scp->history_head = scp->history_pos = scp->history = NULL;
3236 scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize;
3237}
3238
3239static u_char
3240*get_fstr(u_int c, u_int *len)
3241{
3242 u_int i;
3243
3244 if (!(c & FKEY))
3245 return(NULL);
3246 i = (c & 0xFF) - F_FN;
3247 if (i > n_fkey_tab)
3248 return(NULL);
3249 *len = fkey_tab[i].len;
3250 return(fkey_tab[i].str);
3251}
3252
3253static void
3254history_to_screen(scr_stat *scp)
3255{
3256 int i;
3257
3258 for (i=0; i<scp->ysize; i++)
3259 bcopy(scp->history + (((scp->history_pos - scp->history) +
3260 scp->history_size-((i+1)*scp->xsize))%scp->history_size),
3261 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)),
3262 scp->xsize * sizeof(u_short));
3263 mark_all(scp);
3264}
3265
3266static int
3267history_up_line(scr_stat *scp)
3268{
3269 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) !=
3270 scp->history_head) {
3271 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize);
3272 history_to_screen(scp);
3273 return 0;
3274 }
3275 else
3276 return -1;
3277}
3278
3279static int
3280history_down_line(scr_stat *scp)
3281{
3282 if (scp->history_pos != scp->history_head) {
3283 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize);
3284 history_to_screen(scp);
3285 return 0;
3286 }
3287 else
3288 return -1;
3289}
3290
3291/*
3292 * scgetc(flags) - get character from keyboard.
3293 * If flags & SCGETC_CN, then avoid harmful side effects.
3294 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else
3295 * return NOKEY if there is nothing there.
3296 */
3297static u_int
3298scgetc(u_int flags)
3299{
3300 struct key_t *key;
3301 u_char scancode, keycode;
3302 u_int state, action;
3303 int c;
3304 static u_char esc_flag = 0, compose = 0;
3305 static u_int chr = 0;
3306
3307next_code:
3308 /* first see if there is something in the keyboard port */
3309 if (flags & SCGETC_NONBLOCK) {
3310 c = read_kbd_data_no_wait(sc_kbdc);
3311 if (c == -1)
3312 return(NOKEY);
3313 } else {
3314 do {
3315 c = read_kbd_data(sc_kbdc);
3316 } while(c == -1);
3317 }
3318 scancode = (u_char)c;
3319
3320 /* make screensaver happy */
3321 if (!(scancode & 0x80)) {
3322 scsplash_stick(FALSE);
3323 run_scrn_saver = FALSE;
3324 }
3325
3326 if (!(flags & SCGETC_CN)) {
3327 /* do the /dev/random device a favour */
3328 add_keyboard_randomness(scancode);
3329
3330 if (cur_console->status & KBD_RAW_MODE)
3331 return scancode;
3332 }
3333
3334 keycode = scancode & 0x7F;
3335 switch (esc_flag) {
3336 case 0x00: /* normal scancode */
3337 switch(scancode) {
3338 case 0xB8: /* left alt (compose key) */
3339 if (compose) {
3340 compose = 0;
3341 if (chr > 255) {
3342 do_bell(cur_console,
3343 BELL_PITCH, BELL_DURATION);
3344 chr = 0;
3345 }
3346 }
3347 break;
3348 case 0x38:
3349 if (!compose) {
3350 compose = 1;
3351 chr = 0;
3352 }
3353 break;
3354 case 0xE0:
3355 case 0xE1:
3356 esc_flag = scancode;
3357 goto next_code;
3358 }
3359 break;
3360 case 0xE0: /* 0xE0 prefix */
3361 esc_flag = 0;
3362 switch (keycode) {
3363 case 0x1C: /* right enter key */
3364 keycode = 0x59;
3365 break;
3366 case 0x1D: /* right ctrl key */
3367 keycode = 0x5A;
3368 break;
3369 case 0x35: /* keypad divide key */
3370 keycode = 0x5B;
3371 break;
3372 case 0x37: /* print scrn key */
3373 keycode = 0x5C;
3374 break;
3375 case 0x38: /* right alt key (alt gr) */
3376 keycode = 0x5D;
3377 break;
3378 case 0x47: /* grey home key */
3379 keycode = 0x5E;
3380 break;
3381 case 0x48: /* grey up arrow key */
3382 keycode = 0x5F;
3383 break;
3384 case 0x49: /* grey page up key */
3385 keycode = 0x60;
3386 break;
3387 case 0x4B: /* grey left arrow key */
3388 keycode = 0x61;
3389 break;
3390 case 0x4D: /* grey right arrow key */
3391 keycode = 0x62;
3392 break;
3393 case 0x4F: /* grey end key */
3394 keycode = 0x63;
3395 break;
3396 case 0x50: /* grey down arrow key */
3397 keycode = 0x64;
3398 break;
3399 case 0x51: /* grey page down key */
3400 keycode = 0x65;
3401 break;
3402 case 0x52: /* grey insert key */
3403 keycode = 0x66;
3404 break;
3405 case 0x53: /* grey delete key */
3406 keycode = 0x67;
3407 break;
3408
3409 /* the following 3 are only used on the MS "Natural" keyboard */
3410 case 0x5b: /* left Window key */
3411 keycode = 0x69;
3412 break;
3413 case 0x5c: /* right Window key */
3414 keycode = 0x6a;
3415 break;
3416 case 0x5d: /* menu key */
3417 keycode = 0x6b;
3418 break;
3419 default: /* ignore everything else */
3420 goto next_code;
3421 }
3422 break;
3423 case 0xE1: /* 0xE1 prefix */
3424 esc_flag = 0;
3425 if (keycode == 0x1D)
3426 esc_flag = 0x1D;
3427 goto next_code;
3428 /* NOT REACHED */
3429 case 0x1D: /* pause / break */
3430 esc_flag = 0;
3431 if (keycode != 0x45)
3432 goto next_code;
3433 keycode = 0x68;
3434 break;
3435 }
3436
3437 if (!(flags & SCGETC_CN) && (cur_console->status & KBD_CODE_MODE))
3438 return (keycode | (scancode & 0x80));
3439
3440 /* if scroll-lock pressed allow history browsing */
3441 if (cur_console->history && cur_console->status & SLKED) {
3442 int i;
3443
3444 cur_console->status &= ~CURSOR_ENABLED;
3445 if (!(cur_console->status & BUFFER_SAVED)) {
3446 cur_console->status |= BUFFER_SAVED;
3447 cur_console->history_save = cur_console->history_head;
3448
3449 /* copy screen into top of history buffer */
3450 for (i=0; i<cur_console->ysize; i++) {
3451 bcopy(cur_console->scr_buf + (cur_console->xsize * i),
3452 cur_console->history_head,
3453 cur_console->xsize * sizeof(u_short));
3454 cur_console->history_head += cur_console->xsize;
3455 if (cur_console->history_head + cur_console->xsize >
3456 cur_console->history + cur_console->history_size)
3457 cur_console->history_head=cur_console->history;
3458 }
3459 cur_console->history_pos = cur_console->history_head;
3460 history_to_screen(cur_console);
3461 }
3462 switch (scancode) {
3463 case 0x47: /* home key */
3464 cur_console->history_pos = cur_console->history_head;
3465 history_to_screen(cur_console);
3466 goto next_code;
3467
3468 case 0x4F: /* end key */
3469 cur_console->history_pos =
3470 WRAPHIST(cur_console, cur_console->history_head,
3471 cur_console->xsize*cur_console->ysize);
3472 history_to_screen(cur_console);
3473 goto next_code;
3474
3475 case 0x48: /* up arrow key */
3476 if (history_up_line(cur_console))
3477 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3478 goto next_code;
3479
3480 case 0x50: /* down arrow key */
3481 if (history_down_line(cur_console))
3482 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3483 goto next_code;
3484
3485 case 0x49: /* page up key */
3486 for (i=0; i<cur_console->ysize; i++)
3487 if (history_up_line(cur_console)) {
3488 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3489 break;
3490 }
3491 goto next_code;
3492
3493 case 0x51: /* page down key */
3494 for (i=0; i<cur_console->ysize; i++)
3495 if (history_down_line(cur_console)) {
3496 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3497 break;
3498 }
3499 goto next_code;
3500 }
3501 }
3502
3503 if (compose) {
3504 switch (scancode) {
3505 /* key pressed process it */
3506 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
3507 chr = (scancode - 0x40) + chr*10;
3508 goto next_code;
3509 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
3510 chr = (scancode - 0x47) + chr*10;
3511 goto next_code;
3512 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
3513 chr = (scancode - 0x4E) + chr*10;
3514 goto next_code;
3515 case 0x52: /* keypad 0 */
3516 chr *= 10;
3517 goto next_code;
3518
3519 /* key release, no interest here */
3520 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
3521 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
3522 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
3523 case 0xD2: /* keypad 0 */
3524 goto next_code;
3525
3526 case 0x38: /* left alt key */
3527 break;
3528 default:
3529 if (chr) {
3530 compose = chr = 0;
3531 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3532 goto next_code;
3533 }
3534 break;
3535 }
3536 }
3537
3538 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0));
3539 if ((!agrs && (cur_console->status & ALKED))
3540 || (agrs && !(cur_console->status & ALKED)))
3541 keycode += ALTGR_OFFSET;
3542 key = &key_map.key[keycode];
3543 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED))
3544 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) )
3545 state ^= 1;
3546
3547 /* Check for make/break */
3548 action = key->map[state];
3549 if (scancode & 0x80) { /* key released */
3550 if (key->spcl & (0x80>>state)) {
3551 switch (action) {
3552 case LSH:
3553 shfts &= ~1;
3554 break;
3555 case RSH:
3556 shfts &= ~2;
3557 break;
3558 case LCTR:
3559 ctls &= ~1;
3560 break;
3561 case RCTR:
3562 ctls &= ~2;
3563 break;
3564 case LALT:
3565 alts &= ~1;
3566 break;
3567 case RALT:
3568 alts &= ~2;
3569 break;
3570 case NLK:
3571 nlkcnt = 0;
3572 break;
3573 case CLK:
3574 clkcnt = 0;
3575 break;
3576 case SLK:
3577 slkcnt = 0;
3578 break;
3579 case ASH:
3580 agrs = 0;
3581 break;
3582 case ALK:
3583 alkcnt = 0;
3584 break;
3585 case META:
3586 metas = 0;
3587 break;
3588 }
3589 }
3590 if (chr && !compose) {
3591 action = chr;
3592 chr = 0;
3593 return(action);
3594 }
3595 } else {
3596 /* key pressed */
3597 if (key->spcl & (0x80>>state)) {
3598 switch (action) {
3599 /* LOCKING KEYS */
3600 case NLK:
3601 if (!nlkcnt) {
3602 nlkcnt++;
3603 if (cur_console->status & NLKED)
3604 cur_console->status &= ~NLKED;
3605 else
3606 cur_console->status |= NLKED;
3607 update_leds(cur_console->status);
3608 }
3609 break;
3610 case CLK:
3611 if (!clkcnt) {
3612 clkcnt++;
3613 if (cur_console->status & CLKED)
3614 cur_console->status &= ~CLKED;
3615 else
3616 cur_console->status |= CLKED;
3617 update_leds(cur_console->status);
3618 }
3619 break;
3620 case SLK:
3621 if (!slkcnt) {
3622 slkcnt++;
3623 if (cur_console->status & SLKED) {
3624 cur_console->status &= ~SLKED;
3625 if (cur_console->status & BUFFER_SAVED){
3626 int i;
3627 u_short *ptr = cur_console->history_save;
3628
3629 for (i=0; i<cur_console->ysize; i++) {
3630 bcopy(ptr,
3631 cur_console->scr_buf +
3632 (cur_console->xsize*i),
3633 cur_console->xsize * sizeof(u_short));
3634 ptr += cur_console->xsize;
3635 if (ptr + cur_console->xsize >
3636 cur_console->history +
3637 cur_console->history_size)
3638 ptr = cur_console->history;
3639 }
3640 cur_console->status &= ~BUFFER_SAVED;
3641 cur_console->history_head=cur_console->history_save;
3642 cur_console->status |= CURSOR_ENABLED;
3643 mark_all(cur_console);
3644 }
3645 scstart(VIRTUAL_TTY(get_scr_num()));
3646 }
3647 else
3648 cur_console->status |= SLKED;
3649 update_leds(cur_console->status);
3650 }
3651 break;
3652 case ALK:
3653 if (!alkcnt) {
3654 alkcnt++;
3655 if (cur_console->status & ALKED)
3656 cur_console->status &= ~ALKED;
3657 else
3658 cur_console->status |= ALKED;
3659 update_leds(cur_console->status);
3660 }
3661 break;
3662
3663 /* NON-LOCKING KEYS */
3664 case NOP:
3665 break;
3666 case SPSC:
3667 /* force activatation/deactivation of the screen saver */
3668 accents = 0;
3669 if (scrn_blanked <= 0) {
3670 run_scrn_saver = TRUE;
3671 scrn_time_stamp -= scrn_blank_time;
3672 }
3673#ifdef SC_SPLASH_SCREEN
3674 if (cold) {
3675 /*
3676 * While devices are being probed, the screen saver need
3677 * to be invoked explictly. XXX
3678 */
3679 if (scrn_blanked > 0) {
3680 scsplash_stick(FALSE);
3681 stop_scrn_saver(current_saver);
3682 } else {
3683 if (!ISGRAPHSC(cur_console)) {
3684 scsplash_stick(TRUE);
3685 scrn_saver(current_saver, TRUE);
3686 }
3687 }
3688 }
3689#endif
3690 break;
3691 case RBT:
3692#ifndef SC_DISABLE_REBOOT
3693 accents = 0;
3694 shutdown_nice();
3695#endif
3696 break;
3697 case SUSP:
3698#if NAPM > 0
3699 accents = 0;
3700 apm_suspend(PMST_SUSPEND);
3701#endif
3702 break;
3703
3704 case STBY:
3705#if NAPM > 0
3706 accents = 0;
3707 apm_suspend(PMST_STANDBY);
3708#endif
3709 break;
3710
3711 case DBG:
3712#ifdef DDB /* try to switch to console 0 */
3713 accents = 0;
3714 /*
3715 * TRY to make sure the screen saver is stopped,
3716 * and the screen is updated before switching to
3717 * the vty0.
3718 */
3719 scrn_timer((void *)FALSE);
3720 if (cur_console->smode.mode == VT_AUTO &&
3721 console[0]->smode.mode == VT_AUTO)
3722 switch_scr(cur_console, 0);
3723 Debugger("manual escape to debugger");
3724#else
3725 printf("No debugger in kernel\n");
3726#endif
3727 break;
3728 case LSH:
3729 shfts |= 1;
3730 break;
3731 case RSH:
3732 shfts |= 2;
3733 break;
3734 case LCTR:
3735 ctls |= 1;
3736 break;
3737 case RCTR:
3738 ctls |= 2;
3739 break;
3740 case LALT:
3741 alts |= 1;
3742 break;
3743 case RALT:
3744 alts |= 2;
3745 break;
3746 case ASH:
3747 agrs = 1;
3748 break;
3749 case META:
3750 metas = 1;
3751 break;
3752 case NEXT:
3753 {
3754 int next, this = get_scr_num();
3755 accents = 0;
3756 for (next = this+1; next != this; next = (next+1)%MAXCONS) {
3757 struct tty *tp = VIRTUAL_TTY(next);
3758 if (tp->t_state & TS_ISOPEN) {
3759 switch_scr(cur_console, next);
3760 break;
3761 }
3762 }
3763 }
3764 break;
3765 case BTAB:
3766 accents = 0;
3767 return(BKEY);
3768 default:
3769 if (action >= F_ACC && action <= L_ACC) {
3770 /* turn it into an index */
3771 action -= F_ACC - 1;
3772 if ((action > accent_map.n_accs)
3773 || (accent_map.acc[action - 1].accchar == 0)) {
3774 /*
3775 * The index is out of range or pointing to an
3776 * empty entry.
3777 */
3778 accents = 0;
3779 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3780 }
3781 /*
3782 * If the same accent key has been hit twice,
3783 * produce the accent char itself.
3784 */
3785 if (action == accents) {
3786 action = accent_map.acc[accents - 1].accchar;
3787 accents = 0;
3788 if (metas)
3789 action |= MKEY;
3790 return (action);
3791 }
3792 /* remember the index and wait for the next key stroke */
3793 accents = action;
3794 break;
3795 }
3796 if (accents > 0) {
3797 accents = 0;
3798 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3799 }
3800 if (action >= F_SCR && action <= L_SCR) {
3801 switch_scr(cur_console, action - F_SCR);
3802 break;
3803 }
3804 if (action >= F_FN && action <= L_FN)
3805 action |= FKEY;
3806 return(action);
3807 }
3808 }
3809 else {
3810 if (accents) {
3811 struct acc_t *acc;
3812 int i;
3813
3814 acc = &accent_map.acc[accents - 1];
3815 accents = 0;
3816 /*
3817 * If the accent key is followed by the space key,
3818 * produce the accent char itself.
3819 */
3820 if (action == ' ') {
3821 action = acc->accchar;
3822 if (metas)
3823 action |= MKEY;
3824 return (action);
3825 }
3826 for (i = 0; i < NUM_ACCENTCHARS; ++i) {
3827 if (acc->map[i][0] == 0) /* end of the map entry */
3828 break;
3829 if (acc->map[i][0] == action) {
3830 action = acc->map[i][1];
3831 if (metas)
3832 action |= MKEY;
3833 return (action);
3834 }
3835 }
3836 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3837 goto next_code;
3838 }
3839 if (metas)
3840 action |= MKEY;
3841 return(action);
3842 }
3843 }
3844 goto next_code;
3845}
3846
3847int
3848scmmap(dev_t dev, int offset, int nprot)
3849{
3850 if (offset > 0x20000 - PAGE_SIZE)
3851 return -1;
3852 return i386_btop((VIDEOMEM + offset));
3853}
3854
3855/*
3856 * Calculate hardware attributes word using logical attributes mask and
3857 * hardware colors
3858 */
3859
3860static int
3861mask2attr(struct term_stat *term)
3862{
3863 int attr, mask = term->attr_mask;
3864
3865 if (mask & REVERSE_ATTR) {
3866 attr = ((mask & FOREGROUND_CHANGED) ?
3867 ((term->cur_color & 0xF000) >> 4) :
3868 (term->rev_color & 0x0F00)) |
3869 ((mask & BACKGROUND_CHANGED) ?
3870 ((term->cur_color & 0x0F00) << 4) :
3871 (term->rev_color & 0xF000));
3872 } else
3873 attr = term->cur_color;
3874
3875 /* XXX: underline mapping for Hercules adapter can be better */
3876 if (mask & (BOLD_ATTR | UNDERLINE_ATTR))
3877 attr ^= 0x0800;
3878 if (mask & BLINK_ATTR)
3879 attr ^= 0x8000;
3880
3881 return attr;
3882}
3883
3884static void
3885set_keyboard(int command, int data)
3886{
3887 int s;
3888
3889 if (sc_kbdc == NULL)
3890 return;
3891
3892 /* prevent the timeout routine from polling the keyboard */
3893 if (!kbdc_lock(sc_kbdc, TRUE))
3894 return;
3895
3896 /* disable the keyboard and mouse interrupt */
3897 s = spltty();
3898#if 0
3899 c = get_controller_command_byte(sc_kbdc);
3900 if ((c == -1)
3901 || !set_controller_command_byte(sc_kbdc,
3902 kbdc_get_device_mask(sc_kbdc),
3903 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
3904 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
3905 /* CONTROLLER ERROR */
3906 kbdc_lock(sc_kbdc, FALSE);
3907 splx(s);
3908 return;
3909 }
3910 /*
3911 * Now that the keyboard controller is told not to generate
3912 * the keyboard and mouse interrupts, call `splx()' to allow
3913 * the other tty interrupts. The clock interrupt may also occur,
3914 * but the timeout routine (`scrn_timer()') will be blocked
3915 * by the lock flag set via `kbdc_lock()'
3916 */
3917 splx(s);
3918#endif
3919
3920 if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK)
3921 send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD);
3922
3923#if 0
3924 /* restore the interrupts */
3925 if (!set_controller_command_byte(sc_kbdc,
3926 kbdc_get_device_mask(sc_kbdc),
3927 c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
3928 /* CONTROLLER ERROR */
3929 }
3930#else
3931 splx(s);
3932#endif
3933 kbdc_lock(sc_kbdc, FALSE);
3934}
3935
3936static void
3937update_leds(int which)
3938{
3939 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
3940
3941 /* replace CAPS led with ALTGR led for ALTGR keyboards */
3942 if (key_map.n_keys > ALTGR_OFFSET) {
3943 if (which & ALKED)
3944 which |= CLKED;
3945 else
3946 which &= ~CLKED;
3947 }
3948
3949 set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]);
3950}
3951
3952int
3953set_mode(scr_stat *scp)
3954{
3955 video_info_t info;
3956 video_adapter_t *adp;
3957
3958 /* reject unsupported mode */
3959 if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info))
3960 return 1;
3961
3962 /* if this vty is not currently showing, do nothing */
3963 if (scp != cur_console)
3964 return 0;
3965
3966 /* setup video hardware for the given mode */
3967 adp = get_adapter(scp);
3968 (*biosvidsw.set_mode)(scp->adp, scp->mode);
3969 Crtat = (u_short *)adp->va_window;
3970
3971 if (!(scp->status & GRAPHICS_MODE)) {
3972 /* load appropriate font */
3973 if (!(scp->status & PIXEL_MODE)
3974 && ISFONTAVAIL(get_adapter(scp)->va_flags)) {
3975 if (scp->font_size < 14) {
3976 if (fonts_loaded & FONT_8)
3977 copy_font(scp, LOAD, 8, font_8);
3978 } else if (scp->font_size >= 16) {
3979 if (fonts_loaded & FONT_16)
3980 copy_font(scp, LOAD, 16, font_16);
3981 } else {
3982 if (fonts_loaded & FONT_14)
3983 copy_font(scp, LOAD, 14, font_14);
3984 }
3985 /*
3986 * FONT KLUDGE:
3987 * This is an interim kludge to display correct font.
3988 * Always use the font page #0 on the video plane 2.
3989 * Somehow we cannot show the font in other font pages on
3990 * some video cards... XXX
3991 */
3992 (*biosvidsw.show_font)(scp->adp, 0);
3993 }
3994 mark_all(scp);
3995 }
3037
3038 console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos
3039 = sc_buffer;
3040 if (col >= console[0]->xsize)
3041 col = 0;
3042 if (row >= console[0]->ysize)
3043 row = console[0]->ysize - 1;
3044 console[0]->xpos = col;
3045 console[0]->ypos = row;
3046 console[0]->cursor_pos = console[0]->cursor_oldpos =
3047 sc_buffer + row*console[0]->xsize + col;
3048 console[0]->cursor_saveunder = *console[0]->cursor_pos;
3049 for (i=1; i<MAXCONS; i++)
3050 console[i] = NULL;
3051 kernel_console.esc = 0;
3052 kernel_console.attr_mask = NORMAL_ATTR;
3053 kernel_console.cur_attr =
3054 kernel_console.cur_color = kernel_console.std_color =
3055 kernel_default.std_color;
3056 kernel_console.rev_color = kernel_default.rev_color;
3057
3058 /* initialize mapscrn arrays to a one to one map */
3059 for (i=0; i<sizeof(scr_map); i++) {
3060 scr_map[i] = scr_rmap[i] = i;
3061 }
3062
3063 /* Save font and palette */
3064 if (ISFONTAVAIL(get_adapter(cur_console)->va_flags)) {
3065 if (fonts_loaded & FONT_16) {
3066 copy_font(cur_console, LOAD, 16, font_16);
3067 } else {
3068 copy_font(cur_console, SAVE, 16, font_16);
3069 fonts_loaded = FONT_16;
3070 set_destructive_cursor(cur_console);
3071 }
3072 /*
3073 * FONT KLUDGE
3074 * Always use the font page #0. XXX
3075 */
3076 (*biosvidsw.show_font)(cur_console->adp, 0);
3077 }
3078 save_palette(cur_console, palette);
3079
3080#ifdef SC_SPLASH_SCREEN
3081 /* put up the splash. */
3082 scsplash_init(cur_console);
3083#endif
3084}
3085
3086static void
3087scshutdown(int howto, void *arg)
3088{
3089 scsplash_stick(FALSE);
3090 run_scrn_saver = FALSE;
3091 if (!cold && cur_console->smode.mode == VT_AUTO
3092 && console[0]->smode.mode == VT_AUTO)
3093 switch_scr(cur_console, 0);
3094 shutdown_in_progress = TRUE;
3095}
3096
3097int
3098sc_clean_up(scr_stat *scp)
3099{
3100 int error;
3101
3102 if ((error = wait_scrn_saver_stop()))
3103 return error;
3104 scp->status &= ~MOUSE_VISIBLE;
3105 remove_cutmarking(scp);
3106 return 0;
3107}
3108
3109void
3110sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear)
3111{
3112 if (scp->scr_buf)
3113 free(scp->scr_buf, M_DEVBUF);
3114 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short),
3115 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
3116
3117 if (clear) {
3118 /* clear the screen and move the text cursor to the top-left position */
3119 sc_clear_screen(scp);
3120 } else {
3121 /* retain the current cursor position, but adjust pointers */
3122 move_crsr(scp, scp->xpos, scp->ypos);
3123 scp->cursor_oldpos = scp->cursor_pos;
3124 }
3125
3126 /* move the mouse cursor at the center of the screen */
3127 sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2);
3128}
3129
3130void
3131sc_alloc_cut_buffer(scr_stat *scp, int wait)
3132{
3133 if ((cut_buffer == NULL)
3134 || (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
3135 if (cut_buffer != NULL)
3136 free(cut_buffer, M_DEVBUF);
3137 cut_buffer_size = scp->xsize * scp->ysize + 1;
3138 cut_buffer = (u_char *)malloc(cut_buffer_size,
3139 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
3140 if (cut_buffer != NULL)
3141 cut_buffer[0] = '\0';
3142 }
3143}
3144
3145void
3146sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait)
3147{
3148 u_short *usp;
3149
3150 if (lines < scp->ysize)
3151 lines = scp->ysize;
3152
3153 usp = scp->history;
3154 scp->history = NULL;
3155 if (usp != NULL) {
3156 free(usp, M_DEVBUF);
3157 if (extra > 0)
3158 extra_history_size += extra;
3159 }
3160
3161 scp->history_size = lines * scp->xsize;
3162 if (lines > imax(sc_history_size, scp->ysize))
3163 extra_history_size -= lines - imax(sc_history_size, scp->ysize);
3164 usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
3165 M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
3166 if (usp != NULL)
3167 bzero(usp, scp->history_size * sizeof(u_short));
3168 scp->history_head = scp->history_pos = usp;
3169 scp->history = usp;
3170}
3171
3172static scr_stat
3173*alloc_scp()
3174{
3175 scr_stat *scp;
3176
3177 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK);
3178 init_scp(scp);
3179 sc_alloc_scr_buffer(scp, TRUE, TRUE);
3180 if (ISMOUSEAVAIL(get_adapter(scp)->va_flags))
3181 sc_alloc_cut_buffer(scp, TRUE);
3182 sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE);
3183/* SOS
3184 if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE)
3185 set_mode(scp);
3186*/
3187 sc_clear_screen(scp);
3188 scp->cursor_saveunder = *scp->cursor_pos;
3189 return scp;
3190}
3191
3192static void
3193init_scp(scr_stat *scp)
3194{
3195 video_info_t info;
3196
3197 scp->adp = V_ADP_PRIMARY;
3198 (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info);
3199
3200 scp->status = 0;
3201 scp->mode = scp->initial_mode = initial_video_mode;
3202 scp->scr_buf = NULL;
3203 if (info.vi_flags & V_INFO_GRAPHICS) {
3204 scp->status |= GRAPHICS_MODE;
3205 scp->xpixel = info.vi_width;
3206 scp->ypixel = info.vi_height;
3207 scp->xsize = info.vi_width/8;
3208 scp->ysize = info.vi_height/info.vi_cheight;
3209 scp->font_size = FONT_NONE;
3210 } else {
3211 scp->xsize = info.vi_width;
3212 scp->ysize = info.vi_height;
3213 scp->xpixel = scp->xsize*8;
3214 scp->ypixel = scp->ysize*info.vi_cheight;
3215 scp->font_size = info.vi_cheight;
3216 }
3217 scp->xoff = scp->yoff = 0;
3218 scp->xpos = scp->ypos = 0;
3219 scp->saved_xpos = scp->saved_ypos = -1;
3220 scp->start = scp->xsize * scp->ysize;
3221 scp->end = 0;
3222 scp->term.esc = 0;
3223 scp->term.attr_mask = NORMAL_ATTR;
3224 scp->term.cur_attr =
3225 scp->term.cur_color = scp->term.std_color =
3226 current_default->std_color;
3227 scp->term.rev_color = current_default->rev_color;
3228 scp->border = BG_BLACK;
3229 scp->cursor_start = *(u_int8_t *)pa_to_va(0x461);
3230 scp->cursor_end = *(u_int8_t *)pa_to_va(0x460);
3231 scp->mouse_xpos = scp->xsize*8/2;
3232 scp->mouse_ypos = scp->ysize*scp->font_size/2;
3233 scp->mouse_cut_start = scp->mouse_cut_end = NULL;
3234 scp->mouse_signal = 0;
3235 scp->mouse_pid = 0;
3236 scp->mouse_proc = NULL;
3237 scp->bell_pitch = BELL_PITCH;
3238 scp->bell_duration = BELL_DURATION;
3239 scp->status |= (*(u_int8_t *)pa_to_va(0x417) & 0x20) ? NLKED : 0;
3240 scp->status |= CURSOR_ENABLED;
3241 scp->pid = 0;
3242 scp->proc = NULL;
3243 scp->smode.mode = VT_AUTO;
3244 scp->history_head = scp->history_pos = scp->history = NULL;
3245 scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize;
3246}
3247
3248static u_char
3249*get_fstr(u_int c, u_int *len)
3250{
3251 u_int i;
3252
3253 if (!(c & FKEY))
3254 return(NULL);
3255 i = (c & 0xFF) - F_FN;
3256 if (i > n_fkey_tab)
3257 return(NULL);
3258 *len = fkey_tab[i].len;
3259 return(fkey_tab[i].str);
3260}
3261
3262static void
3263history_to_screen(scr_stat *scp)
3264{
3265 int i;
3266
3267 for (i=0; i<scp->ysize; i++)
3268 bcopy(scp->history + (((scp->history_pos - scp->history) +
3269 scp->history_size-((i+1)*scp->xsize))%scp->history_size),
3270 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)),
3271 scp->xsize * sizeof(u_short));
3272 mark_all(scp);
3273}
3274
3275static int
3276history_up_line(scr_stat *scp)
3277{
3278 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) !=
3279 scp->history_head) {
3280 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize);
3281 history_to_screen(scp);
3282 return 0;
3283 }
3284 else
3285 return -1;
3286}
3287
3288static int
3289history_down_line(scr_stat *scp)
3290{
3291 if (scp->history_pos != scp->history_head) {
3292 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize);
3293 history_to_screen(scp);
3294 return 0;
3295 }
3296 else
3297 return -1;
3298}
3299
3300/*
3301 * scgetc(flags) - get character from keyboard.
3302 * If flags & SCGETC_CN, then avoid harmful side effects.
3303 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else
3304 * return NOKEY if there is nothing there.
3305 */
3306static u_int
3307scgetc(u_int flags)
3308{
3309 struct key_t *key;
3310 u_char scancode, keycode;
3311 u_int state, action;
3312 int c;
3313 static u_char esc_flag = 0, compose = 0;
3314 static u_int chr = 0;
3315
3316next_code:
3317 /* first see if there is something in the keyboard port */
3318 if (flags & SCGETC_NONBLOCK) {
3319 c = read_kbd_data_no_wait(sc_kbdc);
3320 if (c == -1)
3321 return(NOKEY);
3322 } else {
3323 do {
3324 c = read_kbd_data(sc_kbdc);
3325 } while(c == -1);
3326 }
3327 scancode = (u_char)c;
3328
3329 /* make screensaver happy */
3330 if (!(scancode & 0x80)) {
3331 scsplash_stick(FALSE);
3332 run_scrn_saver = FALSE;
3333 }
3334
3335 if (!(flags & SCGETC_CN)) {
3336 /* do the /dev/random device a favour */
3337 add_keyboard_randomness(scancode);
3338
3339 if (cur_console->status & KBD_RAW_MODE)
3340 return scancode;
3341 }
3342
3343 keycode = scancode & 0x7F;
3344 switch (esc_flag) {
3345 case 0x00: /* normal scancode */
3346 switch(scancode) {
3347 case 0xB8: /* left alt (compose key) */
3348 if (compose) {
3349 compose = 0;
3350 if (chr > 255) {
3351 do_bell(cur_console,
3352 BELL_PITCH, BELL_DURATION);
3353 chr = 0;
3354 }
3355 }
3356 break;
3357 case 0x38:
3358 if (!compose) {
3359 compose = 1;
3360 chr = 0;
3361 }
3362 break;
3363 case 0xE0:
3364 case 0xE1:
3365 esc_flag = scancode;
3366 goto next_code;
3367 }
3368 break;
3369 case 0xE0: /* 0xE0 prefix */
3370 esc_flag = 0;
3371 switch (keycode) {
3372 case 0x1C: /* right enter key */
3373 keycode = 0x59;
3374 break;
3375 case 0x1D: /* right ctrl key */
3376 keycode = 0x5A;
3377 break;
3378 case 0x35: /* keypad divide key */
3379 keycode = 0x5B;
3380 break;
3381 case 0x37: /* print scrn key */
3382 keycode = 0x5C;
3383 break;
3384 case 0x38: /* right alt key (alt gr) */
3385 keycode = 0x5D;
3386 break;
3387 case 0x47: /* grey home key */
3388 keycode = 0x5E;
3389 break;
3390 case 0x48: /* grey up arrow key */
3391 keycode = 0x5F;
3392 break;
3393 case 0x49: /* grey page up key */
3394 keycode = 0x60;
3395 break;
3396 case 0x4B: /* grey left arrow key */
3397 keycode = 0x61;
3398 break;
3399 case 0x4D: /* grey right arrow key */
3400 keycode = 0x62;
3401 break;
3402 case 0x4F: /* grey end key */
3403 keycode = 0x63;
3404 break;
3405 case 0x50: /* grey down arrow key */
3406 keycode = 0x64;
3407 break;
3408 case 0x51: /* grey page down key */
3409 keycode = 0x65;
3410 break;
3411 case 0x52: /* grey insert key */
3412 keycode = 0x66;
3413 break;
3414 case 0x53: /* grey delete key */
3415 keycode = 0x67;
3416 break;
3417
3418 /* the following 3 are only used on the MS "Natural" keyboard */
3419 case 0x5b: /* left Window key */
3420 keycode = 0x69;
3421 break;
3422 case 0x5c: /* right Window key */
3423 keycode = 0x6a;
3424 break;
3425 case 0x5d: /* menu key */
3426 keycode = 0x6b;
3427 break;
3428 default: /* ignore everything else */
3429 goto next_code;
3430 }
3431 break;
3432 case 0xE1: /* 0xE1 prefix */
3433 esc_flag = 0;
3434 if (keycode == 0x1D)
3435 esc_flag = 0x1D;
3436 goto next_code;
3437 /* NOT REACHED */
3438 case 0x1D: /* pause / break */
3439 esc_flag = 0;
3440 if (keycode != 0x45)
3441 goto next_code;
3442 keycode = 0x68;
3443 break;
3444 }
3445
3446 if (!(flags & SCGETC_CN) && (cur_console->status & KBD_CODE_MODE))
3447 return (keycode | (scancode & 0x80));
3448
3449 /* if scroll-lock pressed allow history browsing */
3450 if (cur_console->history && cur_console->status & SLKED) {
3451 int i;
3452
3453 cur_console->status &= ~CURSOR_ENABLED;
3454 if (!(cur_console->status & BUFFER_SAVED)) {
3455 cur_console->status |= BUFFER_SAVED;
3456 cur_console->history_save = cur_console->history_head;
3457
3458 /* copy screen into top of history buffer */
3459 for (i=0; i<cur_console->ysize; i++) {
3460 bcopy(cur_console->scr_buf + (cur_console->xsize * i),
3461 cur_console->history_head,
3462 cur_console->xsize * sizeof(u_short));
3463 cur_console->history_head += cur_console->xsize;
3464 if (cur_console->history_head + cur_console->xsize >
3465 cur_console->history + cur_console->history_size)
3466 cur_console->history_head=cur_console->history;
3467 }
3468 cur_console->history_pos = cur_console->history_head;
3469 history_to_screen(cur_console);
3470 }
3471 switch (scancode) {
3472 case 0x47: /* home key */
3473 cur_console->history_pos = cur_console->history_head;
3474 history_to_screen(cur_console);
3475 goto next_code;
3476
3477 case 0x4F: /* end key */
3478 cur_console->history_pos =
3479 WRAPHIST(cur_console, cur_console->history_head,
3480 cur_console->xsize*cur_console->ysize);
3481 history_to_screen(cur_console);
3482 goto next_code;
3483
3484 case 0x48: /* up arrow key */
3485 if (history_up_line(cur_console))
3486 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3487 goto next_code;
3488
3489 case 0x50: /* down arrow key */
3490 if (history_down_line(cur_console))
3491 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3492 goto next_code;
3493
3494 case 0x49: /* page up key */
3495 for (i=0; i<cur_console->ysize; i++)
3496 if (history_up_line(cur_console)) {
3497 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3498 break;
3499 }
3500 goto next_code;
3501
3502 case 0x51: /* page down key */
3503 for (i=0; i<cur_console->ysize; i++)
3504 if (history_down_line(cur_console)) {
3505 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3506 break;
3507 }
3508 goto next_code;
3509 }
3510 }
3511
3512 if (compose) {
3513 switch (scancode) {
3514 /* key pressed process it */
3515 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
3516 chr = (scancode - 0x40) + chr*10;
3517 goto next_code;
3518 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
3519 chr = (scancode - 0x47) + chr*10;
3520 goto next_code;
3521 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
3522 chr = (scancode - 0x4E) + chr*10;
3523 goto next_code;
3524 case 0x52: /* keypad 0 */
3525 chr *= 10;
3526 goto next_code;
3527
3528 /* key release, no interest here */
3529 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
3530 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
3531 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
3532 case 0xD2: /* keypad 0 */
3533 goto next_code;
3534
3535 case 0x38: /* left alt key */
3536 break;
3537 default:
3538 if (chr) {
3539 compose = chr = 0;
3540 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3541 goto next_code;
3542 }
3543 break;
3544 }
3545 }
3546
3547 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0));
3548 if ((!agrs && (cur_console->status & ALKED))
3549 || (agrs && !(cur_console->status & ALKED)))
3550 keycode += ALTGR_OFFSET;
3551 key = &key_map.key[keycode];
3552 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED))
3553 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) )
3554 state ^= 1;
3555
3556 /* Check for make/break */
3557 action = key->map[state];
3558 if (scancode & 0x80) { /* key released */
3559 if (key->spcl & (0x80>>state)) {
3560 switch (action) {
3561 case LSH:
3562 shfts &= ~1;
3563 break;
3564 case RSH:
3565 shfts &= ~2;
3566 break;
3567 case LCTR:
3568 ctls &= ~1;
3569 break;
3570 case RCTR:
3571 ctls &= ~2;
3572 break;
3573 case LALT:
3574 alts &= ~1;
3575 break;
3576 case RALT:
3577 alts &= ~2;
3578 break;
3579 case NLK:
3580 nlkcnt = 0;
3581 break;
3582 case CLK:
3583 clkcnt = 0;
3584 break;
3585 case SLK:
3586 slkcnt = 0;
3587 break;
3588 case ASH:
3589 agrs = 0;
3590 break;
3591 case ALK:
3592 alkcnt = 0;
3593 break;
3594 case META:
3595 metas = 0;
3596 break;
3597 }
3598 }
3599 if (chr && !compose) {
3600 action = chr;
3601 chr = 0;
3602 return(action);
3603 }
3604 } else {
3605 /* key pressed */
3606 if (key->spcl & (0x80>>state)) {
3607 switch (action) {
3608 /* LOCKING KEYS */
3609 case NLK:
3610 if (!nlkcnt) {
3611 nlkcnt++;
3612 if (cur_console->status & NLKED)
3613 cur_console->status &= ~NLKED;
3614 else
3615 cur_console->status |= NLKED;
3616 update_leds(cur_console->status);
3617 }
3618 break;
3619 case CLK:
3620 if (!clkcnt) {
3621 clkcnt++;
3622 if (cur_console->status & CLKED)
3623 cur_console->status &= ~CLKED;
3624 else
3625 cur_console->status |= CLKED;
3626 update_leds(cur_console->status);
3627 }
3628 break;
3629 case SLK:
3630 if (!slkcnt) {
3631 slkcnt++;
3632 if (cur_console->status & SLKED) {
3633 cur_console->status &= ~SLKED;
3634 if (cur_console->status & BUFFER_SAVED){
3635 int i;
3636 u_short *ptr = cur_console->history_save;
3637
3638 for (i=0; i<cur_console->ysize; i++) {
3639 bcopy(ptr,
3640 cur_console->scr_buf +
3641 (cur_console->xsize*i),
3642 cur_console->xsize * sizeof(u_short));
3643 ptr += cur_console->xsize;
3644 if (ptr + cur_console->xsize >
3645 cur_console->history +
3646 cur_console->history_size)
3647 ptr = cur_console->history;
3648 }
3649 cur_console->status &= ~BUFFER_SAVED;
3650 cur_console->history_head=cur_console->history_save;
3651 cur_console->status |= CURSOR_ENABLED;
3652 mark_all(cur_console);
3653 }
3654 scstart(VIRTUAL_TTY(get_scr_num()));
3655 }
3656 else
3657 cur_console->status |= SLKED;
3658 update_leds(cur_console->status);
3659 }
3660 break;
3661 case ALK:
3662 if (!alkcnt) {
3663 alkcnt++;
3664 if (cur_console->status & ALKED)
3665 cur_console->status &= ~ALKED;
3666 else
3667 cur_console->status |= ALKED;
3668 update_leds(cur_console->status);
3669 }
3670 break;
3671
3672 /* NON-LOCKING KEYS */
3673 case NOP:
3674 break;
3675 case SPSC:
3676 /* force activatation/deactivation of the screen saver */
3677 accents = 0;
3678 if (scrn_blanked <= 0) {
3679 run_scrn_saver = TRUE;
3680 scrn_time_stamp -= scrn_blank_time;
3681 }
3682#ifdef SC_SPLASH_SCREEN
3683 if (cold) {
3684 /*
3685 * While devices are being probed, the screen saver need
3686 * to be invoked explictly. XXX
3687 */
3688 if (scrn_blanked > 0) {
3689 scsplash_stick(FALSE);
3690 stop_scrn_saver(current_saver);
3691 } else {
3692 if (!ISGRAPHSC(cur_console)) {
3693 scsplash_stick(TRUE);
3694 scrn_saver(current_saver, TRUE);
3695 }
3696 }
3697 }
3698#endif
3699 break;
3700 case RBT:
3701#ifndef SC_DISABLE_REBOOT
3702 accents = 0;
3703 shutdown_nice();
3704#endif
3705 break;
3706 case SUSP:
3707#if NAPM > 0
3708 accents = 0;
3709 apm_suspend(PMST_SUSPEND);
3710#endif
3711 break;
3712
3713 case STBY:
3714#if NAPM > 0
3715 accents = 0;
3716 apm_suspend(PMST_STANDBY);
3717#endif
3718 break;
3719
3720 case DBG:
3721#ifdef DDB /* try to switch to console 0 */
3722 accents = 0;
3723 /*
3724 * TRY to make sure the screen saver is stopped,
3725 * and the screen is updated before switching to
3726 * the vty0.
3727 */
3728 scrn_timer((void *)FALSE);
3729 if (cur_console->smode.mode == VT_AUTO &&
3730 console[0]->smode.mode == VT_AUTO)
3731 switch_scr(cur_console, 0);
3732 Debugger("manual escape to debugger");
3733#else
3734 printf("No debugger in kernel\n");
3735#endif
3736 break;
3737 case LSH:
3738 shfts |= 1;
3739 break;
3740 case RSH:
3741 shfts |= 2;
3742 break;
3743 case LCTR:
3744 ctls |= 1;
3745 break;
3746 case RCTR:
3747 ctls |= 2;
3748 break;
3749 case LALT:
3750 alts |= 1;
3751 break;
3752 case RALT:
3753 alts |= 2;
3754 break;
3755 case ASH:
3756 agrs = 1;
3757 break;
3758 case META:
3759 metas = 1;
3760 break;
3761 case NEXT:
3762 {
3763 int next, this = get_scr_num();
3764 accents = 0;
3765 for (next = this+1; next != this; next = (next+1)%MAXCONS) {
3766 struct tty *tp = VIRTUAL_TTY(next);
3767 if (tp->t_state & TS_ISOPEN) {
3768 switch_scr(cur_console, next);
3769 break;
3770 }
3771 }
3772 }
3773 break;
3774 case BTAB:
3775 accents = 0;
3776 return(BKEY);
3777 default:
3778 if (action >= F_ACC && action <= L_ACC) {
3779 /* turn it into an index */
3780 action -= F_ACC - 1;
3781 if ((action > accent_map.n_accs)
3782 || (accent_map.acc[action - 1].accchar == 0)) {
3783 /*
3784 * The index is out of range or pointing to an
3785 * empty entry.
3786 */
3787 accents = 0;
3788 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3789 }
3790 /*
3791 * If the same accent key has been hit twice,
3792 * produce the accent char itself.
3793 */
3794 if (action == accents) {
3795 action = accent_map.acc[accents - 1].accchar;
3796 accents = 0;
3797 if (metas)
3798 action |= MKEY;
3799 return (action);
3800 }
3801 /* remember the index and wait for the next key stroke */
3802 accents = action;
3803 break;
3804 }
3805 if (accents > 0) {
3806 accents = 0;
3807 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3808 }
3809 if (action >= F_SCR && action <= L_SCR) {
3810 switch_scr(cur_console, action - F_SCR);
3811 break;
3812 }
3813 if (action >= F_FN && action <= L_FN)
3814 action |= FKEY;
3815 return(action);
3816 }
3817 }
3818 else {
3819 if (accents) {
3820 struct acc_t *acc;
3821 int i;
3822
3823 acc = &accent_map.acc[accents - 1];
3824 accents = 0;
3825 /*
3826 * If the accent key is followed by the space key,
3827 * produce the accent char itself.
3828 */
3829 if (action == ' ') {
3830 action = acc->accchar;
3831 if (metas)
3832 action |= MKEY;
3833 return (action);
3834 }
3835 for (i = 0; i < NUM_ACCENTCHARS; ++i) {
3836 if (acc->map[i][0] == 0) /* end of the map entry */
3837 break;
3838 if (acc->map[i][0] == action) {
3839 action = acc->map[i][1];
3840 if (metas)
3841 action |= MKEY;
3842 return (action);
3843 }
3844 }
3845 do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3846 goto next_code;
3847 }
3848 if (metas)
3849 action |= MKEY;
3850 return(action);
3851 }
3852 }
3853 goto next_code;
3854}
3855
3856int
3857scmmap(dev_t dev, int offset, int nprot)
3858{
3859 if (offset > 0x20000 - PAGE_SIZE)
3860 return -1;
3861 return i386_btop((VIDEOMEM + offset));
3862}
3863
3864/*
3865 * Calculate hardware attributes word using logical attributes mask and
3866 * hardware colors
3867 */
3868
3869static int
3870mask2attr(struct term_stat *term)
3871{
3872 int attr, mask = term->attr_mask;
3873
3874 if (mask & REVERSE_ATTR) {
3875 attr = ((mask & FOREGROUND_CHANGED) ?
3876 ((term->cur_color & 0xF000) >> 4) :
3877 (term->rev_color & 0x0F00)) |
3878 ((mask & BACKGROUND_CHANGED) ?
3879 ((term->cur_color & 0x0F00) << 4) :
3880 (term->rev_color & 0xF000));
3881 } else
3882 attr = term->cur_color;
3883
3884 /* XXX: underline mapping for Hercules adapter can be better */
3885 if (mask & (BOLD_ATTR | UNDERLINE_ATTR))
3886 attr ^= 0x0800;
3887 if (mask & BLINK_ATTR)
3888 attr ^= 0x8000;
3889
3890 return attr;
3891}
3892
3893static void
3894set_keyboard(int command, int data)
3895{
3896 int s;
3897
3898 if (sc_kbdc == NULL)
3899 return;
3900
3901 /* prevent the timeout routine from polling the keyboard */
3902 if (!kbdc_lock(sc_kbdc, TRUE))
3903 return;
3904
3905 /* disable the keyboard and mouse interrupt */
3906 s = spltty();
3907#if 0
3908 c = get_controller_command_byte(sc_kbdc);
3909 if ((c == -1)
3910 || !set_controller_command_byte(sc_kbdc,
3911 kbdc_get_device_mask(sc_kbdc),
3912 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
3913 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
3914 /* CONTROLLER ERROR */
3915 kbdc_lock(sc_kbdc, FALSE);
3916 splx(s);
3917 return;
3918 }
3919 /*
3920 * Now that the keyboard controller is told not to generate
3921 * the keyboard and mouse interrupts, call `splx()' to allow
3922 * the other tty interrupts. The clock interrupt may also occur,
3923 * but the timeout routine (`scrn_timer()') will be blocked
3924 * by the lock flag set via `kbdc_lock()'
3925 */
3926 splx(s);
3927#endif
3928
3929 if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK)
3930 send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD);
3931
3932#if 0
3933 /* restore the interrupts */
3934 if (!set_controller_command_byte(sc_kbdc,
3935 kbdc_get_device_mask(sc_kbdc),
3936 c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
3937 /* CONTROLLER ERROR */
3938 }
3939#else
3940 splx(s);
3941#endif
3942 kbdc_lock(sc_kbdc, FALSE);
3943}
3944
3945static void
3946update_leds(int which)
3947{
3948 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
3949
3950 /* replace CAPS led with ALTGR led for ALTGR keyboards */
3951 if (key_map.n_keys > ALTGR_OFFSET) {
3952 if (which & ALKED)
3953 which |= CLKED;
3954 else
3955 which &= ~CLKED;
3956 }
3957
3958 set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]);
3959}
3960
3961int
3962set_mode(scr_stat *scp)
3963{
3964 video_info_t info;
3965 video_adapter_t *adp;
3966
3967 /* reject unsupported mode */
3968 if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info))
3969 return 1;
3970
3971 /* if this vty is not currently showing, do nothing */
3972 if (scp != cur_console)
3973 return 0;
3974
3975 /* setup video hardware for the given mode */
3976 adp = get_adapter(scp);
3977 (*biosvidsw.set_mode)(scp->adp, scp->mode);
3978 Crtat = (u_short *)adp->va_window;
3979
3980 if (!(scp->status & GRAPHICS_MODE)) {
3981 /* load appropriate font */
3982 if (!(scp->status & PIXEL_MODE)
3983 && ISFONTAVAIL(get_adapter(scp)->va_flags)) {
3984 if (scp->font_size < 14) {
3985 if (fonts_loaded & FONT_8)
3986 copy_font(scp, LOAD, 8, font_8);
3987 } else if (scp->font_size >= 16) {
3988 if (fonts_loaded & FONT_16)
3989 copy_font(scp, LOAD, 16, font_16);
3990 } else {
3991 if (fonts_loaded & FONT_14)
3992 copy_font(scp, LOAD, 14, font_14);
3993 }
3994 /*
3995 * FONT KLUDGE:
3996 * This is an interim kludge to display correct font.
3997 * Always use the font page #0 on the video plane 2.
3998 * Somehow we cannot show the font in other font pages on
3999 * some video cards... XXX
4000 */
4001 (*biosvidsw.show_font)(scp->adp, 0);
4002 }
4003 mark_all(scp);
4004 }
4005
4006 if (scp->status & PIXEL_MODE)
4007 generic_bzero((u_char *)(adp->va_window), scp->xpixel*scp->ypixel/8);
3996 set_border(scp, scp->border);
3997
3998 /* move hardware cursor out of the way */
3999 (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1);
4000
4001 return 0;
4002}
4003
4004void
4008 set_border(scp, scp->border);
4009
4010 /* move hardware cursor out of the way */
4011 (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1);
4012
4013 return 0;
4014}
4015
4016void
4017set_border(scr_stat *scp, int color)
4018{
4019 u_char *p;
4020 int xoff;
4021 int yoff;
4022 int xlen;
4023 int ylen;
4024 int i;
4025
4026 (*biosvidsw.set_border)(scp->adp, color);
4027
4028 if (scp->status & PIXEL_MODE) {
4029 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
4030 outw(GDCIDX, 0x0003); /* data rotate/function select */
4031 outw(GDCIDX, 0x0f01); /* set/reset enable */
4032 outw(GDCIDX, 0xff08); /* bit mask */
4033 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
4034 p = (u_char *)(get_adapter(scp)->va_window);
4035 xoff = scp->xoff;
4036 yoff = scp->yoff*scp->font_size;
4037 xlen = scp->xpixel/8;
4038 ylen = scp->ysize*scp->font_size;
4039 if (yoff > 0) {
4040 generic_bzero(p, xlen*yoff);
4041 generic_bzero(p + xlen*(yoff + ylen),
4042 xlen*scp->ypixel - xlen*(yoff + ylen));
4043 }
4044 if (xoff > 0) {
4045 for (i = 0; i < ylen; ++i) {
4046 generic_bzero(p + xlen*(yoff + i), xoff);
4047 generic_bzero(p + xlen*(yoff + i) + xoff + scp->xsize,
4048 xlen - xoff - scp->xsize);
4049 }
4050 }
4051 outw(GDCIDX, 0x0000); /* set/reset */
4052 outw(GDCIDX, 0x0001); /* set/reset enable */
4053 }
4054}
4055
4056void
4005copy_font(scr_stat *scp, int operation, int font_size, u_char *buf)
4006{
4007 /*
4008 * FONT KLUDGE:
4009 * This is an interim kludge to display correct font.
4010 * Always use the font page #0 on the video plane 2.
4011 * Somehow we cannot show the font in other font pages on
4012 * some video cards... XXX
4013 */
4014 font_loading_in_progress = TRUE;
4015 if (operation == LOAD) {
4016 (*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256);
4017 if (flags & CHAR_CURSOR)
4018 set_destructive_cursor(scp);
4019 } else if (operation == SAVE) {
4020 (*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256);
4021 }
4022 font_loading_in_progress = FALSE;
4023}
4024
4025static void
4026set_destructive_cursor(scr_stat *scp)
4027{
4028 u_char cursor[32];
4029 u_char *font_buffer;
4030 int font_size;
4031 int i;
4032
4033 if (!ISFONTAVAIL(get_adapter(scp)->va_flags) || !ISTEXTSC(scp))
4034 return;
4035
4036 if (scp->font_size < 14) {
4037 font_buffer = font_8;
4038 font_size = 8;
4039 } else if (scp->font_size >= 16) {
4040 font_buffer = font_16;
4041 font_size = 16;
4042 } else {
4043 font_buffer = font_14;
4044 font_size = 14;
4045 }
4046
4047 if (scp->status & MOUSE_VISIBLE) {
4048 if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR)
4049 bcopy(&scp->mouse_cursor[0], cursor, scp->font_size);
4050 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 1)
4051 bcopy(&scp->mouse_cursor[32], cursor, scp->font_size);
4052 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 2)
4053 bcopy(&scp->mouse_cursor[64], cursor, scp->font_size);
4054 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 3)
4055 bcopy(&scp->mouse_cursor[96], cursor, scp->font_size);
4056 else
4057 bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size),
4058 cursor, scp->font_size);
4059 }
4060 else
4061 bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size),
4062 cursor, scp->font_size);
4063 for (i=0; i<32; i++)
4064 if ((i >= scp->cursor_start && i <= scp->cursor_end) ||
4065 (scp->cursor_start >= scp->font_size && i == scp->font_size - 1))
4066 cursor[i] |= 0xff;
4067#if 1
4068 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ;
4069#endif
4070 font_loading_in_progress = TRUE;
4071 (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1);
4072 font_loading_in_progress = FALSE;
4073}
4074
4075void
4076sc_move_mouse(scr_stat *scp, int x, int y)
4077{
4078 scp->mouse_xpos = x;
4079 scp->mouse_ypos = y;
4080 scp->mouse_pos = scp->mouse_oldpos =
4081 scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8;
4082}
4083
4084static void
4085set_mouse_pos(scr_stat *scp)
4086{
4087 static int last_xpos = -1, last_ypos = -1;
4088
4089 if (scp->mouse_xpos < 0)
4090 scp->mouse_xpos = 0;
4091 if (scp->mouse_ypos < 0)
4092 scp->mouse_ypos = 0;
4093 if (!ISTEXTSC(scp)) {
4094 if (scp->mouse_xpos > scp->xpixel-1)
4095 scp->mouse_xpos = scp->xpixel-1;
4096 if (scp->mouse_ypos > scp->ypixel-1)
4097 scp->mouse_ypos = scp->ypixel-1;
4098 return;
4099 }
4100 if (scp->mouse_xpos > (scp->xsize*8)-1)
4101 scp->mouse_xpos = (scp->xsize*8)-1;
4102 if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1)
4103 scp->mouse_ypos = (scp->ysize*scp->font_size)-1;
4104
4105 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) {
4106 scp->status |= MOUSE_MOVED;
4107
4108 scp->mouse_pos = scp->scr_buf +
4109 ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8);
4110
4111 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING))
4112 mouse_cut(scp);
4113 }
4114}
4115
4116#define isspace(c) (((c) & 0xff) == ' ')
4117
4118static int
4119skip_spc_right(scr_stat *scp, u_short *p)
4120{
4121 int i;
4122
4123 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) {
4124 if (!isspace(*p))
4125 break;
4126 ++p;
4127 }
4128 return i;
4129}
4130
4131static int
4132skip_spc_left(scr_stat *scp, u_short *p)
4133{
4134 int i;
4135
4136 for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) {
4137 if (!isspace(*p))
4138 break;
4139 --p;
4140 }
4141 return i;
4142}
4143
4144static void
4145mouse_cut(scr_stat *scp)
4146{
4147 u_short *end;
4148 u_short *p;
4149 int i = 0;
4150 int j = 0;
4151
4152 scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ?
4153 scp->mouse_pos + 1 : scp->mouse_pos;
4154 end = (scp->mouse_cut_start > scp->mouse_cut_end) ?
4155 scp->mouse_cut_start : scp->mouse_cut_end;
4156 for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ?
4157 scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) {
4158 cut_buffer[i] = *p & 0xff;
4159 /* remember the position of the last non-space char */
4160 if (!isspace(cut_buffer[i++]))
4161 j = i;
4162 /* trim trailing blank when crossing lines */
4163 if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) {
4164 cut_buffer[j++] = '\r';
4165 i = j;
4166 }
4167 }
4168 cut_buffer[i] = '\0';
4169
4170 /* scan towards the end of the last line */
4171 --p;
4172 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) {
4173 if (!isspace(*p))
4174 break;
4175 ++p;
4176 }
4177 /* if there is nothing but blank chars, trim them, but mark towards eol */
4178 if (i >= scp->xsize) {
4179 if (scp->mouse_cut_start > scp->mouse_cut_end)
4180 scp->mouse_cut_start = p;
4181 else
4182 scp->mouse_cut_end = p;
4183 cut_buffer[j++] = '\r';
4184 cut_buffer[j] = '\0';
4185 }
4186
4187 mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf);
4188 mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf);
4189}
4190
4191static void
4192mouse_cut_start(scr_stat *scp)
4193{
4194 int i;
4195
4196 if (scp->status & MOUSE_VISIBLE) {
4197 if (scp->mouse_pos == scp->mouse_cut_start &&
4198 scp->mouse_cut_start == scp->mouse_cut_end - 1) {
4199 cut_buffer[0] = '\0';
4200 remove_cutmarking(scp);
4201 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) {
4202 /* if the pointer is on trailing blank chars, mark towards eol */
4203 i = skip_spc_left(scp, scp->mouse_pos) + 1;
4204 scp->mouse_cut_start = scp->scr_buf +
4205 ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i;
4206 scp->mouse_cut_end = scp->scr_buf +
4207 ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize;
4208 cut_buffer[0] = '\r';
4209 cut_buffer[1] = '\0';
4210 scp->status |= MOUSE_CUTTING;
4211 } else {
4212 scp->mouse_cut_start = scp->mouse_pos;
4213 scp->mouse_cut_end = scp->mouse_cut_start + 1;
4214 cut_buffer[0] = *scp->mouse_cut_start & 0xff;
4215 cut_buffer[1] = '\0';
4216 scp->status |= MOUSE_CUTTING;
4217 }
4218 mark_all(scp);
4219 /* delete all other screens cut markings */
4220 for (i=0; i<MAXCONS; i++) {
4221 if (console[i] == NULL || console[i] == scp)
4222 continue;
4223 remove_cutmarking(console[i]);
4224 }
4225 }
4226}
4227
4228static void
4229mouse_cut_end(scr_stat *scp)
4230{
4231 if (scp->status & MOUSE_VISIBLE) {
4232 scp->status &= ~MOUSE_CUTTING;
4233 }
4234}
4235
4236static void
4237mouse_cut_word(scr_stat *scp)
4238{
4239 u_short *p;
4240 u_short *sol;
4241 u_short *eol;
4242 int i;
4243
4244 /*
4245 * Because we don't have locale information in the kernel,
4246 * we only distinguish space char and non-space chars. Punctuation
4247 * chars, symbols and other regular chars are all treated alike.
4248 */
4249 if (scp->status & MOUSE_VISIBLE) {
4250 sol = scp->scr_buf
4251 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize;
4252 eol = sol + scp->xsize;
4253 if (isspace(*scp->mouse_pos)) {
4254 for (p = scp->mouse_pos; p >= sol; --p)
4255 if (!isspace(*p))
4256 break;
4257 scp->mouse_cut_start = ++p;
4258 for (p = scp->mouse_pos; p < eol; ++p)
4259 if (!isspace(*p))
4260 break;
4261 scp->mouse_cut_end = p;
4262 } else {
4263 for (p = scp->mouse_pos; p >= sol; --p)
4264 if (isspace(*p))
4265 break;
4266 scp->mouse_cut_start = ++p;
4267 for (p = scp->mouse_pos; p < eol; ++p)
4268 if (isspace(*p))
4269 break;
4270 scp->mouse_cut_end = p;
4271 }
4272 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p)
4273 cut_buffer[i++] = *p & 0xff;
4274 cut_buffer[i] = '\0';
4275 scp->status |= MOUSE_CUTTING;
4276 }
4277}
4278
4279static void
4280mouse_cut_line(scr_stat *scp)
4281{
4282 u_short *p;
4283 int i;
4284
4285 if (scp->status & MOUSE_VISIBLE) {
4286 scp->mouse_cut_start = scp->scr_buf
4287 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize;
4288 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize;
4289 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p)
4290 cut_buffer[i++] = *p & 0xff;
4291 cut_buffer[i++] = '\r';
4292 cut_buffer[i] = '\0';
4293 scp->status |= MOUSE_CUTTING;
4294 }
4295}
4296
4297static void
4298mouse_cut_extend(scr_stat *scp)
4299{
4300 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING)
4301 && (scp->mouse_cut_start != NULL)) {
4302 mouse_cut(scp);
4303 scp->status |= MOUSE_CUTTING;
4304 }
4305}
4306
4307static void
4308mouse_paste(scr_stat *scp)
4309{
4310 if (scp->status & MOUSE_VISIBLE) {
4311 struct tty *tp;
4312 u_char *ptr = cut_buffer;
4313
4314 tp = VIRTUAL_TTY(get_scr_num());
4315 while (*ptr)
4316 (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp);
4317 }
4318}
4319
4320static void
4321draw_mouse_image(scr_stat *scp)
4322{
4323 u_short buffer[32];
4324 u_short xoffset, yoffset;
4057copy_font(scr_stat *scp, int operation, int font_size, u_char *buf)
4058{
4059 /*
4060 * FONT KLUDGE:
4061 * This is an interim kludge to display correct font.
4062 * Always use the font page #0 on the video plane 2.
4063 * Somehow we cannot show the font in other font pages on
4064 * some video cards... XXX
4065 */
4066 font_loading_in_progress = TRUE;
4067 if (operation == LOAD) {
4068 (*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256);
4069 if (flags & CHAR_CURSOR)
4070 set_destructive_cursor(scp);
4071 } else if (operation == SAVE) {
4072 (*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256);
4073 }
4074 font_loading_in_progress = FALSE;
4075}
4076
4077static void
4078set_destructive_cursor(scr_stat *scp)
4079{
4080 u_char cursor[32];
4081 u_char *font_buffer;
4082 int font_size;
4083 int i;
4084
4085 if (!ISFONTAVAIL(get_adapter(scp)->va_flags) || !ISTEXTSC(scp))
4086 return;
4087
4088 if (scp->font_size < 14) {
4089 font_buffer = font_8;
4090 font_size = 8;
4091 } else if (scp->font_size >= 16) {
4092 font_buffer = font_16;
4093 font_size = 16;
4094 } else {
4095 font_buffer = font_14;
4096 font_size = 14;
4097 }
4098
4099 if (scp->status & MOUSE_VISIBLE) {
4100 if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR)
4101 bcopy(&scp->mouse_cursor[0], cursor, scp->font_size);
4102 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 1)
4103 bcopy(&scp->mouse_cursor[32], cursor, scp->font_size);
4104 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 2)
4105 bcopy(&scp->mouse_cursor[64], cursor, scp->font_size);
4106 else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 3)
4107 bcopy(&scp->mouse_cursor[96], cursor, scp->font_size);
4108 else
4109 bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size),
4110 cursor, scp->font_size);
4111 }
4112 else
4113 bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size),
4114 cursor, scp->font_size);
4115 for (i=0; i<32; i++)
4116 if ((i >= scp->cursor_start && i <= scp->cursor_end) ||
4117 (scp->cursor_start >= scp->font_size && i == scp->font_size - 1))
4118 cursor[i] |= 0xff;
4119#if 1
4120 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ;
4121#endif
4122 font_loading_in_progress = TRUE;
4123 (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1);
4124 font_loading_in_progress = FALSE;
4125}
4126
4127void
4128sc_move_mouse(scr_stat *scp, int x, int y)
4129{
4130 scp->mouse_xpos = x;
4131 scp->mouse_ypos = y;
4132 scp->mouse_pos = scp->mouse_oldpos =
4133 scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8;
4134}
4135
4136static void
4137set_mouse_pos(scr_stat *scp)
4138{
4139 static int last_xpos = -1, last_ypos = -1;
4140
4141 if (scp->mouse_xpos < 0)
4142 scp->mouse_xpos = 0;
4143 if (scp->mouse_ypos < 0)
4144 scp->mouse_ypos = 0;
4145 if (!ISTEXTSC(scp)) {
4146 if (scp->mouse_xpos > scp->xpixel-1)
4147 scp->mouse_xpos = scp->xpixel-1;
4148 if (scp->mouse_ypos > scp->ypixel-1)
4149 scp->mouse_ypos = scp->ypixel-1;
4150 return;
4151 }
4152 if (scp->mouse_xpos > (scp->xsize*8)-1)
4153 scp->mouse_xpos = (scp->xsize*8)-1;
4154 if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1)
4155 scp->mouse_ypos = (scp->ysize*scp->font_size)-1;
4156
4157 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) {
4158 scp->status |= MOUSE_MOVED;
4159
4160 scp->mouse_pos = scp->scr_buf +
4161 ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8);
4162
4163 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING))
4164 mouse_cut(scp);
4165 }
4166}
4167
4168#define isspace(c) (((c) & 0xff) == ' ')
4169
4170static int
4171skip_spc_right(scr_stat *scp, u_short *p)
4172{
4173 int i;
4174
4175 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) {
4176 if (!isspace(*p))
4177 break;
4178 ++p;
4179 }
4180 return i;
4181}
4182
4183static int
4184skip_spc_left(scr_stat *scp, u_short *p)
4185{
4186 int i;
4187
4188 for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) {
4189 if (!isspace(*p))
4190 break;
4191 --p;
4192 }
4193 return i;
4194}
4195
4196static void
4197mouse_cut(scr_stat *scp)
4198{
4199 u_short *end;
4200 u_short *p;
4201 int i = 0;
4202 int j = 0;
4203
4204 scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ?
4205 scp->mouse_pos + 1 : scp->mouse_pos;
4206 end = (scp->mouse_cut_start > scp->mouse_cut_end) ?
4207 scp->mouse_cut_start : scp->mouse_cut_end;
4208 for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ?
4209 scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) {
4210 cut_buffer[i] = *p & 0xff;
4211 /* remember the position of the last non-space char */
4212 if (!isspace(cut_buffer[i++]))
4213 j = i;
4214 /* trim trailing blank when crossing lines */
4215 if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) {
4216 cut_buffer[j++] = '\r';
4217 i = j;
4218 }
4219 }
4220 cut_buffer[i] = '\0';
4221
4222 /* scan towards the end of the last line */
4223 --p;
4224 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) {
4225 if (!isspace(*p))
4226 break;
4227 ++p;
4228 }
4229 /* if there is nothing but blank chars, trim them, but mark towards eol */
4230 if (i >= scp->xsize) {
4231 if (scp->mouse_cut_start > scp->mouse_cut_end)
4232 scp->mouse_cut_start = p;
4233 else
4234 scp->mouse_cut_end = p;
4235 cut_buffer[j++] = '\r';
4236 cut_buffer[j] = '\0';
4237 }
4238
4239 mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf);
4240 mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf);
4241}
4242
4243static void
4244mouse_cut_start(scr_stat *scp)
4245{
4246 int i;
4247
4248 if (scp->status & MOUSE_VISIBLE) {
4249 if (scp->mouse_pos == scp->mouse_cut_start &&
4250 scp->mouse_cut_start == scp->mouse_cut_end - 1) {
4251 cut_buffer[0] = '\0';
4252 remove_cutmarking(scp);
4253 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) {
4254 /* if the pointer is on trailing blank chars, mark towards eol */
4255 i = skip_spc_left(scp, scp->mouse_pos) + 1;
4256 scp->mouse_cut_start = scp->scr_buf +
4257 ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i;
4258 scp->mouse_cut_end = scp->scr_buf +
4259 ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize;
4260 cut_buffer[0] = '\r';
4261 cut_buffer[1] = '\0';
4262 scp->status |= MOUSE_CUTTING;
4263 } else {
4264 scp->mouse_cut_start = scp->mouse_pos;
4265 scp->mouse_cut_end = scp->mouse_cut_start + 1;
4266 cut_buffer[0] = *scp->mouse_cut_start & 0xff;
4267 cut_buffer[1] = '\0';
4268 scp->status |= MOUSE_CUTTING;
4269 }
4270 mark_all(scp);
4271 /* delete all other screens cut markings */
4272 for (i=0; i<MAXCONS; i++) {
4273 if (console[i] == NULL || console[i] == scp)
4274 continue;
4275 remove_cutmarking(console[i]);
4276 }
4277 }
4278}
4279
4280static void
4281mouse_cut_end(scr_stat *scp)
4282{
4283 if (scp->status & MOUSE_VISIBLE) {
4284 scp->status &= ~MOUSE_CUTTING;
4285 }
4286}
4287
4288static void
4289mouse_cut_word(scr_stat *scp)
4290{
4291 u_short *p;
4292 u_short *sol;
4293 u_short *eol;
4294 int i;
4295
4296 /*
4297 * Because we don't have locale information in the kernel,
4298 * we only distinguish space char and non-space chars. Punctuation
4299 * chars, symbols and other regular chars are all treated alike.
4300 */
4301 if (scp->status & MOUSE_VISIBLE) {
4302 sol = scp->scr_buf
4303 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize;
4304 eol = sol + scp->xsize;
4305 if (isspace(*scp->mouse_pos)) {
4306 for (p = scp->mouse_pos; p >= sol; --p)
4307 if (!isspace(*p))
4308 break;
4309 scp->mouse_cut_start = ++p;
4310 for (p = scp->mouse_pos; p < eol; ++p)
4311 if (!isspace(*p))
4312 break;
4313 scp->mouse_cut_end = p;
4314 } else {
4315 for (p = scp->mouse_pos; p >= sol; --p)
4316 if (isspace(*p))
4317 break;
4318 scp->mouse_cut_start = ++p;
4319 for (p = scp->mouse_pos; p < eol; ++p)
4320 if (isspace(*p))
4321 break;
4322 scp->mouse_cut_end = p;
4323 }
4324 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p)
4325 cut_buffer[i++] = *p & 0xff;
4326 cut_buffer[i] = '\0';
4327 scp->status |= MOUSE_CUTTING;
4328 }
4329}
4330
4331static void
4332mouse_cut_line(scr_stat *scp)
4333{
4334 u_short *p;
4335 int i;
4336
4337 if (scp->status & MOUSE_VISIBLE) {
4338 scp->mouse_cut_start = scp->scr_buf
4339 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize;
4340 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize;
4341 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p)
4342 cut_buffer[i++] = *p & 0xff;
4343 cut_buffer[i++] = '\r';
4344 cut_buffer[i] = '\0';
4345 scp->status |= MOUSE_CUTTING;
4346 }
4347}
4348
4349static void
4350mouse_cut_extend(scr_stat *scp)
4351{
4352 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING)
4353 && (scp->mouse_cut_start != NULL)) {
4354 mouse_cut(scp);
4355 scp->status |= MOUSE_CUTTING;
4356 }
4357}
4358
4359static void
4360mouse_paste(scr_stat *scp)
4361{
4362 if (scp->status & MOUSE_VISIBLE) {
4363 struct tty *tp;
4364 u_char *ptr = cut_buffer;
4365
4366 tp = VIRTUAL_TTY(get_scr_num());
4367 while (*ptr)
4368 (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp);
4369 }
4370}
4371
4372static void
4373draw_mouse_image(scr_stat *scp)
4374{
4375 u_short buffer[32];
4376 u_short xoffset, yoffset;
4325 u_short *crt_pos = Crtat + (scp->mouse_pos - scp->scr_buf);
4377 u_short *crt_pos = (u_short *)(get_adapter(scp)->va_window)
4378 + (scp->mouse_pos - scp->scr_buf);
4326 u_char *font_buffer;
4327 int font_size;
4328 int i;
4329
4330 if (scp->font_size < 14) {
4331 font_buffer = font_8;
4332 font_size = 8;
4333 } else if (scp->font_size >= 16) {
4334 font_buffer = font_16;
4335 font_size = 16;
4336 } else {
4337 font_buffer = font_14;
4338 font_size = 14;
4339 }
4340
4341 xoffset = scp->mouse_xpos % 8;
4342 yoffset = scp->mouse_ypos % scp->font_size;
4343
4344 /* prepare mousepointer char's bitmaps */
4345 bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size),
4346 &scp->mouse_cursor[0], font_size);
4347 bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size),
4348 &scp->mouse_cursor[32], font_size);
4349 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size),
4350 &scp->mouse_cursor[64], font_size);
4351 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size),
4352 &scp->mouse_cursor[96], font_size);
4353 for (i=0; i<font_size; i++) {
4354 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32];
4355 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96];
4356 }
4357
4358 /* now and-or in the mousepointer image */
4359 for (i=0; i<16; i++) {
4360 buffer[i+yoffset] =
4361 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset))
4362 | (mouse_or_mask[i] >> xoffset);
4363 }
4364 for (i=0; i<font_size; i++) {
4365 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8;
4366 scp->mouse_cursor[i+32] = buffer[i] & 0xff;
4367 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8;
4368 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff;
4369 }
4370
4371 scp->mouse_oldpos = scp->mouse_pos;
4372
4373#if 1
4374 /* wait for vertical retrace to avoid jitter on some videocards */
4375 while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ;
4376#endif
4377 font_loading_in_progress = TRUE;
4378 (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor,
4379 SC_MOUSE_CHAR, 4);
4380 font_loading_in_progress = FALSE;
4381
4382 *(crt_pos) = (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR;
4383 *(crt_pos+scp->xsize) =
4384 (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2);
4385 if (scp->mouse_xpos < (scp->xsize-1)*8) {
4386 *(crt_pos + 1) = (*(scp->mouse_pos + 1) & 0xff00) | (SC_MOUSE_CHAR + 1);
4387 *(crt_pos+scp->xsize + 1) =
4388 (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (SC_MOUSE_CHAR + 3);
4389 }
4390 mark_for_update(scp, scp->mouse_pos - scp->scr_buf);
4391 mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf);
4392}
4393
4394static void
4395remove_mouse_image(scr_stat *scp)
4396{
4379 u_char *font_buffer;
4380 int font_size;
4381 int i;
4382
4383 if (scp->font_size < 14) {
4384 font_buffer = font_8;
4385 font_size = 8;
4386 } else if (scp->font_size >= 16) {
4387 font_buffer = font_16;
4388 font_size = 16;
4389 } else {
4390 font_buffer = font_14;
4391 font_size = 14;
4392 }
4393
4394 xoffset = scp->mouse_xpos % 8;
4395 yoffset = scp->mouse_ypos % scp->font_size;
4396
4397 /* prepare mousepointer char's bitmaps */
4398 bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size),
4399 &scp->mouse_cursor[0], font_size);
4400 bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size),
4401 &scp->mouse_cursor[32], font_size);
4402 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size),
4403 &scp->mouse_cursor[64], font_size);
4404 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size),
4405 &scp->mouse_cursor[96], font_size);
4406 for (i=0; i<font_size; i++) {
4407 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32];
4408 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96];
4409 }
4410
4411 /* now and-or in the mousepointer image */
4412 for (i=0; i<16; i++) {
4413 buffer[i+yoffset] =
4414 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset))
4415 | (mouse_or_mask[i] >> xoffset);
4416 }
4417 for (i=0; i<font_size; i++) {
4418 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8;
4419 scp->mouse_cursor[i+32] = buffer[i] & 0xff;
4420 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8;
4421 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff;
4422 }
4423
4424 scp->mouse_oldpos = scp->mouse_pos;
4425
4426#if 1
4427 /* wait for vertical retrace to avoid jitter on some videocards */
4428 while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ;
4429#endif
4430 font_loading_in_progress = TRUE;
4431 (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor,
4432 SC_MOUSE_CHAR, 4);
4433 font_loading_in_progress = FALSE;
4434
4435 *(crt_pos) = (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR;
4436 *(crt_pos+scp->xsize) =
4437 (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2);
4438 if (scp->mouse_xpos < (scp->xsize-1)*8) {
4439 *(crt_pos + 1) = (*(scp->mouse_pos + 1) & 0xff00) | (SC_MOUSE_CHAR + 1);
4440 *(crt_pos+scp->xsize + 1) =
4441 (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (SC_MOUSE_CHAR + 3);
4442 }
4443 mark_for_update(scp, scp->mouse_pos - scp->scr_buf);
4444 mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf);
4445}
4446
4447static void
4448remove_mouse_image(scr_stat *scp)
4449{
4397 u_short *crt_pos = Crtat + (scp->mouse_oldpos - scp->scr_buf);
4450 u_short *crt_pos;
4398
4399 if (!ISTEXTSC(scp))
4400 return;
4451
4452 if (!ISTEXTSC(scp))
4453 return;
4454
4455 crt_pos = (u_short *)(get_adapter(scp)->va_window)
4456 + (scp->mouse_oldpos - scp->scr_buf);
4401 *(crt_pos) = *(scp->mouse_oldpos);
4402 *(crt_pos+1) = *(scp->mouse_oldpos+1);
4403 *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize);
4404 *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1);
4405 mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf);
4406 mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf);
4407}
4408
4409static void
4410draw_cutmarking(scr_stat *scp)
4411{
4457 *(crt_pos) = *(scp->mouse_oldpos);
4458 *(crt_pos+1) = *(scp->mouse_oldpos+1);
4459 *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize);
4460 *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1);
4461 mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf);
4462 mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf);
4463}
4464
4465static void
4466draw_cutmarking(scr_stat *scp)
4467{
4468 u_short *crt_pos;
4412 u_short *ptr;
4413 u_short och, nch;
4414
4469 u_short *ptr;
4470 u_short och, nch;
4471
4472 crt_pos = (u_short *)(get_adapter(scp)->va_window);
4415 for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) {
4473 for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) {
4416 nch = och = *(Crtat + (ptr - scp->scr_buf));
4474 nch = och = *(crt_pos + (ptr - scp->scr_buf));
4417 /* are we outside the selected area ? */
4418 if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ?
4419 scp->mouse_cut_end : scp->mouse_cut_start) ||
4420 ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ?
4421 scp->mouse_cut_start : scp->mouse_cut_end)) {
4422 if (ptr != scp->cursor_pos)
4423 nch = (och & 0xff) | (*ptr & 0xff00);
4424 }
4425 else {
4426 /* are we clear of the cursor image ? */
4427 if (ptr != scp->cursor_pos)
4428 nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4;
4429 else {
4430 if (flags & CHAR_CURSOR)
4431 nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4;
4432 else
4433 if (!(flags & BLINK_CURSOR))
4434 nch = (och & 0xff) | (*ptr & 0xff00);
4435 }
4436 }
4437 if (nch != och)
4475 /* are we outside the selected area ? */
4476 if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ?
4477 scp->mouse_cut_end : scp->mouse_cut_start) ||
4478 ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ?
4479 scp->mouse_cut_start : scp->mouse_cut_end)) {
4480 if (ptr != scp->cursor_pos)
4481 nch = (och & 0xff) | (*ptr & 0xff00);
4482 }
4483 else {
4484 /* are we clear of the cursor image ? */
4485 if (ptr != scp->cursor_pos)
4486 nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4;
4487 else {
4488 if (flags & CHAR_CURSOR)
4489 nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4;
4490 else
4491 if (!(flags & BLINK_CURSOR))
4492 nch = (och & 0xff) | (*ptr & 0xff00);
4493 }
4494 }
4495 if (nch != och)
4438 *(Crtat + (ptr - scp->scr_buf)) = nch;
4496 *(crt_pos + (ptr - scp->scr_buf)) = nch;
4439 }
4440}
4441
4442static void
4443remove_cutmarking(scr_stat *scp)
4444{
4445 scp->mouse_cut_start = scp->mouse_cut_end = NULL;
4446 scp->status &= ~MOUSE_CUTTING;
4447 mark_all(scp);
4448}
4449
4450static void
4451do_bell(scr_stat *scp, int pitch, int duration)
4452{
4453 if (cold || shutdown_in_progress)
4454 return;
4455
4456 if (scp != cur_console && (flags & QUIET_BELL))
4457 return;
4458
4459 if (flags & VISUAL_BELL) {
4460 if (blink_in_progress)
4461 return;
4462 blink_in_progress = 4;
4463 if (scp != cur_console)
4464 blink_in_progress += 2;
4465 blink_screen(cur_console);
4466 } else {
4467 if (scp != cur_console)
4468 pitch *= 2;
4469 sysbeep(pitch, duration);
4470 }
4471}
4472
4473static void
4474blink_screen(void *arg)
4475{
4476 scr_stat *scp = arg;
4477
4478 if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) {
4479 blink_in_progress = FALSE;
4480 mark_all(scp);
4481 if (delayed_next_scr)
4482 switch_scr(scp, delayed_next_scr - 1);
4483 }
4484 else {
4485 if (blink_in_progress & 1)
4486 fillw(kernel_default.std_color | scr_map[0x20],
4497 }
4498}
4499
4500static void
4501remove_cutmarking(scr_stat *scp)
4502{
4503 scp->mouse_cut_start = scp->mouse_cut_end = NULL;
4504 scp->status &= ~MOUSE_CUTTING;
4505 mark_all(scp);
4506}
4507
4508static void
4509do_bell(scr_stat *scp, int pitch, int duration)
4510{
4511 if (cold || shutdown_in_progress)
4512 return;
4513
4514 if (scp != cur_console && (flags & QUIET_BELL))
4515 return;
4516
4517 if (flags & VISUAL_BELL) {
4518 if (blink_in_progress)
4519 return;
4520 blink_in_progress = 4;
4521 if (scp != cur_console)
4522 blink_in_progress += 2;
4523 blink_screen(cur_console);
4524 } else {
4525 if (scp != cur_console)
4526 pitch *= 2;
4527 sysbeep(pitch, duration);
4528 }
4529}
4530
4531static void
4532blink_screen(void *arg)
4533{
4534 scr_stat *scp = arg;
4535
4536 if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) {
4537 blink_in_progress = FALSE;
4538 mark_all(scp);
4539 if (delayed_next_scr)
4540 switch_scr(scp, delayed_next_scr - 1);
4541 }
4542 else {
4543 if (blink_in_progress & 1)
4544 fillw(kernel_default.std_color | scr_map[0x20],
4487 Crtat, scp->xsize * scp->ysize);
4545 (u_short *)(get_adapter(scp)->va_window),
4546 scp->xsize * scp->ysize);
4488 else
4489 fillw(kernel_default.rev_color | scr_map[0x20],
4547 else
4548 fillw(kernel_default.rev_color | scr_map[0x20],
4490 Crtat, scp->xsize * scp->ysize);
4549 (u_short *)(get_adapter(scp)->va_window),
4550 scp->xsize * scp->ysize);
4491 blink_in_progress--;
4492 timeout(blink_screen, scp, hz / 10);
4493 }
4494}
4495
4496void
4497sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark)
4498{
4499 u_char *font;
4551 blink_in_progress--;
4552 timeout(blink_screen, scp, hz / 10);
4553 }
4554}
4555
4556void
4557sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark)
4558{
4559 u_char *font;
4500 u_char *d, *e;
4560 u_char volatile *d;
4561 u_char *e;
4501 u_char *f;
4502 int font_size;
4503 int line_length;
4504 int xsize;
4562 u_char *f;
4563 int font_size;
4564 int line_length;
4565 int xsize;
4566 u_short bg;
4505 int i, j;
4567 int i, j;
4568 u_char c;
4506
4507 if (ISTEXTSC(scp)) {
4569
4570 if (ISTEXTSC(scp)) {
4508 generic_bcopy(p+from, Crtat+from, (to-from+1)*sizeof (u_short));
4571 generic_bcopy(p + from, (u_short *)(get_adapter(scp)->va_window) + from,
4572 (to - from + 1)*sizeof(u_short));
4509 } else /* if ISPIXELSC(scp) */ {
4510 if (mark)
4511 mark = 255;
4512 font_size = scp->font_size;
4513 if (font_size < 14)
4514 font = font_8;
4515 else if (font_size >= 16)
4516 font = font_16;
4517 else
4518 font = font_14;
4519 line_length = scp->xpixel/8;
4520 xsize = scp->xsize;
4573 } else /* if ISPIXELSC(scp) */ {
4574 if (mark)
4575 mark = 255;
4576 font_size = scp->font_size;
4577 if (font_size < 14)
4578 font = font_8;
4579 else if (font_size >= 16)
4580 font = font_16;
4581 else
4582 font = font_14;
4583 line_length = scp->xpixel/8;
4584 xsize = scp->xsize;
4521 d = (u_char *)Crtat
4585 d = (u_char *)(get_adapter(scp)->va_window)
4522 + scp->xoff + scp->yoff*font_size*line_length
4523 + (from%xsize) + font_size*line_length*(from/xsize);
4586 + scp->xoff + scp->yoff*font_size*line_length
4587 + (from%xsize) + font_size*line_length*(from/xsize);
4588
4589 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
4590 outw(GDCIDX, 0x0003); /* data rotate/function select */
4591 outw(GDCIDX, 0x0f01); /* set/reset enable */
4592 bg = -1;
4524 for (i = from ; i <= to ; i++) {
4593 for (i = from ; i <= to ; i++) {
4525 e = d;
4594 /* set background color in EGA/VGA latch */
4595 if (bg != (p[i] & 0xf000)) {
4596 bg = (p[i] & 0xf000);
4597 outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */
4598 outw(GDCIDX, 0xff08); /* bit mask */
4599 *d = 0;
4600 c = *d; /* set the background color in the latch */
4601 }
4602 /* foreground color */
4603 outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */
4604 e = (u_char *)d;
4526 f = &font[(p[i] & 0x00ff)*font_size];
4527 for (j = 0 ; j < font_size; j++, f++) {
4605 f = &font[(p[i] & 0x00ff)*font_size];
4606 for (j = 0 ; j < font_size; j++, f++) {
4528 *e = mark^*f;
4607 outw(GDCIDX, ((*f^mark) << 8) | 0x08); /* bit mask */
4608 *e = 0;
4529 e += line_length;
4530 }
4531 d++;
4532 if ((i % xsize) == xsize - 1)
4533 d += scp->xoff*2 + (font_size - 1)*line_length;
4534 }
4609 e += line_length;
4610 }
4611 d++;
4612 if ((i % xsize) == xsize - 1)
4613 d += scp->xoff*2 + (font_size - 1)*line_length;
4614 }
4615 outw(GDCIDX, 0x0000); /* set/reset */
4616 outw(GDCIDX, 0x0001); /* set/reset enable */
4617 outw(GDCIDX, 0xff08); /* bit mask */
4618
4619#if 0 /* VGA only */
4620 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
4621 outw(GDCIDX, 0x0003); /* data rotate/function select */
4622 outw(GDCIDX, 0x0f01); /* set/reset enable */
4623 outw(GDCIDX, 0xff08); /* bit mask */
4624 bg = -1;
4625 for (i = from ; i <= to ; i++) {
4626 /* set background color in EGA/VGA latch */
4627 if (bg != (p[i] & 0xf000)) {
4628 bg = (p[i] & 0xf000);
4629 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
4630 outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */
4631 *d = 0;
4632 c = *d; /* set the background color in the latch */
4633 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
4634 }
4635 /* foreground color */
4636 outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */
4637 e = (u_char *)d;
4638 f = &font[(p[i] & 0x00ff)*font_size];
4639 for (j = 0 ; j < font_size; j++, f++) {
4640 *e = *f^mark;
4641 e += line_length;
4642 }
4643 d++;
4644 if ((i % xsize) == xsize - 1)
4645 d += scp->xoff*2 + (font_size - 1)*line_length;
4646 }
4647 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
4648 outw(GDCIDX, 0x0000); /* set/reset */
4649 outw(GDCIDX, 0x0001); /* set/reset enable */
4650#endif /* 0 */
4535 }
4536}
4537
4538#ifdef SC_SPLASH_SCREEN
4539
4540static void
4541scsplash_init(scr_stat *scp)
4542{
4543 video_info_t info;
4544
4651 }
4652}
4653
4654#ifdef SC_SPLASH_SCREEN
4655
4656static void
4657scsplash_init(scr_stat *scp)
4658{
4659 video_info_t info;
4660
4545 /*
4546 * We currently assume the splash screen always use
4547 * VGA_CG320 mode and abort installation if this mode is not
4548 * supported with this video card. XXX
4549 */
4550 if ((*biosvidsw.get_info)(scp->adp, M_VGA_CG320, &info))
4551 return;
4552
4553 if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) {
4554 default_saver = scsplash_saver;
4555 scrn_blank_time = DEFAULT_BLANKTIME;
4556 run_scrn_saver = TRUE;
4557 if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) {
4558 scsplash_stick(TRUE);
4559 scsplash_saver(TRUE);
4560 }
4561 }
4562}
4563
4564static void
4661 if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) {
4662 default_saver = scsplash_saver;
4663 scrn_blank_time = DEFAULT_BLANKTIME;
4664 run_scrn_saver = TRUE;
4665 if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) {
4666 scsplash_stick(TRUE);
4667 scsplash_saver(TRUE);
4668 }
4669 }
4670}
4671
4672static void
4673scsplash_term(scr_stat *scp)
4674{
4675 default_saver = none_saver;
4676 scsplash_stick(FALSE);
4677 remove_scrn_saver(scsplash_saver);
4678 scsplash_unload(scp);
4679}
4680
4681static void
4565scsplash_saver(int show)
4566{
4567 if (show)
4568 scsplash(TRUE);
4569 else if (!sticky_splash)
4570 scsplash(FALSE);
4571}
4572
4573#endif /* SC_SPLASH_SCREEN */
4574
4575#endif /* NSC */
4682scsplash_saver(int show)
4683{
4684 if (show)
4685 scsplash(TRUE);
4686 else if (!sticky_splash)
4687 scsplash(FALSE);
4688}
4689
4690#endif /* SC_SPLASH_SCREEN */
4691
4692#endif /* NSC */