syscons.c revision 2092
1201052Smarius/*-
2201052Smarius * Copyright (c) 1992-1994 S�ren Schmidt
3201052Smarius * Copyright (c) 1990 The Regents of the University of California.
4201052Smarius * All rights reserved.
5201052Smarius *
6201052Smarius * This code is derived from software contributed to Berkeley by
7201052Smarius * William Jolitz and Don Ahn.
8201052Smarius *
9201052Smarius * Redistribution and use in source and binary forms, with or without
10201052Smarius * modification, are permitted provided that the following conditions
11201052Smarius * are met:
12201052Smarius * 1. Redistributions of source code must retain the above copyright
13201052Smarius *    notice, this list of conditions and the following disclaimer.
14201052Smarius * 2. Redistributions in binary form must reproduce the above copyright
15201052Smarius *    notice, this list of conditions and the following disclaimer in the
16201052Smarius *    documentation and/or other materials provided with the distribution.
17201052Smarius * 3. All advertising materials mentioning features or use of this software
18201052Smarius *    must display the following acknowledgement:
19201052Smarius *	This product includes software developed by the University of
20201052Smarius *	California, Berkeley and its contributors.
21201052Smarius * 4. Neither the name of the University nor the names of its contributors
22201052Smarius *    may be used to endorse or promote products derived from this software
23201052Smarius *    without specific prior written permission.
24201052Smarius *
25201052Smarius * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26201052Smarius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27201052Smarius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28201052Smarius * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29201052Smarius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30201052Smarius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31201052Smarius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32201052Smarius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33201052Smarius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34201052Smarius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35201052Smarius * SUCH DAMAGE.
36201052Smarius *
37201052Smarius *	$Id: syscons.c,v 1.50 1994/08/17 08:51:59 sos Exp $
38201052Smarius */
39201052Smarius
40201052Smarius#include "sc.h"
41201052Smarius
42201052Smarius#if NSC > 0
43201052Smarius
44201052Smarius#include <sys/param.h>
45201052Smarius#include <sys/systm.h>
46201052Smarius#include <sys/conf.h>
47201052Smarius#include <sys/ioctl.h>
48201052Smarius#include <sys/proc.h>
49201052Smarius#include <sys/user.h>
50201052Smarius#include <sys/tty.h>
51201052Smarius#include <sys/uio.h>
52201052Smarius#include <sys/callout.h>
53201052Smarius#include <sys/kernel.h>
54201052Smarius#include <sys/syslog.h>
55201052Smarius#include <sys/errno.h>
56201052Smarius#include <sys/malloc.h>
57201052Smarius#include <machine/console.h>
58201052Smarius#include <machine/psl.h>
59201052Smarius#include <machine/frame.h>
60201052Smarius#include <machine/pc/display.h>
61201052Smarius#include <i386/isa/isa.h>
62201052Smarius#include <i386/isa/isa_device.h>
63201052Smarius#include <i386/isa/timerreg.h>
64201052Smarius#include <i386/isa/kbdtables.h>
65201052Smarius#include <i386/i386/cons.h>
66201052Smarius
67201052Smarius#if !defined(NCONS)
68201052Smarius#define NCONS 12
69201052Smarius#endif
70201052Smarius
71201052Smarius#if !defined(NO_HARDFONTS)
72201052Smarius#include <i386/isa/iso8859.font>
73201052Smarius#endif
74201052Smarius
75201052Smarius/* status flags */
76201052Smarius#define LOCK_KEY_MASK	0x0000F
77201052Smarius#define LED_MASK	0x00007
78201052Smarius#define UNKNOWN_MODE	0x00010
79201052Smarius#define KBD_RAW_MODE	0x00020
80201052Smarius#define SWITCH_WAIT_REL	0x00040
81201052Smarius#define SWITCH_WAIT_ACQ	0x00080
82201052Smarius
83201052Smarius/* video hardware memory addresses */
84202003Smarius#define VIDEOMEM	0x000A0000
85202003Smarius
86201052Smarius/* misc defines */
87201052Smarius#define MAX_ESC_PAR 	5
88201052Smarius#define TEXT80x25	1
89201052Smarius#define TEXT80x50	2
90201052Smarius#define	LOAD		1
91201052Smarius#define SAVE		0
92201052Smarius#define	COL		80
93201052Smarius#define	ROW		25
94201052Smarius#define BELL_DURATION	5
95201052Smarius#define BELL_PITCH	800
96202003Smarius#define TIMER_FREQ	1193182			/* should be in isa.h */
97202003Smarius#define CONSOLE_BUFSIZE 1024
98202003Smarius#define PCBURST		128
99201052Smarius#define FONT_8_LOADED	0x001
100201052Smarius#define FONT_14_LOADED	0x002
101201052Smarius#define FONT_16_LOADED	0x004
102201052Smarius
103201052Smarius/* defines related to hardware addresses */
104201052Smarius#define	MONO_BASE	0x3B4			/* crt controller base mono */
105201052Smarius#define	COLOR_BASE	0x3D4			/* crt controller base color */
106201052Smarius#define ATC		IO_VGA+0x00		/* attribute controller */
107201052Smarius#define TSIDX		IO_VGA+0x04		/* timing sequencer idx */
108201052Smarius#define TSREG		IO_VGA+0x05		/* timing sequencer data */
109201052Smarius#define PIXMASK		IO_VGA+0x06		/* pixel write mask */
110201052Smarius#define PALRADR		IO_VGA+0x07		/* palette read address */
111201052Smarius#define PALWADR		IO_VGA+0x08		/* palette write address */
112201052Smarius#define PALDATA		IO_VGA+0x09		/* palette data register */
113201052Smarius#define GDCIDX		IO_VGA+0x0E		/* graph data controller idx */
114201052Smarius#define GDCREG		IO_VGA+0x0F		/* graph data controller data */
115201052Smarius
116201052Smarius/* special characters */
117201052Smarius#define cntlc	0x03
118201052Smarius#define cntld	0x04
119201052Smarius#define bs	0x08
120201052Smarius#define lf	0x0a
121201052Smarius#define cr	0x0d
122201052Smarius#define del	0x7f
123201052Smarius
124201052Smariustypedef struct term_stat {
125201052Smarius	int 		esc;			/* processing escape sequence */
126201052Smarius	int 		num_param;		/* # of parameters to ESC */
127201052Smarius	int	 	last_param;		/* last parameter # */
128201052Smarius	int 		param[MAX_ESC_PAR];	/* contains ESC parameters */
129201052Smarius	int 		cur_attr;		/* current attributes */
130201052Smarius	int 		std_attr;		/* normal attributes */
131201052Smarius	int 		rev_attr;		/* reverse attributes */
132201052Smarius} term_stat;
133201052Smarius
134201052Smariustypedef struct scr_stat {
135201052Smarius	u_short 	*crt_base;		/* address of screen memory */
136292789Smarius	u_short 	*scr_buf;		/* buffer when off screen */
137201052Smarius	u_short 	*crtat;			/* cursor address */
138201052Smarius	int 		xpos;			/* current X position */
139201052Smarius	int 		ypos;			/* current Y position */
140292789Smarius	int 		xsize;			/* X size */
141225931Smarius	int 		ysize;			/* Y size */
142292789Smarius	term_stat 	term;			/* terminal emulation stuff */
143225931Smarius	char		cursor_start;		/* cursor start line # */
144292789Smarius	char		cursor_end;		/* cursor end line # */
145201052Smarius	u_char		border;			/* border color */
146201052Smarius	u_short		bell_duration;
147201052Smarius	u_short		bell_pitch;
148201052Smarius	u_short 	status;			/* status (bitfield) */
149201052Smarius	u_short 	mode;			/* mode */
150201052Smarius	pid_t 		pid;			/* pid of controlling proc */
151201052Smarius	struct proc 	*proc;			/* proc* of controlling proc */
152201052Smarius	struct vt_mode 	smode;			/* switch mode */
153201052Smarius} scr_stat;
154201052Smarius
155201052Smariustypedef struct default_attr {
156201052Smarius	int             std_attr;               /* normal attributes */
157201052Smarius	int 		rev_attr;		/* reverse attributes */
158292789Smarius} default_attr;
159201052Smarius
160227843Smariusstatic default_attr user_default = {
161201052Smarius	(FG_LIGHTGREY | BG_BLACK) << 8,
162201052Smarius	(FG_BLACK | BG_LIGHTGREY) << 8
163201052Smarius};
164201052Smarius
165201052Smariusstatic default_attr kernel_default = {
166201052Smarius	(FG_WHITE | BG_BLACK) << 8,
167201052Smarius	(FG_BLACK | BG_LIGHTGREY) << 8
168201052Smarius};
169201052Smarius
170201052Smariusstatic	scr_stat	console[NCONS];
171201052Smariusstatic	scr_stat	*cur_console = &console[0];
172201052Smariusstatic	scr_stat	*new_scp, *old_scp;
173201052Smariusstatic	term_stat	kernel_console;
174201052Smariusstatic	default_attr	*current_default;
175201052Smariusstatic	int 		console_buffer_count;
176201052Smariusstatic	char 		console_buffer[CONSOLE_BUFSIZE];
177201052Smariusstatic	int		switch_in_progress = 0;
178201052Smariusstatic 	u_short	 	*crtat = 0;
179201052Smariusstatic	u_int		crtc_addr = MONO_BASE;
180201052Smariusstatic	char		crtc_vga = 0;
181201052Smariusstatic 	u_char		shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0;
182201052Smariusstatic 	u_char		nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0;
183202003Smariusstatic	char		*font_8 = NULL, *font_14 = NULL, *font_16 = NULL;
184202003Smariusstatic  int		fonts_loaded = 0;
185202003Smariusstatic	char		palette[3*256];
186202003Smariusstatic 	const u_int 	n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab);
187202003Smariusstatic	int 		cur_cursor_pos = -1;
188202003Smariusstatic	char 		in_putc = 0;
189202003Smariusstatic	char	 	polling = 0;
190201052Smarius#if ASYNCH
191201052Smariusstatic  u_char		kbd_reply = 0;
192201052Smarius#endif
193201052Smariusstatic	int	 	delayed_next_scr;
194201052Smariusstatic	char		saved_console = -1;	/* saved console number	*/
195201052Smariusstatic	long		scrn_blank_time = 0;	/* screen saver timeout value */
196201052Smariusstatic	int		scrn_blanked = 0;	/* screen saver active flag */
197201052Smariusstatic	int		scrn_saver = 0;		/* screen saver routine */
198201052Smariusstatic	long 		scrn_time_stamp;
199201052Smariusstatic  u_char		scr_map[256];
200201052Smarius
201201052Smariusextern	int hz;
202201052Smariusextern	struct timeval time;
203201052Smarius
204201052Smarius/* function prototypes */
205201052Smariusint pcprobe(struct isa_device *dev);
206201052Smariusint pcattach(struct isa_device *dev);
207201052Smariusint pcopen(dev_t dev, int flag, int mode, struct proc *p);
208201052Smariusint pcclose(dev_t dev, int flag, int mode, struct proc *p);
209201052Smariusint pcread(dev_t dev, struct uio *uio, int flag);
210201052Smariusint pcwrite(dev_t dev, struct uio *uio, int flag);
211201052Smariusint pcparam(struct tty *tp, struct termios *t);
212201052Smariusint pcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
213201052Smariusvoid pcxint(dev_t dev);
214201052Smariusvoid pcstart(struct tty *tp);
215201052Smariusvoid pccnprobe(struct consdev *cp);
216201052Smariusvoid pccninit(struct consdev *cp);
217201052Smariusvoid pccnputc(dev_t dev, char c);
218201052Smariusint pccngetc(dev_t dev);
219201052Smariusvoid scintr(int unit);
220201052Smariusint pcmmap(dev_t dev, int offset, int nprot);
221201052Smariusu_int sgetc(int noblock);
222201052Smariusint getchar(void);
223201052Smariusstatic void scinit(void);
224201052Smariusstatic void scput(u_char c);
225201052Smariusstatic u_int scgetc(int noblock);
226201052Smariusstatic struct tty *get_tty_ptr(dev_t dev);
227201052Smariusstatic scr_stat *get_scr_stat(dev_t dev);
228201052Smariusstatic int get_scr_num();
229201052Smariusstatic void cursor_shape(int start, int end);
230201052Smariusstatic void get_cursor_shape(int *start, int *end);
231201052Smariusstatic void cursor_pos(int force);
232201052Smariusstatic void clear_screen(scr_stat *scp);
233201052Smariusstatic int switch_scr(u_int next_scr);
234201052Smariusstatic void exchange_scr(void);
235201052Smariusstatic void move_crsr(scr_stat *scp, int x, int y);
236201052Smariusstatic void move_up(u_short *s, u_short *d, u_int len);
237201052Smariusstatic void move_down(u_short *s, u_short *d, u_int len);
238201052Smariusstatic void scan_esc(scr_stat *scp, u_char c);
239201052Smariusstatic void ansi_put(scr_stat *scp, u_char c);
240201052Smariusstatic u_char *get_fstr(u_int c, u_int *len);
241201052Smariusstatic void update_leds(int which);
242201052Smariusstatic void kbd_wait(void);
243201052Smariusstatic void kbd_cmd(u_char command);
244201052Smariusstatic void set_mode(scr_stat *scp);
245242625Sdimstatic void set_border(int color);
246201052Smariusstatic void copy_font(int direction, int segment, int size, char* font);
247201052Smariusstatic void save_palette(void);
248201052Smariusstatic void load_palette(void);
249201052Smariusstatic void change_winsize(struct tty *tp, int x, int y);
250201052Smarius
251201052Smarius/* available screen savers */
252201052Smariusstatic void none_saver(int test);
253201052Smariusstatic void blank_saver(int test);
254201052Smariusstatic void fade_saver(int test);
255201052Smariusstatic void star_saver(int test);
256201052Smariusstatic void snake_saver(int test);
257201052Smarius
258201052Smariusstatic const struct {
259201052Smarius	char	*name;
260201052Smarius	void	(*routine)();
261201052Smarius} screen_savers[] = {
262201052Smarius	{ "none",	none_saver },	/* 0 */
263201052Smarius	{ "blank",	blank_saver },	/* 1 */
264201052Smarius	{ "fade",	fade_saver },	/* 2 */
265201052Smarius	{ "star",	star_saver },	/* 3 */
266201052Smarius	{ "snake",	snake_saver },	/* 4 */
267201052Smarius};
268201052Smarius#define SCRN_SAVER(arg)	(*screen_savers[scrn_saver].routine)(arg)
269201052Smarius#define NUM_SCRN_SAVERS	(sizeof(screen_savers) / sizeof(screen_savers[0]))
270201052Smarius
271201052Smarius/* OS specific stuff */
272201052Smarius#if 0
273201052Smarius#define VIRTUAL_TTY(x)	(pccons[x] = ttymalloc(pccons[x]))
274201052Smarius#define	CONSOLE_TTY	(pccons[NCONS] = ttymalloc(pccons[NCONS]))
275201052Smariusstruct	tty 		*pccons[NCONS+1];
276201052Smarius#else
277201052Smarius#define VIRTUAL_TTY(x)	&pccons[x]
278201052Smarius#define	CONSOLE_TTY	&pccons[NCONS]
279201052Smariusstruct	tty 		pccons[NCONS+1];
280201052Smarius#endif
281201052Smarius#define	timeout_t	timeout_func_t
282201052Smarius#define	MONO_BUF	(KERNBASE+0xB0000)
283201052Smarius#define	CGA_BUF		(KERNBASE+0xB8000)
284201052Smarius#include "ddb.h"
285201052Smarius#if NDDB > 0
286201052Smarius#define DDB	1
287201052Smarius#endif
288201052Smariusu_short			*Crtat = (u_short *)MONO_BUF;
289201052Smariusvoid 	consinit(void) 	{scinit();}
290201052Smarius
291201052Smariusstruct	isa_driver scdriver = {
292292789Smarius	pcprobe, pcattach, "sc",
293201052Smarius};
294201052Smarius
295201052Smarius
296201200Smariusint
297201052Smariuspcprobe(struct isa_device *dev)
298201052Smarius{
299201052Smarius	int i, retries = 5;
300201052Smarius	unsigned char val;
301201052Smarius
302201052Smarius	/* Enable interrupts and keyboard controller */
303201052Smarius	kbd_wait();
304201052Smarius	outb(KB_STAT, KB_WRITE);
305201052Smarius	kbd_wait();
306201052Smarius	outb(KB_DATA, KB_MODE);
307201052Smarius
308201052Smarius	/* flush any noise in the buffer */
309201052Smarius	while (inb(KB_STAT) & KB_BUF_FULL) {
310201052Smarius		DELAY(10);
311201052Smarius		(void) inb(KB_DATA);
312201052Smarius	}
313201052Smarius
314201052Smarius	/* Reset keyboard hardware */
315201052Smarius	while (retries--) {
316201052Smarius		kbd_wait();
317201052Smarius		outb(KB_DATA, KB_RESET);
318201052Smarius		for (i=0; i<100000; i++) {
319201052Smarius			DELAY(10);
320201052Smarius			val = inb(KB_DATA);
321201052Smarius			if (val == KB_ACK || val == KB_ECHO)
322201052Smarius				goto gotres;
323201052Smarius			if (val == KB_RESEND)
324201052Smarius				break;
325201052Smarius		}
326201052Smarius	}
327201052Smariusgotres:
328201052Smarius	if (!retries)
329201052Smarius		printf("scprobe: keyboard won't accept RESET command\n");
330219785Smarius	else {
331201052Smariusgotack:
332201052Smarius		DELAY(10);
333201052Smarius		while ((inb(KB_STAT) & KB_BUF_FULL) == 0) DELAY(10);
334201052Smarius		DELAY(10);
335201052Smarius		val = inb(KB_DATA);
336201052Smarius		if (val == KB_ACK)
337201052Smarius			goto gotack;
338201052Smarius		if (val != KB_RESET_DONE)
339201052Smarius			printf("scprobe: keyboard RESET failed %02x\n", val);
340201052Smarius	}
341201052Smarius	return (IO_KBDSIZE);
342201052Smarius}
343201052Smarius
344201052Smarius
345201052Smariusint
346201052Smariuspcattach(struct isa_device *dev)
347201052Smarius{
348201052Smarius	scr_stat *scp;
349201052Smarius	int start = -1, end = -1, i;
350201052Smarius
351201052Smarius	printf("sc%d: ", dev->id_unit);
352201052Smarius	if (crtc_vga)
353201052Smarius		if (crtc_addr == MONO_BASE)
354201052Smarius			printf("VGA mono");
355201052Smarius		else
356201052Smarius			printf("VGA color");
357201052Smarius	else
358201052Smarius		if (crtc_addr == MONO_BASE)
359201052Smarius			printf("MDA/hercules");
360201052Smarius		else
361201052Smarius			printf("CGA/EGA");
362201052Smarius
363201052Smarius	if (NCONS > 1)
364201052Smarius		printf(" <%d virtual consoles>\n", NCONS);
365201052Smarius	else
366201052Smarius		printf("\n");
367201052Smarius#if defined(FAT_CURSOR)
368201052Smarius                start = 0;
369201052Smarius                end = 18;
370201052Smarius	if (crtc_vga) {
371201052Smarius#else
372201052Smarius	if (crtc_vga) {
373201052Smarius		get_cursor_shape(&start, &end);
374201052Smarius#endif
375201052Smarius#if !defined(NO_HARDFONTS)
376201052Smarius		font_8 = font_8x8;
377201052Smarius		font_14 = font_8x14;
378201052Smarius		font_16 = font_8x16;
379201052Smarius		fonts_loaded = FONT_8_LOADED|FONT_14_LOADED|FONT_16_LOADED;
380201052Smarius		copy_font(LOAD, 1, 8, font_8);
381201052Smarius		copy_font(LOAD, 2, 14, font_14);
382201052Smarius		copy_font(LOAD, 0, 16, font_16);
383201052Smarius#else
384201052Smarius		font_8 = (char *)malloc(8*256, M_DEVBUF, M_NOWAIT);
385201052Smarius		font_14 = (char *)malloc(14*256, M_DEVBUF, M_NOWAIT);
386201052Smarius		font_16 = (char *)malloc(16*256, M_DEVBUF, M_NOWAIT);
387201052Smarius		copy_font(SAVE, 0, 16, font_16);
388201052Smarius		fonts_loaded = FONT_16_LOADED;
389201052Smarius#endif
390201052Smarius		save_palette();
391201052Smarius	}
392201052Smarius	current_default = &user_default;
393201052Smarius	for (i = 0; i < NCONS; i++) {
394201052Smarius		scp = &console[i];
395201052Smarius		scp->scr_buf = (u_short *)malloc(COL * ROW * 2,
396201052Smarius						 M_DEVBUF, M_NOWAIT);
397201052Smarius		scp->mode = TEXT80x25;
398201052Smarius		scp->term.esc = 0;
399201052Smarius		scp->term.std_attr = current_default->std_attr;
400201052Smarius		scp->term.rev_attr = current_default->rev_attr;
401201052Smarius		scp->term.cur_attr = scp->term.std_attr;
402201052Smarius		scp->border = BG_BLACK;
403201052Smarius		scp->cursor_start = start;
404201052Smarius		scp->cursor_end = end;
405201052Smarius		scp->xsize = COL;
406201052Smarius		scp->ysize = ROW;
407201052Smarius		scp->bell_pitch = BELL_PITCH;
408201052Smarius		scp->bell_duration = BELL_DURATION;
409201052Smarius		scp->status = NLKED;
410201052Smarius		scp->pid = 0;
411201052Smarius		scp->proc = NULL;
412201052Smarius		scp->smode.mode = VT_AUTO;
413201052Smarius		if (i > 0) {
414201052Smarius			scp->crt_base = scp->crtat = scp->scr_buf;
415201052Smarius			fillw(scp->term.cur_attr|scr_map[0x20],
416201052Smarius			      scp->scr_buf, COL*ROW);
417201052Smarius		}
418201052Smarius	}
419201052Smarius	/* get cursor going */
420201052Smarius#if defined(FAT_CURSOR)
421201052Smarius        cursor_shape(console[0].cursor_start,
422201052Smarius                     console[0].cursor_end);
423201052Smarius#endif
424201052Smarius	cursor_pos(1);
425201052Smarius	update_leds(console[0].status);
426201052Smarius	return 0;
427201052Smarius}
428201052Smarius
429201052Smarius
430201052Smariusstatic struct tty
431201052Smarius*get_tty_ptr(dev_t dev)
432201052Smarius{
433201052Smarius	int unit = minor(dev);
434201052Smarius
435201052Smarius	if (unit > NCONS)
436201052Smarius		return(NULL);
437201052Smarius	if (unit == NCONS)
438233701Smarius		return(CONSOLE_TTY);
439233701Smarius	return(VIRTUAL_TTY(unit));
440201052Smarius}
441201052Smarius
442233701Smarius
443201052Smariusstatic scr_stat
444201052Smarius*get_scr_stat(dev_t dev)
445201052Smarius{
446201052Smarius	int unit = minor(dev);
447201052Smarius
448201052Smarius	if (unit > NCONS)
449201052Smarius		return(NULL);
450201052Smarius	if (unit == NCONS)
451201052Smarius		return(&console[0]);
452201052Smarius	return(&console[unit]);
453201052Smarius}
454201052Smarius
455201052Smarius
456201052Smariusstatic int
457201052Smariusget_scr_num()
458201052Smarius{
459201052Smarius	int i = 0;
460201052Smarius
461201052Smarius	while ((i < NCONS) && (cur_console != &console[i])) i++;
462201052Smarius	return i < NCONS ? i : 0;
463201052Smarius}
464201052Smarius
465201052Smarius
466201052Smariusint
467201052Smariuspcopen(dev_t dev, int flag, int mode, struct proc *p)
468201052Smarius{
469201052Smarius	struct tty *tp = get_tty_ptr(dev);
470201052Smarius
471201052Smarius	if (!tp)
472201052Smarius		return(ENXIO);
473201052Smarius
474201052Smarius	tp->t_oproc = pcstart;
475201052Smarius	tp->t_param = pcparam;
476201052Smarius	tp->t_dev = dev;
477201052Smarius	if (!(tp->t_state & TS_ISOPEN)) {
478201052Smarius		ttychars(tp);
479201052Smarius		tp->t_iflag = TTYDEF_IFLAG;
480201052Smarius		tp->t_oflag = TTYDEF_OFLAG;
481201052Smarius		tp->t_cflag = TTYDEF_CFLAG;
482201052Smarius		tp->t_lflag = TTYDEF_LFLAG;
483201052Smarius		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
484201052Smarius		pcparam(tp, &tp->t_termios);
485201052Smarius		ttsetwater(tp);
486201052Smarius	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
487201052Smarius		return(EBUSY);
488201052Smarius	tp->t_state |= TS_CARR_ON;
489201052Smarius	tp->t_cflag |= CLOCAL;
490201052Smarius	return((*linesw[tp->t_line].l_open)(dev, tp));
491201052Smarius}
492201052Smarius
493201052Smarius
494201052Smariusint
495201052Smariuspcclose(dev_t dev, int flag, int mode, struct proc *p)
496201052Smarius{
497201052Smarius	struct tty *tp = get_tty_ptr(dev);
498201052Smarius	struct scr_stat *scp;
499201052Smarius
500201052Smarius	if (!tp)
501201052Smarius		return(ENXIO);
502201052Smarius	if (minor(dev) < NCONS) {
503201052Smarius		scp = get_scr_stat(tp->t_dev);
504201052Smarius		if (scp->status & SWITCH_WAIT_ACQ)
505201052Smarius			wakeup((caddr_t)&scp->smode);
506201052Smarius		scp->pid = 0;
507201052Smarius		scp->proc = NULL;
508201052Smarius		scp->smode.mode = VT_AUTO;
509201052Smarius	}
510201052Smarius	(*linesw[tp->t_line].l_close)(tp, flag);
511201052Smarius	ttyclose(tp);
512201052Smarius	return(0);
513201052Smarius}
514201052Smarius
515201052Smarius
516201052Smariusint
517201052Smariuspcread(dev_t dev, struct uio *uio, int flag)
518201052Smarius{
519201052Smarius	struct tty *tp = get_tty_ptr(dev);
520201052Smarius
521201052Smarius	if (!tp)
522201052Smarius		return(ENXIO);
523201052Smarius	return((*linesw[tp->t_line].l_read)(tp, uio, flag));
524201052Smarius}
525201052Smarius
526201052Smarius
527201052Smariusint
528201052Smariuspcwrite(dev_t dev, struct uio *uio, int flag)
529201052Smarius{
530201052Smarius	struct tty *tp = get_tty_ptr(dev);
531201052Smarius
532201052Smarius	if (!tp)
533201052Smarius		return(ENXIO);
534201052Smarius	return((*linesw[tp->t_line].l_write)(tp, uio, flag));
535201052Smarius}
536201052Smarius
537201052Smarius
538201052Smariusvoid
539201052Smariusscintr(int unit)
540201052Smarius{
541201052Smarius	static struct tty *cur_tty;
542201052Smarius	int c, len;
543201052Smarius	u_char *cp;
544201052Smarius
545201052Smarius	/* make screensaver happy */
546201052Smarius	scrn_time_stamp = time.tv_sec;
547201052Smarius	if (scrn_blanked)
548201052Smarius		SCRN_SAVER(0);
549201052Smarius
550201052Smarius	c = scgetc(1);
551201052Smarius
552201052Smarius	cur_tty = VIRTUAL_TTY(get_scr_num());
553201052Smarius	if (!(cur_tty->t_state & TS_ISOPEN))
554201052Smarius		cur_tty = CONSOLE_TTY;
555201052Smarius
556201052Smarius	if (!(cur_tty->t_state & TS_ISOPEN) || polling)
557201052Smarius		return;
558201052Smarius
559201052Smarius	switch (c & 0xff00) {
560201052Smarius	case 0x0000: /* normal key */
561201052Smarius		(*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
562201052Smarius		break;
563201052Smarius	case NOKEY:	/* nothing there */
564201052Smarius		break;
565201052Smarius	case FKEY:	/* function key, return string */
566201052Smarius		if (cp = get_fstr((u_int)c, (u_int *)&len)) {
567201052Smarius			while (len-- >  0)
568201052Smarius				(*linesw[cur_tty->t_line].l_rint)
569201052Smarius					(*cp++ & 0xFF, cur_tty);
570201052Smarius		}
571201052Smarius		break;
572201052Smarius	case MKEY:	/* meta is active, prepend ESC */
573201052Smarius		(*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
574201052Smarius		(*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
575201052Smarius		break;
576201052Smarius	}
577201052Smarius}
578201052Smarius
579201052Smarius
580201052Smariusint
581201052Smariuspcparam(struct tty *tp, struct termios *t)
582201052Smarius{
583201052Smarius	int cflag = t->c_cflag;
584201052Smarius
585201052Smarius	/* and copy to tty */
586201052Smarius	tp->t_ispeed = t->c_ispeed;
587201052Smarius	tp->t_ospeed = t->c_ospeed;
588201052Smarius	tp->t_cflag = cflag;
589201052Smarius	return 0;
590201052Smarius}
591201052Smarius
592201052Smarius
593201052Smariusint
594201052Smariuspcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
595201052Smarius{
596201052Smarius	int i, error;
597201052Smarius	struct tty *tp;
598201052Smarius	struct trapframe *fp;
599201052Smarius	scr_stat *scp;
600201052Smarius
601201052Smarius	tp = get_tty_ptr(dev);
602201052Smarius	if (!tp)
603201052Smarius		return ENXIO;
604201052Smarius	scp = get_scr_stat(tp->t_dev);
605201052Smarius
606201052Smarius	switch (cmd) {	/* process console hardware related ioctl's */
607201052Smarius
608201052Smarius	case CONS_BLANKTIME:	/* set screen saver timeout (0 = no saver) */
609201052Smarius		scrn_blank_time = *(int*)data;
610201052Smarius		return 0;
611201052Smarius	case CONS_SSAVER:	/* set screen saver */
612201052Smarius		{
613201052Smarius		register ssaver_t *sav = (ssaver_t *)data;
614201052Smarius		if (sav->num < 0 || sav->num >= NUM_SCRN_SAVERS)
615201052Smarius			return EIO;
616201052Smarius		SCRN_SAVER(0);
617201052Smarius		scrn_saver = sav->num;
618201052Smarius		scrn_blank_time = sav->time;
619201052Smarius		return 0;
620201052Smarius		}
621201052Smarius	case CONS_GSAVER:	/* get screen saver info */
622201052Smarius		{
623201052Smarius		register ssaver_t *sav = (ssaver_t *)data;
624201052Smarius		if (sav->num < 0)
625201052Smarius			sav->num = scrn_saver;
626201052Smarius		else if (sav->num >= NUM_SCRN_SAVERS)
627201052Smarius			return EIO;
628201052Smarius		sav->time = scrn_blank_time;
629201052Smarius		strcpy(sav->name, screen_savers[sav->num].name);
630201052Smarius		return 0;
631201052Smarius		}
632201052Smarius	case CONS_80x25TEXT:	/* set 80x25 text mode */
633201052Smarius		if (!crtc_vga)
634201052Smarius			return ENXIO;
635201052Smarius		scp->mode = TEXT80x25;
636201052Smarius		scp->ysize = 25;
637201052Smarius		free(scp->scr_buf, M_DEVBUF);
638201052Smarius		scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*2,
639201052Smarius					     M_DEVBUF, M_NOWAIT);
640201052Smarius		if (scp != cur_console)
641201052Smarius			scp->crt_base = scp->scr_buf;
642201052Smarius		set_mode(scp);
643201052Smarius		clear_screen(scp);
644201052Smarius		change_winsize(tp, scp->xsize, scp->ysize);
645201052Smarius		return 0;
646201052Smarius
647201052Smarius	case CONS_80x50TEXT:	/* set 80x50 text mode */
648201052Smarius		if (!crtc_vga)
649201052Smarius			return ENXIO;
650201052Smarius		/* is there a 8x8 font loaded ? */
651201052Smarius		if (fonts_loaded & FONT_8_LOADED) {
652201052Smarius			scp->mode = TEXT80x50;
653201052Smarius			scp->ysize = 50;
654201052Smarius			free(scp->scr_buf, M_DEVBUF);
655201052Smarius			scp->scr_buf =
656201052Smarius				(u_short *)malloc(scp->xsize * scp->ysize * 2,
657201052Smarius						  M_DEVBUF, M_NOWAIT);
658223960Smarius			if (scp != cur_console)
659201052Smarius				scp->crt_base = scp->scr_buf;
660201052Smarius			set_mode(scp);
661201052Smarius			clear_screen(scp);
662201052Smarius			change_winsize(tp, scp->xsize, scp->ysize);
663201052Smarius			return 0;
664201052Smarius		}
665201052Smarius		else
666201052Smarius			return EINVAL;
667201052Smarius
668201052Smarius	case CONS_GETVERS:	/* get version number */
669201052Smarius		*(int*)data = 0x103;	/* version 1.3 */
670201052Smarius		return 0;
671201052Smarius
672201052Smarius	case CONS_GETINFO:	/* get current (virtual) console info */
673201052Smarius		{
674201052Smarius			vid_info_t *ptr = (vid_info_t*)data;
675201052Smarius		if (ptr->size == sizeof(struct vid_info)) {
676201052Smarius			ptr->m_num = get_scr_num();
677201052Smarius			ptr->mv_col = scp->xpos;
678223960Smarius			ptr->mv_row = scp->ypos;
679223960Smarius			ptr->mv_csz = scp->xsize;
680223960Smarius			ptr->mv_rsz = scp->ysize;
681223960Smarius			ptr->mv_norm.fore = (scp->term.std_attr & 0x0f00)>>8;
682223960Smarius			ptr->mv_norm.back = (scp->term.std_attr & 0xf000)>>12;
683223960Smarius			ptr->mv_rev.fore = (scp->term.rev_attr & 0x0f00)>>8;
684223960Smarius			ptr->mv_rev.back = (scp->term.rev_attr & 0xf000)>>12;
685223960Smarius			ptr->mv_grfc.fore = 0;		/* not supported */
686223960Smarius			ptr->mv_grfc.back = 0;		/* not supported */
687201052Smarius			ptr->mv_ovscan = scp->border;
688201052Smarius			ptr->mk_keylock = scp->status & LOCK_KEY_MASK;
689201052Smarius			return 0;
690201052Smarius		}
691201052Smarius		return EINVAL;
692201052Smarius		}
693201052Smarius
694201052Smarius	case VT_SETMODE:	/* set screen switcher mode */
695201052Smarius		bcopy(data, &scp->smode, sizeof(struct vt_mode));
696201052Smarius		if (scp->smode.mode == VT_PROCESS) {
697201052Smarius			scp->proc = p;
698201052Smarius			scp->pid = scp->proc->p_pid;
699201052Smarius		}
700201052Smarius		return 0;
701201052Smarius
702201052Smarius	case VT_GETMODE:	/* get screen switcher mode */
703201052Smarius		bcopy(&scp->smode, data, sizeof(struct vt_mode));
704201052Smarius		return 0;
705201052Smarius
706201052Smarius	case VT_RELDISP:	/* screen switcher ioctl */
707201052Smarius		switch(*data) {
708201052Smarius		case VT_FALSE:	/* user refuses to release screen, abort */
709201052Smarius			if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
710292789Smarius				old_scp->status &= ~SWITCH_WAIT_REL;
711201052Smarius				switch_in_progress = 0;
712201052Smarius				return 0;
713201052Smarius			}
714201052Smarius			return EINVAL;
715292789Smarius
716233421Smarius		case VT_TRUE:	/* user has released screen, go on */
717201052Smarius			if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
718292789Smarius				scp->status &= ~SWITCH_WAIT_REL;
719225931Smarius				exchange_scr();
720292789Smarius				if (new_scp->smode.mode == VT_PROCESS) {
721292789Smarius					new_scp->status |= SWITCH_WAIT_ACQ;
722201052Smarius					psignal(new_scp->proc,
723292789Smarius						new_scp->smode.acqsig);
724292789Smarius				}
725201052Smarius				else
726201052Smarius					switch_in_progress = 0;
727201052Smarius				return 0;
728201052Smarius			}
729201052Smarius			return EINVAL;
730201052Smarius
731201052Smarius		case VT_ACKACQ:	/* acquire acknowledged, switch completed */
732201052Smarius			if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) {
733201052Smarius				scp->status &= ~SWITCH_WAIT_ACQ;
734201052Smarius				switch_in_progress = 0;
735201052Smarius				return 0;
736201052Smarius			}
737201052Smarius			return EINVAL;
738201052Smarius
739201052Smarius		default:
740201052Smarius			return EINVAL;
741201052Smarius		}
742201052Smarius		/* NOT REACHED */
743201052Smarius
744201052Smarius	case VT_OPENQRY:	/* return free virtual console */
745201052Smarius 		for (i = 0; i < NCONS; i++) {
746201052Smarius			tp = VIRTUAL_TTY(i);
747201052Smarius 			if (!(tp->t_state & TS_ISOPEN)) {
748201052Smarius 				*data = i + 1;
749201052Smarius 				return 0;
750201052Smarius 			}
751201052Smarius		}
752201052Smarius 		return EINVAL;
753201052Smarius
754201052Smarius	case VT_ACTIVATE:	/* switch to screen *data */
755201052Smarius		return switch_scr((*data) - 1);
756201052Smarius
757201052Smarius	case VT_WAITACTIVE:	/* wait for switch to occur */
758201052Smarius		if (*data > NCONS)
759201052Smarius			return EINVAL;
760201052Smarius		if (minor(dev) == (*data) - 1)
761201052Smarius			return 0;
762201052Smarius		if (*data == 0) {
763201052Smarius			if (scp == cur_console)
764201052Smarius				return 0;
765201052Smarius			while ((error=tsleep((caddr_t)&scp->smode,
766201052Smarius			    	PZERO|PCATCH, "waitvt", 0)) == ERESTART) ;
767201052Smarius		}
768201052Smarius		else
769201052Smarius			while ((error=tsleep(
770201052Smarius      				(caddr_t)&console[*(data-1)].smode,
771201052Smarius			    	PZERO|PCATCH, "waitvt", 0)) == ERESTART) ;
772201052Smarius		return error;
773216961Smarius
774201052Smarius	case VT_GETACTIVE:
775201052Smarius		*data = get_scr_num()+1;
776201052Smarius		return 0;
777201052Smarius
778201052Smarius	case KDENABIO:		/* allow io operations */
779201052Smarius	 	fp = (struct trapframe *)p->p_md.md_regs;
780201052Smarius	 	fp->tf_eflags |= PSL_IOPL;
781201052Smarius		return 0;
782201052Smarius
783201052Smarius	case KDDISABIO:		/* disallow io operations (default) */
784201052Smarius	 	fp = (struct trapframe *)p->p_md.md_regs;
785201052Smarius	 	fp->tf_eflags &= ~PSL_IOPL;
786201052Smarius	 	return 0;
787201052Smarius
788201052Smarius        case KDSETMODE:		/* set current mode of this (virtual) console */
789203094Smarius		switch (*data) {
790201052Smarius		case KD_TEXT:	/* switch to TEXT (known) mode */
791201052Smarius				/* restore fonts & palette ! */
792201052Smarius			if (crtc_vga) {
793201052Smarius				copy_font(LOAD, 0, 16, font_16);
794201052Smarius				copy_font(LOAD, 1, 8, font_8);
795201052Smarius				copy_font(LOAD, 2, 14, font_14);
796201052Smarius				load_palette();
797201052Smarius			}
798201052Smarius			/* FALL THROUGH */
799201052Smarius
800201052Smarius		case KD_TEXT1:	/* switch to TEXT (known) mode */
801201052Smarius				/* no restore fonts & palette */
802201052Smarius			scp->status &= ~UNKNOWN_MODE;
803201052Smarius			set_mode(scp);
804201052Smarius			clear_screen(scp);
805201052Smarius			return 0;
806201052Smarius
807201052Smarius		case KD_GRAPHICS:/* switch to GRAPHICS (unknown) mode */
808201052Smarius			scp->status |= UNKNOWN_MODE;
809201052Smarius			return 0;
810201052Smarius		default:
811201052Smarius			return EINVAL;
812201052Smarius		}
813201052Smarius		/* NOT REACHED */
814201052Smarius
815201052Smarius	case KDGETMODE:		/* get current mode of this (virtual) console */
816201052Smarius		*data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT;
817201052Smarius		return 0;
818201052Smarius
819201052Smarius	case KDSBORDER:		/* set border color of this (virtual) console */
820201052Smarius		if (!crtc_vga)
821201052Smarius			return ENXIO;
822201052Smarius		scp->border = *data;
823201052Smarius		if (scp == cur_console)
824201052Smarius			set_border(scp->border);
825201052Smarius		return 0;
826201052Smarius
827201052Smarius	case KDSKBSTATE:	/* set keyboard state (locks) */
828201052Smarius		if (*data >= 0 && *data <= LOCK_KEY_MASK) {
829201052Smarius			scp->status &= ~LOCK_KEY_MASK;
830201052Smarius			scp->status |= *data;
831201052Smarius			if (scp == cur_console)
832201052Smarius				update_leds(scp->status);
833201052Smarius			return 0;
834201052Smarius		}
835201052Smarius		return EINVAL;
836201052Smarius
837201052Smarius	case KDGKBSTATE:	/* get keyboard state (locks) */
838201052Smarius		*data = scp->status & LOCK_KEY_MASK;
839201052Smarius		return 0;
840201052Smarius
841201052Smarius	case KDSETRAD:		/* set keyboard repeat & delay rates */
842201052Smarius		if (*data & 0x80)
843201052Smarius			return EINVAL;
844201052Smarius		i = spltty();
845201052Smarius		kbd_cmd(KB_SETRAD);
846201052Smarius		kbd_cmd(*data);
847201052Smarius		splx(i);
848201052Smarius		return 0;
849201052Smarius
850201052Smarius	case KDSKBMODE:		/* set keyboard mode */
851201052Smarius		switch (*data) {
852201052Smarius		case K_RAW:	/* switch to RAW scancode mode */
853201052Smarius			scp->status |= KBD_RAW_MODE;
854201052Smarius			return 0;
855201052Smarius
856201052Smarius		case K_XLATE:	/* switch to XLT ascii mode */
857201052Smarius			if (scp == cur_console && scp->status == KBD_RAW_MODE)
858201052Smarius				shfts = ctls = alts = agrs = metas = 0;
859201052Smarius			scp->status &= ~KBD_RAW_MODE;
860201052Smarius			return 0;
861201052Smarius		default:
862201052Smarius			return EINVAL;
863201052Smarius		}
864201052Smarius		/* NOT REACHED */
865201052Smarius
866201052Smarius	case KDGKBMODE:		/* get keyboard mode */
867201052Smarius		*data = (scp->status & KBD_RAW_MODE) ? K_RAW : K_XLATE;
868201052Smarius		return 0;
869201052Smarius
870201052Smarius	case KDMKTONE:		/* sound the bell */
871201052Smarius		if (scp == cur_console)
872201052Smarius			sysbeep(scp->bell_pitch, scp->bell_duration);
873201052Smarius		return 0;
874201052Smarius
875201052Smarius	case KIOCSOUND:		/* make tone (*data) hz */
876201052Smarius		if (scp == cur_console) {
877201052Smarius			if (*(int*)data) {
878201052Smarius			int pitch = TIMER_FREQ/(*(int*)data);
879201052Smarius				/* set command for counter 2, 2 byte write */
880201052Smarius				if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) {
881201052Smarius					return EBUSY;
882201052Smarius				}
883201052Smarius				/* set pitch */
884201052Smarius				outb(TIMER_CNTR2, pitch);
885201052Smarius				outb(TIMER_CNTR2, (pitch>>8));
886201052Smarius				/* enable counter 2 output to speaker */
887201052Smarius				outb(IO_PPI, inb(IO_PPI) | 3);
888201052Smarius			}
889201052Smarius			else {
890201052Smarius				/* disable counter 2 output to speaker */
891201052Smarius				outb(IO_PPI, inb(IO_PPI) & 0xFC);
892201052Smarius				release_timer2();
893201052Smarius			}
894201052Smarius		}
895201052Smarius		return 0;
896201052Smarius
897201052Smarius	case KDGKBTYPE:		/* get keyboard type */
898201052Smarius		*data = 0;	/* type not known (yet) */
899201052Smarius		return 0;
900201052Smarius
901201052Smarius	case KDSETLED:		/* set keyboard LED status */
902201052Smarius		if (*data >= 0 && *data <= LED_MASK) {
903201052Smarius			scp->status &= ~LED_MASK;
904201052Smarius			scp->status |= *data;
905201052Smarius			if (scp == cur_console)
906201052Smarius				update_leds(scp->status);
907201052Smarius			return 0;
908201052Smarius		}
909201052Smarius		return EINVAL;
910201052Smarius
911201052Smarius	case KDGETLED:		/* get keyboard LED status */
912201052Smarius		*data = scp->status & LED_MASK;
913201052Smarius		return 0;
914201052Smarius
915201052Smarius	case GETFKEY:		/* get functionkey string */
916201052Smarius		if (*(u_short*)data < n_fkey_tab) {
917201052Smarius		 	fkeyarg_t *ptr = (fkeyarg_t*)data;
918201052Smarius			bcopy(&fkey_tab[ptr->keynum].str,
919201052Smarius			      ptr->keydef,
920201052Smarius			      fkey_tab[ptr->keynum].len);
921201052Smarius			ptr->flen = fkey_tab[ptr->keynum].len;
922201052Smarius			return 0;
923201052Smarius		}
924201052Smarius		else
925201052Smarius			return EINVAL;
926201052Smarius
927201052Smarius	case SETFKEY:		/* set functionkey string */
928201052Smarius		if (*(u_short*)data < n_fkey_tab) {
929201052Smarius		 	fkeyarg_t *ptr = (fkeyarg_t*)data;
930201052Smarius			bcopy(ptr->keydef,
931201052Smarius			      &fkey_tab[ptr->keynum].str,
932201052Smarius			      min(ptr->flen, MAXFK));
933201052Smarius			fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK);
934201052Smarius			return 0;
935201052Smarius		}
936201052Smarius		else
937201052Smarius			return EINVAL;
938201052Smarius
939201052Smarius	case GIO_SCRNMAP: 	/* get output translation table */
940201052Smarius		bcopy(&scr_map, data, sizeof(scr_map));
941201052Smarius		return 0;
942201052Smarius
943201052Smarius	case PIO_SCRNMAP:	/* set output translation table */
944201052Smarius		bcopy(data, &scr_map, sizeof(scr_map));
945201052Smarius		return 0;
946201052Smarius
947201052Smarius	case GIO_KEYMAP: 	/* get keyboard translation table */
948201052Smarius		bcopy(&key_map, data, sizeof(key_map));
949201052Smarius		return 0;
950201052Smarius
951201052Smarius	case PIO_KEYMAP:	/* set keyboard translation table */
952201052Smarius		bcopy(data, &key_map, sizeof(key_map));
953201052Smarius		return 0;
954201052Smarius
955201052Smarius	case PIO_FONT8x8:	/* set 8x8 dot font */
956201052Smarius		if (!crtc_vga)
957201052Smarius			return ENXIO;
958201052Smarius		bcopy(data, font_8, 8*256);
959201052Smarius		fonts_loaded |= FONT_8_LOADED;
960201052Smarius		copy_font(LOAD, 1, 8, font_8);
961201052Smarius		return 0;
962201052Smarius
963201052Smarius	case GIO_FONT8x8:	/* get 8x8 dot font */
964201052Smarius		if (!crtc_vga)
965201052Smarius			return ENXIO;
966201052Smarius		if (fonts_loaded & FONT_8_LOADED) {
967201052Smarius			bcopy(font_8, data, 8*256);
968201052Smarius			return 0;
969201052Smarius		}
970201052Smarius		else
971201052Smarius			return ENXIO;
972201052Smarius
973201052Smarius	case PIO_FONT8x14:	/* set 8x14 dot font */
974201052Smarius		if (!crtc_vga)
975201052Smarius			return ENXIO;
976201052Smarius		bcopy(data, font_14, 14*256);
977201052Smarius		fonts_loaded |= FONT_14_LOADED;
978201052Smarius		copy_font(LOAD, 2, 14, font_14);
979201052Smarius		return 0;
980201052Smarius
981201052Smarius	case GIO_FONT8x14:	/* get 8x14 dot font */
982201052Smarius		if (!crtc_vga)
983201052Smarius			return ENXIO;
984201052Smarius		if (fonts_loaded & FONT_14_LOADED) {
985201052Smarius			bcopy(font_14, data, 14*256);
986201052Smarius			return 0;
987201052Smarius		}
988201052Smarius		else
989201052Smarius			return ENXIO;
990201052Smarius
991201052Smarius	case PIO_FONT8x16:	/* set 8x16 dot font */
992201052Smarius		if (!crtc_vga)
993201052Smarius			return ENXIO;
994201052Smarius		bcopy(data, font_16, 16*256);
995201052Smarius		fonts_loaded |= FONT_16_LOADED;
996201052Smarius		copy_font(LOAD, 0, 16, font_16);
997201052Smarius		return 0;
998201052Smarius
999201052Smarius	case GIO_FONT8x16:	/* get 8x16 dot font */
1000201052Smarius		if (!crtc_vga)
1001201052Smarius			return ENXIO;
1002201052Smarius		if (fonts_loaded & FONT_16_LOADED) {
1003201052Smarius			bcopy(font_16, data, 16*256);
1004201052Smarius			return 0;
1005201052Smarius		}
1006201052Smarius		else
1007201052Smarius			return ENXIO;
1008201052Smarius
1009201052Smarius	case CONSOLE_X_MODE_ON:	/* just to be compatible */
1010201052Smarius		if (saved_console < 0) {
1011201052Smarius			saved_console = get_scr_num();
1012201052Smarius			switch_scr(minor(dev));
1013201052Smarius	 		fp = (struct trapframe *)p->p_md.md_regs;
1014201052Smarius	 		fp->tf_eflags |= PSL_IOPL;
1015201052Smarius			scp->status |= UNKNOWN_MODE;
1016201052Smarius			scp->status |= KBD_RAW_MODE;
1017201052Smarius			return 0;
1018201052Smarius		}
1019201052Smarius		return EAGAIN;
1020201052Smarius
1021201052Smarius	case CONSOLE_X_MODE_OFF:/* just to be compatible */
1022201052Smarius	 	fp = (struct trapframe *)p->p_md.md_regs;
1023201052Smarius	 	fp->tf_eflags &= ~PSL_IOPL;
1024201052Smarius		if (crtc_vga) {
1025201052Smarius			copy_font(LOAD, 0, 16, font_16);
1026201052Smarius			copy_font(LOAD, 1, 8, font_8);
1027201052Smarius			copy_font(LOAD, 2, 14, font_14);
1028201052Smarius			load_palette();
1029201052Smarius		}
1030201052Smarius		scp->status &= ~UNKNOWN_MODE;
1031201052Smarius		set_mode(scp);
1032201052Smarius		clear_screen(scp);
1033201052Smarius		scp->status &= ~KBD_RAW_MODE;
1034201052Smarius		switch_scr(saved_console);
1035201052Smarius		saved_console = -1;
1036201052Smarius		return 0;
1037201052Smarius
1038201052Smarius	 case CONSOLE_X_BELL:	/* more compatibility */
1039201052Smarius                /*
1040201052Smarius                 * if set, data is a pointer to a length 2 array of
1041201052Smarius                 * integers. data[0] is the pitch in Hz and data[1]
1042201052Smarius                 * is the duration in msec.
1043201052Smarius                 */
1044201052Smarius                if (data)
1045201052Smarius	    		sysbeep(TIMER_FREQ/((int*)data)[0],
1046201052Smarius				((int*)data)[1]*hz/1000);
1047201052Smarius                else
1048201052Smarius			sysbeep(scp->bell_pitch, scp->bell_duration);
1049201052Smarius                return 0;
1050201052Smarius
1051201052Smarius	default:
1052201052Smarius		break;
1053201052Smarius	}
1054201052Smarius
1055201052Smarius	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1056201052Smarius	if (error >= 0)
1057201052Smarius		return(error);
1058201052Smarius	error = ttioctl(tp, cmd, data, flag);
1059201052Smarius	if (error >= 0)
1060201052Smarius		return(error);
1061201052Smarius	return(ENOTTY);
1062201052Smarius}
1063201052Smarius
1064201052Smarius
1065201052Smariusvoid
1066201052Smariuspcxint(dev_t dev)
1067201052Smarius{
1068201052Smarius	struct tty *tp = get_tty_ptr(dev);
1069201052Smarius
1070201052Smarius	if (!tp)
1071201052Smarius		return;
1072201052Smarius	tp->t_state &= ~TS_BUSY;
1073201052Smarius	if (tp->t_line)
1074201052Smarius		(*linesw[tp->t_line].l_start)(tp);
1075201052Smarius	else
1076201052Smarius		pcstart(tp);
1077201052Smarius}
1078201052Smarius
1079201052Smarius
1080201052Smariusvoid
1081201052Smariuspcstart(struct tty *tp)
1082201052Smarius{
1083201052Smarius	struct clist *rbp;
1084201052Smarius	int i, s, len;
1085201052Smarius	u_char buf[PCBURST];
1086201052Smarius	scr_stat *scp = get_scr_stat(tp->t_dev);
1087201052Smarius
1088201052Smarius	if (scp->status & SLKED)
1089201052Smarius		return;
1090201052Smarius	s = spltty();
1091201052Smarius	if (!(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) {
1092201052Smarius		tp->t_state |= TS_BUSY;
1093201052Smarius		splx(s);
1094201052Smarius		rbp = &tp->t_outq;
1095201052Smarius		while (rbp->c_cc) {
1096201052Smarius			len = q_to_b(rbp, buf, PCBURST);
1097201052Smarius			for (i=0; i<len; i++)
1098201052Smarius				if (buf[i]) ansi_put(scp, buf[i]);
1099201052Smarius		}
1100201052Smarius		s = spltty();
1101201052Smarius		tp->t_state &= ~TS_BUSY;
1102201052Smarius#if 0
1103201052Smarius		if (rbp->c_cc) {
1104201052Smarius			tp->t_state |= TS_TIMEOUT;
1105201052Smarius			timeout((timeout_t)ttrstrt, (caddr_t)tp, 1);
1106201052Smarius		}
1107201052Smarius#endif
1108201052Smarius		if (rbp->c_cc <= tp->t_lowat) {
1109201052Smarius			if (tp->t_state & TS_ASLEEP) {
1110201052Smarius				tp->t_state &= ~TS_ASLEEP;
1111201052Smarius				wakeup((caddr_t)rbp);
1112201052Smarius			}
1113201052Smarius			selwakeup(&tp->t_wsel);
1114201052Smarius		}
1115201052Smarius	}
1116201052Smarius	splx(s);
1117201052Smarius}
1118201052Smarius
1119201052Smarius
1120201052Smariusvoid
1121201052Smariuspccnprobe(struct consdev *cp)
1122201052Smarius{
1123201052Smarius	int maj;
1124201052Smarius
1125201052Smarius	/* locate the major number */
1126201052Smarius	for (maj = 0; maj < nchrdev; maj++)
1127201052Smarius		if ((void*)cdevsw[maj].d_open == (void*)pcopen)
1128201052Smarius			break;
1129201052Smarius
1130201052Smarius	/* initialize required fields */
1131201052Smarius	cp->cn_dev = makedev(maj, NCONS);
1132201052Smarius	cp->cn_pri = CN_INTERNAL;
1133201052Smarius}
1134201052Smarius
1135201052Smarius
1136201052Smariusvoid
1137201052Smariuspccninit(struct consdev *cp)
1138201052Smarius{
1139201052Smarius	scinit();
1140201052Smarius}
1141201052Smarius
1142201052Smarius
1143201052Smariusvoid
1144201052Smariuspccnputc(dev_t dev, char c)
1145201052Smarius{
1146201052Smarius	if (c == '\n')
1147201052Smarius		scput('\r');
1148201052Smarius	scput(c);
1149201052Smarius	if (cur_console == &console[0]) {
1150201052Smarius	int 	pos = cur_console->crtat - cur_console->crt_base;
1151201052Smarius		if (pos != cur_cursor_pos) {
1152201052Smarius			cur_cursor_pos = pos;
1153201052Smarius			outb(crtc_addr,14);
1154201052Smarius			outb(crtc_addr+1,pos >> 8);
1155201052Smarius			outb(crtc_addr,15);
1156201052Smarius			outb(crtc_addr+1,pos&0xff);
1157201052Smarius		}
1158201052Smarius	}
1159201052Smarius}
1160201052Smarius
1161201052Smarius
1162201052Smariusint
1163201052Smariuspccngetc(dev_t dev)
1164201052Smarius{
1165201052Smarius	int s = spltty();		/* block scintr while we poll */
1166201052Smarius	int c = scgetc(0);
1167201052Smarius	splx(s);
1168201052Smarius	if (c == '\r') c = '\n';
1169201052Smarius	return(c);
1170201052Smarius}
1171201052Smarius
1172201052Smarius
1173201052Smariusstatic void
1174201052Smariusnone_saver(int test)
1175201052Smarius{
1176201052Smarius}
1177201052Smarius
1178201052Smarius
1179201052Smariusstatic void
1180201052Smariusfade_saver(int test)
1181201052Smarius{
1182201052Smarius	static int count = 0;
1183201052Smarius	int i;
1184201052Smarius
1185201052Smarius	if (test) {
1186201052Smarius		scrn_blanked = 1;
1187201052Smarius		if (count < 64) {
1188201052Smarius  			outb(PIXMASK, 0xFF);		/* no pixelmask */
1189201052Smarius  			outb(PALWADR, 0x00);
1190201052Smarius    			outb(PALDATA, 0);
1191201052Smarius    			outb(PALDATA, 0);
1192201052Smarius    			outb(PALDATA, 0);
1193201052Smarius  			for (i = 3; i < 768; i++) {
1194201052Smarius  				if (palette[i] - count > 15)
1195201052Smarius    					outb(PALDATA, palette[i]-count);
1196201052Smarius				else
1197201052Smarius    					outb(PALDATA, 15);
1198201052Smarius			}
1199201052Smarius			inb(crtc_addr+6);		/* reset flip/flop */
1200201052Smarius			outb(ATC, 0x20);		/* enable palette */
1201201052Smarius			count++;
1202201052Smarius		}
1203201052Smarius	}
1204201052Smarius	else {
1205201052Smarius		count = scrn_blanked = 0;
1206201052Smarius		load_palette();
1207201052Smarius	}
1208201052Smarius}
1209201052Smarius
1210201052Smarius
1211201052Smariusstatic void
1212201052Smariusblank_saver(int test)
1213201052Smarius{
1214201052Smarius	u_char val;
1215201052Smarius	if (test) {
1216201052Smarius		scrn_blanked = 1;
1217201052Smarius  		outb(TSIDX, 0x01); val = inb(TSREG);
1218201052Smarius		outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1219201052Smarius	}
1220201052Smarius	else {
1221201052Smarius		scrn_blanked = 0;
1222201052Smarius  		outb(TSIDX, 0x01); val = inb(TSREG);
1223201052Smarius		outb(TSIDX, 0x01); outb(TSREG, val & 0xDF);
1224201052Smarius	}
1225201052Smarius}
1226201052Smarius
1227201052Smarius#define NUM_STARS	50
1228201052Smarius
1229201052Smarius/*
1230201052Smarius * Alternate saver that got its inspiration from a well known utility
1231201052Smarius * package for an inferior^H^H^H^H^H^Hfamous OS.
1232201052Smarius */
1233201052Smariusstatic void
1234201052Smariusstar_saver(int test)
1235201052Smarius{
1236201052Smarius	scr_stat	*scp = cur_console;
1237201052Smarius	int		cell, i;
1238201052Smarius	char 		pattern[] = {"...........++++***   "};
1239201052Smarius	char		colors[] = {FG_DARKGREY, FG_LIGHTGREY,
1240201052Smarius				    FG_WHITE, FG_LIGHTCYAN};
1241201052Smarius	static u_short 	stars[NUM_STARS][2];
1242201052Smarius
1243201052Smarius	if (test) {
1244201052Smarius		if (!scrn_blanked) {
1245201052Smarius			bcopy(Crtat, scp->scr_buf,
1246201052Smarius			      scp->xsize * scp->ysize * 2);
1247201052Smarius			fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], Crtat,
1248201052Smarius			      scp->xsize * scp->ysize);
1249201052Smarius			set_border(0);
1250201052Smarius			i = scp->ysize * scp->xsize + 5;
1251201052Smarius			outb(crtc_addr, 14);
1252201052Smarius			outb(crtc_addr+1, i >> 8);
1253201052Smarius			outb(crtc_addr, 15);
1254201052Smarius			outb(crtc_addr+1, i & 0xff);
1255201052Smarius			scrn_blanked = 1;
1256201052Smarius 			for(i=0; i<NUM_STARS; i++) {
1257201052Smarius  				stars[i][0] =
1258201052Smarius					random() % (scp->xsize*scp->ysize);
1259201052Smarius  				stars[i][1] = 0;
1260201052Smarius 			}
1261201052Smarius		}
1262201052Smarius   		cell = random() % NUM_STARS;
1263201052Smarius		*((u_short*)(Crtat + stars[cell][0])) =
1264201052Smarius			scr_map[pattern[stars[cell][1]]] |
1265201052Smarius			        colors[random()%sizeof(colors)] << 8;
1266201052Smarius		if ((stars[cell][1]+=(random()%4)) >= sizeof(pattern)-1) {
1267201052Smarius    			stars[cell][0] = random() % (scp->xsize*scp->ysize);
1268201052Smarius   			stars[cell][1] = 0;
1269201052Smarius		}
1270201052Smarius	}
1271201052Smarius	else {
1272201052Smarius		if (scrn_blanked) {
1273201052Smarius			bcopy(scp->scr_buf, Crtat, scp->xsize*scp->ysize*2);
1274201052Smarius			cur_cursor_pos = -1;
1275201052Smarius			set_border(scp->border);
1276201052Smarius			scrn_blanked = 0;
1277201052Smarius		}
1278201052Smarius	}
1279201052Smarius}
1280201052Smarius
1281201052Smarius
1282201052Smariusstatic void
1283201052Smariussnake_saver(int test)
1284201052Smarius{
1285201052Smarius	const char	saves[] = {"FreeBSD-2.0"};
1286201052Smarius	static u_char	*savs[sizeof(saves)-1];
1287201052Smarius	static int	dirx, diry;
1288201052Smarius	int		f;
1289201052Smarius	scr_stat	*scp = cur_console;
1290201052Smarius
1291201052Smarius	if (test) {
1292201052Smarius		if (!scrn_blanked) {
1293201052Smarius			bcopy(Crtat, scp->scr_buf,
1294201052Smarius			      scp->xsize * scp->ysize * 2);
1295201052Smarius			fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20],
1296201052Smarius			      Crtat, scp->xsize * scp->ysize);
1297201052Smarius			set_border(0);
1298201052Smarius			dirx = (scp->xpos ? 1 : -1);
1299201052Smarius			diry = (scp->ypos ?
1300201052Smarius				scp->xsize : -scp->xsize);
1301201052Smarius			for (f=0; f< sizeof(saves)-1; f++)
1302201052Smarius				savs[f] = (u_char *)Crtat + 2 *
1303201052Smarius					  (scp->xpos+scp->ypos*scp->xsize);
1304201052Smarius			*(savs[0]) = scr_map[*saves];
1305201052Smarius			f = scp->ysize * scp->xsize + 5;
1306201052Smarius			outb(crtc_addr, 14);
1307201052Smarius			outb(crtc_addr+1, f >> 8);
1308201052Smarius			outb(crtc_addr, 15);
1309201052Smarius			outb(crtc_addr+1, f & 0xff);
1310201052Smarius			scrn_blanked = 1;
1311201052Smarius		}
1312201052Smarius		if (scrn_blanked++ < 4)
1313201052Smarius			return;
1314201052Smarius		scrn_blanked = 1;
1315201052Smarius		*(savs[sizeof(saves)-2]) = scr_map[0x20];
1316201052Smarius		for (f=sizeof(saves)-2; f > 0; f--)
1317201052Smarius			savs[f] = savs[f-1];
1318201052Smarius		f = (savs[0] - (u_char *)Crtat) / 2;
1319201052Smarius		if ((f % scp->xsize) == 0 ||
1320201052Smarius		    (f % scp->xsize) == scp->xsize - 1 ||
1321201052Smarius		    (random() % 50) == 0)
1322201052Smarius			dirx = -dirx;
1323201052Smarius		if ((f / scp->xsize) == 0 ||
1324201052Smarius		    (f / scp->xsize) == scp->ysize - 1 ||
1325201052Smarius		    (random() % 20) == 0)
1326201052Smarius			diry = -diry;
1327201052Smarius		savs[0] += 2*dirx + 2*diry;
1328292789Smarius		for (f=sizeof(saves)-2; f>=0; f--)
1329292789Smarius			*(savs[f]) = scr_map[saves[f]];
1330201052Smarius	}
1331201052Smarius	else {
1332201052Smarius		if (scrn_blanked) {
1333201052Smarius			bcopy(scp->scr_buf, Crtat,
1334201052Smarius			      scp->xsize * scp->ysize * 2);
1335201052Smarius			cur_cursor_pos = -1;
1336201052Smarius			set_border(scp->border);
1337292789Smarius			scrn_blanked = 0;
1338292789Smarius		}
1339201052Smarius	}
1340201052Smarius}
1341201052Smarius
1342201052Smarius
1343201052Smariusstatic void
1344292789Smariuscursor_shape(int start, int end)
1345201052Smarius{
1346292789Smarius	outb(crtc_addr, 10);
1347292789Smarius	outb(crtc_addr+1, start & 0xFF);
1348292789Smarius	outb(crtc_addr, 11);
1349292789Smarius	outb(crtc_addr+1, end & 0xFF);
1350292789Smarius}
1351292789Smarius
1352201052Smarius
1353201052Smarius#if !defined(FAT_CURSOR)
1354201052Smariusstatic void
1355201052Smariusget_cursor_shape(int *start, int *end)
1356201052Smarius{
1357201052Smarius	outb(crtc_addr, 10);
1358201052Smarius	*start = inb(crtc_addr+1) & 0x1F;
1359219785Smarius	outb(crtc_addr, 11);
1360201052Smarius	*end = inb(crtc_addr+1) & 0x1F;
1361201052Smarius}
1362292789Smarius#endif
1363292789Smarius
1364292789Smarius
1365219785Smariusstatic void
1366201052Smariuscursor_pos(int force)
1367201052Smarius{
1368201052Smarius	int pos;
1369201052Smarius
1370201052Smarius	if (cur_console->status & UNKNOWN_MODE)
1371201052Smarius		return;
1372201052Smarius	if (scrn_blank_time && (time.tv_sec > scrn_time_stamp+scrn_blank_time))
1373201052Smarius		SCRN_SAVER(1);
1374201052Smarius	pos = cur_console->crtat - cur_console->crt_base;
1375201052Smarius	if (force || (!scrn_blanked && pos != cur_cursor_pos)) {
1376201052Smarius		cur_cursor_pos = pos;
1377201052Smarius		outb(crtc_addr, 14);
1378201052Smarius		outb(crtc_addr+1, pos>>8);
1379201052Smarius		outb(crtc_addr, 15);
1380201052Smarius		outb(crtc_addr+1, pos&0xff);
1381201052Smarius	}
1382201052Smarius	timeout((timeout_t)cursor_pos, 0, hz/20);
1383201052Smarius}
1384201052Smarius
1385201052Smarius
1386201052Smariusstatic void
1387201052Smariusclear_screen(scr_stat *scp)
1388201052Smarius{
1389201052Smarius	move_crsr(scp, 0, 0);
1390201052Smarius	fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base,
1391201052Smarius	       scp->xsize * scp->ysize);
1392201052Smarius}
1393201052Smarius
1394201052Smarius
1395201052Smariusstatic int
1396201052Smariusswitch_scr(u_int next_scr)
1397201052Smarius{
1398201052Smarius	if (switch_in_progress &&
1399201052Smarius	    (cur_console->proc != pfind(cur_console->pid)))
1400201052Smarius		switch_in_progress = 0;
1401201052Smarius
1402201052Smarius    	if (next_scr >= NCONS || switch_in_progress) {
1403201052Smarius		sysbeep(BELL_PITCH, BELL_DURATION);
1404201052Smarius		return EINVAL;
1405201052Smarius	}
1406201052Smarius
1407201052Smarius	/* is the wanted virtual console open ? */
1408201052Smarius	if (next_scr) {
1409201052Smarius		struct tty *tp = VIRTUAL_TTY(next_scr);
1410201052Smarius		if (!(tp->t_state & TS_ISOPEN)) {
1411201052Smarius			sysbeep(BELL_PITCH, BELL_DURATION);
1412201052Smarius			return EINVAL;
1413201052Smarius		}
1414201052Smarius	}
1415201052Smarius	if (in_putc) {		/* delay switch if in putc */
1416201052Smarius		delayed_next_scr = next_scr+1;
1417201052Smarius		return 0;
1418201052Smarius	}
1419201052Smarius	switch_in_progress = 1;
1420201052Smarius	old_scp = cur_console;
1421201052Smarius	new_scp = &console[next_scr];
1422201052Smarius	wakeup((caddr_t)&new_scp->smode);
1423201052Smarius	if (new_scp == old_scp) {
1424201052Smarius		switch_in_progress = 0;
1425201052Smarius		return 0;
1426201052Smarius	}
1427201052Smarius
1428201052Smarius	/* has controlling process died? */
1429201052Smarius	if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid)))
1430201052Smarius		old_scp->smode.mode = VT_AUTO;
1431201052Smarius	if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid)))
1432201052Smarius		new_scp->smode.mode = VT_AUTO;
1433201052Smarius
1434201052Smarius	/* check the modes and switch approbiatly */
1435201052Smarius	if (old_scp->smode.mode == VT_PROCESS) {
1436201052Smarius		old_scp->status |= SWITCH_WAIT_REL;
1437201052Smarius		psignal(old_scp->proc, old_scp->smode.relsig);
1438201052Smarius	}
1439201052Smarius	else {
1440201052Smarius		exchange_scr();
1441201052Smarius		if (new_scp->smode.mode == VT_PROCESS) {
1442201052Smarius			new_scp->status |= SWITCH_WAIT_ACQ;
1443201052Smarius			psignal(new_scp->proc, new_scp->smode.acqsig);
1444201052Smarius		}
1445201052Smarius		else
1446201052Smarius			switch_in_progress = 0;
1447201052Smarius	}
1448201052Smarius	return 0;
1449201052Smarius}
1450201052Smarius
1451201052Smarius
1452201052Smariusstatic void
1453201052Smariusexchange_scr(void)
1454201052Smarius{
1455201052Smarius	struct tty *tp;
1456201052Smarius
1457201052Smarius	bcopy(Crtat, old_scp->scr_buf, old_scp->xsize * old_scp->ysize * 2);
1458201052Smarius	old_scp->crt_base = old_scp->scr_buf;
1459201052Smarius	move_crsr(old_scp, old_scp->xpos, old_scp->ypos);
1460201052Smarius	cur_console = new_scp;
1461201052Smarius	set_mode(new_scp);
1462201052Smarius	new_scp->crt_base = Crtat;
1463201052Smarius	move_crsr(new_scp, new_scp->xpos, new_scp->ypos);
1464201052Smarius	bcopy(new_scp->scr_buf, Crtat, new_scp->xsize * new_scp->ysize * 2);
1465201052Smarius	update_leds(new_scp->status);
1466201052Smarius	if ((old_scp->status & UNKNOWN_MODE) && crtc_vga) {
1467202003Smarius		copy_font(LOAD, 0, 16, font_16);
1468201052Smarius		copy_font(LOAD, 1, 8, font_8);
1469201052Smarius		copy_font(LOAD, 2, 14, font_14);
1470201052Smarius		load_palette();
1471201052Smarius	}
1472201052Smarius	if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE)
1473201052Smarius		shfts = ctls = alts = agrs = metas = 0;
1474201052Smarius	delayed_next_scr = 0;
1475201052Smarius}
1476201052Smarius
1477201052Smarius
1478201052Smariusstatic void
1479201052Smariusmove_crsr(scr_stat *scp, int x, int y)
1480201052Smarius{
1481201052Smarius	if (x < 0 || y < 0 || x >= scp->xsize || y >= scp->ysize)
1482201052Smarius		return;
1483201052Smarius	scp->xpos = x;
1484201052Smarius	scp->ypos = y;
1485201052Smarius	scp->crtat = scp->crt_base + scp->ypos * scp->xsize + scp->xpos;
1486201052Smarius}
1487201052Smarius
1488201052Smarius
1489201052Smariusstatic void
1490201052Smariusmove_up(u_short *s, u_short *d, u_int len)
1491201052Smarius{
1492201052Smarius	s += len;
1493202003Smarius	d += len;
1494202003Smarius	while (len-- > 0)
1495201052Smarius		*--d = *--s;
1496201052Smarius}
1497202003Smarius
1498201052Smarius
1499201052Smariusstatic void
1500201052Smariusmove_down(u_short *s, u_short *d, u_int len)
1501201052Smarius{
1502201052Smarius	while (len-- > 0)
1503201052Smarius		*d++ = *s++;
1504201052Smarius}
1505201052Smarius
1506201052Smarius
1507201052Smariusstatic void
1508201052Smariusscan_esc(scr_stat *scp, u_char c)
1509201052Smarius{
1510201052Smarius	static u_char ansi_col[16] =
1511201052Smarius		{0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15};
1512201052Smarius	int i, n;
1513201052Smarius	u_short *src, *dst, count;
1514201052Smarius
1515201052Smarius	if (scp->term.esc == 1) {
1516201052Smarius		switch (c) {
1517201052Smarius
1518201052Smarius		case '[': 	/* Start ESC [ sequence */
1519201052Smarius			scp->term.esc = 2;
1520201052Smarius			scp->term.last_param = -1;
1521201052Smarius			for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
1522201052Smarius				scp->term.param[i] = 1;
1523201052Smarius			scp->term.num_param = 0;
1524201052Smarius			return;
1525201052Smarius
1526201052Smarius		case 'M':	/* Move cursor up 1 line, scroll if at top */
1527201052Smarius			if (scp->ypos > 0)
1528201052Smarius				move_crsr(scp, scp->xpos, scp->ypos - 1);
1529201052Smarius			else {
1530201052Smarius				move_up(scp->crt_base,
1531201052Smarius					scp->crt_base + scp->xsize,
1532201052Smarius					(scp->ysize - 1) * scp->xsize);
1533262621Sdim				fillw(scp->term.cur_attr | scr_map[0x20],
1534201052Smarius				      scp->crt_base, scp->xsize);
1535201052Smarius			}
1536201052Smarius			break;
1537201052Smarius#if notyet
1538201052Smarius		case 'Q':
1539201052Smarius			scp->term.esc = 4;
1540201052Smarius			break;
1541201052Smarius#endif
1542201052Smarius		case 'c':	/* Clear screen & home */
1543201052Smarius			clear_screen(scp);
1544201052Smarius			break;
1545201052Smarius		}
1546201052Smarius	}
1547201052Smarius	else if (scp->term.esc == 2) {
1548201052Smarius		if (c >= '0' && c <= '9') {
1549201052Smarius			if (scp->term.num_param < MAX_ESC_PAR) {
1550201052Smarius				if (scp->term.last_param != scp->term.num_param) {
1551201052Smarius					scp->term.last_param = scp->term.num_param;
1552201052Smarius					scp->term.param[scp->term.num_param] = 0;
1553201052Smarius				}
1554201052Smarius				else
1555201052Smarius					scp->term.param[scp->term.num_param] *= 10;
1556201052Smarius				scp->term.param[scp->term.num_param] += c - '0';
1557201052Smarius				return;
1558201052Smarius			}
1559201052Smarius		}
1560201052Smarius		scp->term.num_param = scp->term.last_param + 1;
1561201052Smarius		switch (c) {
1562201052Smarius
1563201052Smarius		case ';':
1564201052Smarius			if (scp->term.num_param < MAX_ESC_PAR)
1565201052Smarius				return;
1566201052Smarius			break;
1567201052Smarius
1568201052Smarius		case '=':
1569201052Smarius			scp->term.esc = 3;
1570201052Smarius			scp->term.last_param = -1;
1571201052Smarius			for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
1572201052Smarius				scp->term.param[i] = 1;
1573201052Smarius			scp->term.num_param = 0;
1574201052Smarius			return;
1575201052Smarius
1576201052Smarius		case 'A': /* up n rows */
1577201052Smarius			n = scp->term.param[0]; if (n < 1) n = 1;
1578201052Smarius			move_crsr(scp, scp->xpos, scp->ypos - n);
1579201052Smarius			break;
1580201052Smarius
1581201052Smarius		case 'B': /* down n rows */
1582201052Smarius			n = scp->term.param[0]; if (n < 1) n = 1;
1583201052Smarius			move_crsr(scp, scp->xpos, scp->ypos + n);
1584201052Smarius			break;
1585201052Smarius
1586201052Smarius		case 'C': /* right n columns */
1587201052Smarius			n = scp->term.param[0]; if (n < 1) n = 1;
1588201052Smarius			move_crsr(scp, scp->xpos + n, scp->ypos);
1589201052Smarius			break;
1590201052Smarius
1591201052Smarius		case 'D': /* left n columns */
1592201052Smarius			n = scp->term.param[0]; if (n < 1) n = 1;
1593201052Smarius			move_crsr(scp, scp->xpos - n, scp->ypos);
1594201052Smarius			break;
1595201052Smarius
1596201052Smarius		case 'E': /* cursor to start of line n lines down */
1597201052Smarius			n = scp->term.param[0]; if (n < 1) n = 1;
1598201052Smarius			move_crsr(scp, 0, scp->ypos + n);
1599201052Smarius			break;
1600201052Smarius
1601201052Smarius		case 'F': /* cursor to start of line n lines up */
1602201052Smarius			n = scp->term.param[0]; if (n < 1) n = 1;
1603201052Smarius			move_crsr(scp, 0, scp->ypos - n);
1604201052Smarius			break;
1605201052Smarius
1606201052Smarius		case 'f': /* System V consoles .. */
1607201052Smarius		case 'H': /* Cursor move */
1608201052Smarius			if (scp->term.num_param == 0)
1609201052Smarius				move_crsr(scp, 0, 0);
1610201052Smarius			else if (scp->term.num_param == 2)
1611201052Smarius				move_crsr(scp, scp->term.param[1] - 1,
1612201052Smarius					  scp->term.param[0] - 1);
1613201052Smarius			break;
1614201052Smarius
1615201052Smarius		case 'J': /* Clear all or part of display */
1616201052Smarius			if (scp->term.num_param == 0)
1617201052Smarius				n = 0;
1618201052Smarius			else
1619201052Smarius				n = scp->term.param[0];
1620201052Smarius			switch (n) {
1621202003Smarius			case 0: /* clear form cursor to end of display */
1622202003Smarius				fillw(scp->term.cur_attr | scr_map[0x20],
1623202003Smarius				      scp->crtat, scp->crt_base +
1624201052Smarius				      scp->xsize * scp->ysize -
1625201052Smarius				      scp->crtat);
1626202003Smarius				break;
1627202003Smarius			case 1: /* clear from beginning of display to cursor */
1628201052Smarius				fillw(scp->term.cur_attr | scr_map[0x20],
1629202003Smarius				      scp->crt_base,
1630202003Smarius				      scp->crtat - scp->crt_base);
1631202003Smarius				break;
1632202003Smarius			case 2: /* clear entire display */
1633201052Smarius				clear_screen(scp);
1634201052Smarius				break;
1635202003Smarius			}
1636202003Smarius			break;
1637202003Smarius
1638202003Smarius		case 'K': /* Clear all or part of line */
1639202003Smarius			if (scp->term.num_param == 0)
1640202003Smarius				n = 0;
1641202003Smarius			else
1642202003Smarius				n = scp->term.param[0];
1643202003Smarius			switch (n) {
1644202003Smarius			case 0: /* clear form cursor to end of line */
1645202003Smarius				fillw(scp->term.cur_attr | scr_map[0x20],
1646202003Smarius				      scp->crtat, scp->xsize - scp->xpos);
1647202003Smarius				break;
1648202003Smarius			case 1: /* clear from beginning of line to cursor */
1649202003Smarius				fillw(scp->term.cur_attr|scr_map[0x20],
1650202003Smarius				      scp->crtat - (scp->xsize - scp->xpos),
1651202003Smarius				      (scp->xsize - scp->xpos) + 1);
1652202003Smarius				break;
1653202003Smarius			case 2: /* clear entire line */
1654202003Smarius				fillw(scp->term.cur_attr|scr_map[0x20],
1655202003Smarius				      scp->crtat - (scp->xsize - scp->xpos),
1656202003Smarius				      scp->xsize);
1657202003Smarius				break;
1658202003Smarius			}
1659202003Smarius			break;
1660202003Smarius
1661202003Smarius		case 'L':	/* Insert n lines */
1662202003Smarius			n = scp->term.param[0]; if (n < 1) n = 1;
1663202003Smarius			if (n > scp->ysize - scp->ypos)
1664202003Smarius				n = scp->ysize - scp->ypos;
1665202003Smarius			src = scp->crt_base + scp->ypos * scp->xsize;
1666202003Smarius			dst = src + n * scp->xsize;
1667202003Smarius			count = scp->ysize - (scp->ypos + n);
1668202003Smarius			move_up(src, dst, count * scp->xsize);
1669202003Smarius			fillw(scp->term.cur_attr | scr_map[0x20], src,
1670202003Smarius			      n * scp->xsize);
1671202003Smarius			break;
1672202003Smarius
1673202003Smarius		case 'M':	/* Delete n lines */
1674202003Smarius			n = scp->term.param[0]; if (n < 1) n = 1;
1675202003Smarius			if (n > scp->ysize - scp->ypos)
1676202003Smarius				n = scp->ysize - scp->ypos;
1677201052Smarius			dst = scp->crt_base + scp->ypos * scp->xsize;
1678201052Smarius			src = dst + n * scp->xsize;
1679201052Smarius			count = scp->ysize - (scp->ypos + n);
1680201052Smarius			move_down(src, dst, count * scp->xsize);
1681201052Smarius			src = dst + count * scp->xsize;
1682203094Smarius			fillw(scp->term.cur_attr | scr_map[0x20], src,
1683203094Smarius			      n * scp->xsize);
1684201052Smarius			break;
1685201052Smarius
1686201052Smarius		case 'P':	/* Delete n chars */
1687201052Smarius			n = scp->term.param[0]; if (n < 1) n = 1;
1688201052Smarius			if (n > scp->xsize - scp->xpos)
1689201052Smarius				n = scp->xsize - scp->xpos;
1690201052Smarius			dst = scp->crtat;
1691201052Smarius			src = dst + n;
1692201052Smarius			count = scp->xsize - (scp->xpos + n);
1693201052Smarius			move_down(src, dst, count);
1694201052Smarius			src = dst + count;
1695201052Smarius			fillw(scp->term.cur_attr | scr_map[0x20], src, n);
1696201052Smarius			break;
1697201052Smarius
1698201052Smarius		case '@':	/* Insert n chars */
1699201052Smarius			n = scp->term.param[0]; if (n < 1) n = 1;
1700201052Smarius			if (n > scp->xsize - scp->xpos)
1701201052Smarius				n = scp->xsize - scp->xpos;
1702201052Smarius			src = scp->crtat;
1703201052Smarius			dst = src + n;
1704201052Smarius			count = scp->xsize - (scp->xpos + n);
1705201052Smarius			move_up(src, dst, count);
1706201052Smarius			fillw(scp->term.cur_attr | scr_map[0x20], src, n);
1707201052Smarius			break;
1708201052Smarius
1709201052Smarius		case 'S':	/* scroll up n lines */
1710201052Smarius			n = scp->term.param[0]; if (n < 1)  n = 1;
1711201052Smarius			if (n > scp->ypos)
1712201052Smarius				n = scp->ypos;
1713201052Smarius			bcopy(scp->crt_base + (scp->xsize * n),
1714201052Smarius			      scp->crt_base,
1715201052Smarius			      scp->xsize * (scp->ysize - n) *
1716201052Smarius			      sizeof(u_short));
1717201052Smarius			fillw(scp->term.cur_attr | scr_map[0x20],
1718201052Smarius			      scp->crt_base + scp->xsize *
1719201052Smarius			      (scp->ysize - 1),
1720201052Smarius			      scp->xsize);
1721201052Smarius			break;
1722201052Smarius
1723201052Smarius		case 'T':	/* scroll down n lines */
1724201052Smarius			n = scp->term.param[0]; if (n < 1)  n = 1;
1725201052Smarius			if (n > scp->ysize - scp->ypos)
1726202023Smarius				n = scp->ysize - scp->ypos;
1727201052Smarius			bcopy(scp->crt_base,
1728201052Smarius			      scp->crt_base + (scp->xsize * n),
1729201052Smarius			      scp->xsize * (scp->ysize - n) *
1730201052Smarius			      sizeof(u_short));
1731201052Smarius			fillw(scp->term.cur_attr | scr_map[0x20],
1732201052Smarius			      scp->crt_base, scp->xsize);
1733201052Smarius			break;
1734201052Smarius
1735201052Smarius		case 'X':	/* delete n characters in line */
1736201052Smarius			n = scp->term.param[0]; if (n < 1)  n = 1;
1737201052Smarius			if (n > scp->xsize - scp->xpos)
1738201052Smarius				n = scp->xsize - scp->xpos;
1739201052Smarius			fillw(scp->term.cur_attr | scr_map[0x20],
1740201052Smarius                              scp->crt_base + scp->xpos +
1741201052Smarius			      ((scp->xsize*scp->ypos) * sizeof(u_short)), n);
1742201052Smarius			break;
1743201052Smarius
1744201052Smarius		case 'Z':	/* move n tabs backwards */
1745201052Smarius			n = scp->term.param[0]; if (n < 1)  n = 1;
1746201052Smarius			if ((i = scp->xpos & 0xf8) == scp->xpos)
1747201052Smarius				i -= 8*n;
1748201052Smarius			else
1749201052Smarius				i -= 8*(n-1);
1750201052Smarius			if (i < 0)
1751201052Smarius				i = 0;
1752201052Smarius			move_crsr(scp, i, scp->ypos);
1753201052Smarius			break;
1754201052Smarius
1755201052Smarius		case '`': 	/* move cursor to column n */
1756201052Smarius			n = scp->term.param[0]; if (n < 1)  n = 1;
1757202003Smarius			move_crsr(scp, n, scp->ypos);
1758202003Smarius			break;
1759202023Smarius
1760202003Smarius		case 'a': 	/* move cursor n columns to the right */
1761202003Smarius			n = scp->term.param[0]; if (n < 1)  n = 1;
1762202003Smarius			move_crsr(scp, scp->xpos + n, scp->ypos);
1763202003Smarius			break;
1764202003Smarius
1765202003Smarius		case 'd': 	/* move cursor to row n */
1766202023Smarius			n = scp->term.param[0]; if (n < 1)  n = 1;
1767202023Smarius			move_crsr(scp, scp->xpos, n);
1768202023Smarius			break;
1769202023Smarius
1770202023Smarius		case 'e': 	/* move cursor n rows down */
1771202023Smarius			n = scp->term.param[0]; if (n < 1)  n = 1;
1772202023Smarius			move_crsr(scp, scp->xpos, scp->ypos + n);
1773202003Smarius			break;
1774201052Smarius
1775202003Smarius		case 'm': 	/* change attribute */
1776202023Smarius			if (scp->term.num_param == 0) {
1777202003Smarius				scp->term.cur_attr = scp->term.std_attr;
1778202003Smarius				break;
1779202003Smarius			}
1780202003Smarius			for (i = 0; i < scp->term.num_param; i++) {
1781202003Smarius				switch (n = scp->term.param[i]) {
1782202003Smarius				case 0:	/* back to normal */
1783202003Smarius					scp->term.cur_attr = scp->term.std_attr;
1784202003Smarius					break;
1785202003Smarius				case 1:	/* highlight (bold) */
1786202003Smarius					scp->term.cur_attr &= 0xFF00;
1787202003Smarius					scp->term.cur_attr |= 0x0800;
1788202003Smarius					break;
1789202003Smarius				case 4: /* highlight (underline) */
1790201052Smarius					scp->term.cur_attr &= 0xFF00;
1791201052Smarius					scp->term.cur_attr |= 0x0800;
1792201052Smarius					break;
1793201052Smarius				case 5: /* blink */
1794201052Smarius					scp->term.cur_attr &= 0xFF00;
1795201052Smarius					scp->term.cur_attr |= 0x8000;
1796201052Smarius					break;
1797201052Smarius				case 7: /* reverse video */
1798201052Smarius					scp->term.cur_attr = scp->term.rev_attr;
1799201052Smarius					break;
1800201052Smarius				case 30: case 31: /* set fg color */
1801201052Smarius				case 32: case 33: case 34:
1802201052Smarius				case 35: case 36: case 37:
1803201052Smarius					scp->term.cur_attr =
1804201052Smarius						(scp->term.cur_attr & 0xF8FF)
1805201052Smarius						| (ansi_col[(n-30) & 7] << 8);
1806201052Smarius					break;
1807201052Smarius				case 40: case 41: /* set bg color */
1808201052Smarius				case 42: case 43: case 44:
1809201052Smarius				case 45: case 46: case 47:
1810201052Smarius					scp->term.cur_attr =
1811201052Smarius						(scp->term.cur_attr & 0x8FFF)
1812201052Smarius						| (ansi_col[(n-40) & 7] << 12);
1813201052Smarius					break;
1814201052Smarius				}
1815201052Smarius			}
1816201052Smarius			break;
1817201052Smarius
1818201052Smarius		case 'x':
1819201052Smarius			if (scp->term.num_param == 0)
1820201052Smarius				n = 0;
1821201052Smarius			else
1822201052Smarius				n = scp->term.param[0];
1823201052Smarius			switch (n) {
1824201052Smarius			case 0: 	/* reset attributes */
1825201052Smarius				scp->term.cur_attr = scp->term.std_attr =
1826201052Smarius					current_default->std_attr;
1827201052Smarius				scp->term.rev_attr = current_default->rev_attr;
1828201052Smarius				break;
1829201052Smarius			case 1: 	/* set ansi background */
1830201052Smarius				scp->term.cur_attr = scp->term.std_attr =
1831201052Smarius					(scp->term.std_attr & 0x0F00) |
1832201052Smarius					(ansi_col[(scp->term.param[1])&0x0F]<<12);
1833201052Smarius				break;
1834201052Smarius			case 2: 	/* set ansi foreground */
1835201052Smarius				scp->term.cur_attr = scp->term.std_attr =
1836201052Smarius					(scp->term.std_attr & 0xF000) |
1837201052Smarius					(ansi_col[(scp->term.param[1])&0x0F]<<8);
1838202003Smarius				break;
1839201052Smarius			case 3: 	/* set ansi attribute directly */
1840201052Smarius				scp->term.cur_attr = scp->term.std_attr =
1841201052Smarius					(scp->term.param[1]&0xFF)<<8;
1842201052Smarius				break;
1843201052Smarius			case 5: 	/* set ansi reverse video background */
1844201052Smarius				scp->term.rev_attr =
1845202003Smarius					(scp->term.rev_attr & 0x0F00) |
1846201052Smarius					(ansi_col[(scp->term.param[1])&0x0F]<<12);
1847202003Smarius				break;
1848201052Smarius			case 6: 	/* set ansi reverse video foreground */
1849201052Smarius				scp->term.rev_attr =
1850201052Smarius					(scp->term.rev_attr & 0xF000) |
1851201052Smarius					(ansi_col[(scp->term.param[1])&0x0F]<<8);
1852201052Smarius				break;
1853201052Smarius			case 7: 	/* set ansi reverse video directly */
1854201052Smarius				scp->term.rev_attr = (scp->term.param[1]&0xFF)<<8;
1855201052Smarius				break;
1856201052Smarius			}
1857201052Smarius			break;
1858201052Smarius
1859292789Smarius		case 'z':	/* switch to (virtual) console n */
1860292789Smarius			if (scp->term.num_param == 1)
1861292789Smarius				switch_scr(scp->term.param[0]);
1862201052Smarius			break;
1863292789Smarius		}
1864292789Smarius	}
1865201052Smarius	else if (scp->term.esc == 3) {
1866201052Smarius		if (c >= '0' && c <= '9') {
1867201052Smarius			if (scp->term.num_param < MAX_ESC_PAR) {
1868201052Smarius				if (scp->term.last_param != scp->term.num_param) {
1869201052Smarius					scp->term.last_param = scp->term.num_param;
1870201052Smarius					scp->term.param[scp->term.num_param] = 0;
1871201052Smarius				}
1872201052Smarius				else
1873201052Smarius					scp->term.param[scp->term.num_param] *= 10;
1874201052Smarius				scp->term.param[scp->term.num_param] += c - '0';
1875				return;
1876			}
1877		}
1878		scp->term.num_param = scp->term.last_param + 1;
1879		switch (c) {
1880
1881		case ';':
1882			if (scp->term.num_param < MAX_ESC_PAR)
1883				return;
1884			break;
1885
1886		case 'A':	/* set display border color */
1887			if (scp->term.num_param == 1)
1888				scp->border=scp->term.param[0] & 0xff;
1889				if (scp == cur_console)
1890					set_border(scp->border);
1891			break;
1892
1893		case 'B':	/* set bell pitch and duration */
1894			if (scp->term.num_param == 2) {
1895				scp->bell_pitch = scp->term.param[0];
1896				scp->bell_duration = scp->term.param[1]*10;
1897			}
1898			break;
1899
1900		case 'C': 	/* set cursor shape (start & end line) */
1901			if (scp->term.num_param == 2) {
1902				scp->cursor_start = scp->term.param[0] & 0x1F;
1903				scp->cursor_end = scp->term.param[1] & 0x1F;
1904				if (scp == cur_console)
1905					cursor_shape(scp->cursor_start,
1906						     scp->cursor_end);
1907			}
1908			break;
1909
1910		case 'F':	/* set ansi foreground */
1911			if (scp->term.num_param == 1)
1912				scp->term.cur_attr = scp->term.std_attr =
1913					(scp->term.std_attr & 0xF000)
1914					| ((scp->term.param[0] & 0x0F) << 8);
1915			break;
1916
1917		case 'G': 	/* set ansi background */
1918			if (scp->term.num_param == 1)
1919				scp->term.cur_attr = scp->term.std_attr =
1920					(scp->term.std_attr & 0x0F00)
1921					| ((scp->term.param[0] & 0x0F) << 12);
1922			break;
1923
1924		case 'H':	/* set ansi reverse video foreground */
1925			if (scp->term.num_param == 1)
1926				scp->term.rev_attr =
1927					(scp->term.rev_attr & 0xF000)
1928					| ((scp->term.param[0] & 0x0F) << 8);
1929			break;
1930
1931		case 'I': 	/* set ansi reverse video background */
1932			if (scp->term.num_param == 1)
1933				scp->term.rev_attr =
1934					(scp->term.rev_attr & 0x0F00)
1935					| ((scp->term.param[0] & 0x0F) << 12);
1936			break;
1937		}
1938	}
1939	scp->term.esc = 0;
1940}
1941
1942
1943static void
1944ansi_put(scr_stat *scp, u_char c)
1945{
1946	if (scp->status & UNKNOWN_MODE)
1947		return;
1948
1949	/* make screensaver happy */
1950	if (scp == cur_console) {
1951		scrn_time_stamp = time.tv_sec;
1952		if (scrn_blanked)
1953			SCRN_SAVER(0);
1954	}
1955	in_putc++;
1956	if (scp->term.esc)
1957		scan_esc(scp, c);
1958	else switch(c) {
1959	case 0x1B:	/* start escape sequence */
1960		scp->term.esc = 1;
1961		scp->term.num_param = 0;
1962		break;
1963	case 0x07:
1964		if (scp == cur_console)
1965		 	sysbeep(scp->bell_pitch, scp->bell_duration);
1966		break;
1967	case '\t':	/* non-destructive tab */
1968		scp->crtat += (8 - scp->xpos % 8);
1969		scp->xpos += (8 - scp->xpos % 8);
1970		break;
1971	case '\b':      /* non-destructive backspace */
1972		if (scp->crtat > scp->crt_base) {
1973			scp->crtat--;
1974			if (scp->xpos > 0)
1975				scp->xpos--;
1976			else {
1977				scp->xpos += scp->xsize - 1;
1978				scp->ypos--;
1979			}
1980		}
1981		break;
1982	case '\r':	/* return to pos 0 */
1983		move_crsr(scp, 0, scp->ypos);
1984		break;
1985	case '\n':	/* newline, same pos */
1986		scp->crtat += scp->xsize;
1987		scp->ypos++;
1988		break;
1989	case '\f':	/* form feed, clears screen */
1990		clear_screen(scp);
1991		break;
1992	default:
1993		/* Print only printables */
1994		*scp->crtat = (scp->term.cur_attr | scr_map[c]);
1995		scp->crtat++;
1996		if (++scp->xpos >= scp->xsize) {
1997			scp->xpos = 0;
1998			scp->ypos++;
1999		}
2000		break;
2001	}
2002	if (scp->crtat >= scp->crt_base + scp->ysize * scp->xsize) {
2003		bcopy(scp->crt_base + scp->xsize, scp->crt_base,
2004			scp->xsize * (scp->ysize - 1) * sizeof(u_short));
2005		fillw(scp->term.cur_attr | scr_map[0x20],
2006			scp->crt_base + scp->xsize * (scp->ysize - 1),
2007			scp->xsize);
2008		scp->crtat -= scp->xsize;
2009		scp->ypos--;
2010	}
2011	in_putc--;
2012	if (delayed_next_scr)
2013		switch_scr(delayed_next_scr - 1);
2014}
2015
2016
2017static void
2018scinit(void)
2019{
2020	u_short volatile *cp = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short), was;
2021	unsigned cursorat;
2022	int i;
2023
2024	/*
2025	 * catch that once in a blue moon occurence when scinit is called
2026	 * TWICE, adding the CGA_BUF offset again -> poooff
2027	 */
2028	if (crtat != 0)
2029		return;
2030	/*
2031	 * Crtat initialized to point to MONO buffer, if not present change
2032	 * to CGA_BUF offset. ONLY ADD the difference since locore.s adds
2033	 * in the remapped offset at the "right" time
2034	 */
2035	was = *cp;
2036	*cp = (u_short) 0xA55A;
2037	if (*cp != 0xA55A) {
2038		crtc_addr = MONO_BASE;
2039	} else {
2040		*cp = was;
2041		crtc_addr = COLOR_BASE;
2042		Crtat = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short);
2043	}
2044
2045	/* Extract cursor location */
2046	outb(crtc_addr,14);
2047	cursorat = inb(crtc_addr+1)<<8 ;
2048	outb(crtc_addr,15);
2049	cursorat |= inb(crtc_addr+1);
2050	crtat = Crtat + cursorat;
2051
2052	/* is this a VGA or higher ? */
2053	outb(crtc_addr, 7);
2054	if (inb(crtc_addr) == 7)
2055		crtc_vga = 1;
2056
2057	current_default = &user_default;
2058	console[0].crtat = crtat;
2059	console[0].crt_base = Crtat;
2060	console[0].term.esc = 0;
2061	console[0].term.std_attr = current_default->std_attr;
2062	console[0].term.rev_attr = current_default->rev_attr;
2063	console[0].term.cur_attr = current_default->std_attr;
2064	console[0].xpos = cursorat % COL;
2065	console[0].ypos = cursorat / COL;
2066	console[0].border = BG_BLACK;;
2067	console[0].xsize = COL;
2068	console[0].ysize = ROW;
2069	console[0].status = NLKED;
2070	console[0].pid = 0;
2071	console[0].proc = NULL;
2072	console[0].smode.mode = VT_AUTO;
2073	console[0].bell_pitch = BELL_PITCH;
2074	console[0].bell_duration = BELL_DURATION;
2075	kernel_console.esc = 0;
2076	kernel_console.std_attr = kernel_default.std_attr;
2077	kernel_console.rev_attr = kernel_default.rev_attr;
2078	kernel_console.cur_attr = kernel_default.std_attr;
2079	/* initialize mapscrn array to a one to one map */
2080	for (i=0; i<sizeof(scr_map); i++)
2081		scr_map[i] = i;
2082	clear_screen(&console[0]);
2083}
2084
2085
2086static void
2087scput(u_char c)
2088{
2089	scr_stat *scp = &console[0];
2090	term_stat save;
2091
2092	if (crtat == 0)
2093		scinit();
2094	if( in_putc == 0) {
2095		++in_putc;
2096		save = scp->term;
2097		scp->term = kernel_console;
2098		current_default = &kernel_default;
2099		ansi_put(scp, c);
2100		kernel_console = scp->term;
2101		current_default = &user_default;
2102		scp->term = save;
2103		--in_putc;
2104	} else {
2105		if( console_buffer_count < CONSOLE_BUFSIZE)
2106			console_buffer[console_buffer_count++] = c;
2107	}
2108}
2109
2110
2111static u_char
2112*get_fstr(u_int c, u_int *len)
2113{
2114	u_int i;
2115
2116	if (!(c & FKEY))
2117		return(NULL);
2118	i = (c & 0xFF) - F_FN;
2119	if (i > n_fkey_tab)
2120		return(NULL);
2121	*len = fkey_tab[i].len;
2122	return(fkey_tab[i].str);
2123}
2124
2125
2126static void
2127update_leds(int which)
2128{
2129	int s;
2130  	static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
2131
2132	/* replace CAPS led with ALTGR led for ALTGR keyboards */
2133	if (key_map.n_keys > ALTGR_OFFSET) {
2134		if (which & ALKED)
2135			which |= CLKED;
2136		else
2137			which &= ~CLKED;
2138	}
2139	s = spltty();
2140	kbd_cmd(KB_SETLEDS);
2141	kbd_cmd(xlate_leds[which & LED_MASK]);
2142	splx(s);
2143}
2144
2145
2146/*
2147 * scgetc(noblock) - get character from keyboard.
2148 * If noblock = 0 wait until a key is pressed.
2149 * Else return NOKEY.
2150 */
2151u_int
2152scgetc(int noblock)
2153{
2154	u_char scancode, keycode;
2155	u_int state, action;
2156	struct key_t *key;
2157	static u_char esc_flag = 0, compose = 0;
2158	static u_int chr = 0;
2159
2160next_code:
2161	kbd_wait();
2162	/* First see if there is something in the keyboard port */
2163	if (inb(KB_STAT) & KB_BUF_FULL)
2164		scancode = inb(KB_DATA);
2165	else if (noblock)
2166		return(NOKEY);
2167	else
2168		goto next_code;
2169
2170	if (cur_console->status & KBD_RAW_MODE)
2171		return scancode;
2172#if ASYNCH
2173	if (scancode == KB_ACK || scancode == KB_RESEND) {
2174		kbd_reply = scancode;
2175		if (noblock)
2176			return(NOKEY);
2177		goto next_code;
2178	}
2179#endif
2180	keycode = scancode & 0x7F;
2181	switch (esc_flag) {
2182	case 0x00:		/* normal scancode */
2183		switch(scancode) {
2184		case 0xB8:	/* left alt  (compose key) */
2185			if (compose) {
2186				compose = 0;
2187				if (chr > 255) {
2188					sysbeep(BELL_PITCH, BELL_DURATION);
2189					chr = 0;
2190				}
2191			}
2192			break;
2193		case 0x38:
2194			if (!compose) {
2195				compose = 1;
2196				chr = 0;
2197			}
2198			break;
2199		case 0xE0:
2200		case 0xE1:
2201			esc_flag = scancode;
2202			goto next_code;
2203		}
2204		break;
2205	case 0xE0:		/* 0xE0 prefix */
2206		esc_flag = 0;
2207		switch (keycode) {
2208		case 0x1C:	/* right enter key */
2209			keycode = 0x59;
2210			break;
2211		case 0x1D:	/* right ctrl key */
2212			keycode = 0x5A;
2213			break;
2214		case 0x35:	/* keypad divide key */
2215			keycode = 0x5B;
2216			break;
2217		case 0x37:	/* print scrn key */
2218			keycode = 0x5C;
2219			break;
2220		case 0x38:	/* right alt key (alt gr) */
2221			keycode = 0x5D;
2222			break;
2223		case 0x47:	/* grey home key */
2224			keycode = 0x5E;
2225			break;
2226		case 0x48:	/* grey up arrow key */
2227			keycode = 0x5F;
2228			break;
2229		case 0x49:	/* grey page up key */
2230			keycode = 0x60;
2231			break;
2232		case 0x4B:	/* grey left arrow key */
2233			keycode = 0x61;
2234			break;
2235		case 0x4D:	/* grey right arrow key */
2236			keycode = 0x62;
2237			break;
2238		case 0x4F:	/* grey end key */
2239			keycode = 0x63;
2240			break;
2241		case 0x50:	/* grey down arrow key */
2242			keycode = 0x64;
2243			break;
2244		case 0x51:	/* grey page down key */
2245			keycode = 0x65;
2246			break;
2247		case 0x52:	/* grey insert key */
2248			keycode = 0x66;
2249			break;
2250		case 0x53:	/* grey delete key */
2251			keycode = 0x67;
2252			break;
2253		default:	/* ignore everything else */
2254			goto next_code;
2255		}
2256		break;
2257	case 0xE1:		/* 0xE1 prefix */
2258		esc_flag = 0;
2259		if (keycode == 0x1D)
2260			esc_flag = 0x1D;
2261		goto next_code;
2262		/* NOT REACHED */
2263	case 0x1D:		/* pause / break */
2264		esc_flag = 0;
2265		if (keycode != 0x45)
2266			goto next_code;
2267		keycode = 0x68;
2268		break;
2269	}
2270
2271	if (compose) {
2272		switch (scancode) {
2273		/* key pressed process it */
2274		case 0x47: case 0x48: case 0x49:	/* keypad 7,8,9 */
2275			chr = (scancode - 0x40) + chr*10;
2276			goto next_code;
2277		case 0x4B: case 0x4C: case 0x4D:	/* keypad 4,5,6 */
2278			chr = (scancode - 0x47) + chr*10;
2279			goto next_code;
2280		case 0x4F: case 0x50: case 0x51:	/* keypad 1,2,3 */
2281			chr = (scancode - 0x4E) + chr*10;
2282			goto next_code;
2283		case 0x52:				/* keypad 0 */
2284			chr *= 10;
2285			goto next_code;
2286
2287		/* key release, no interest here */
2288		case 0xC7: case 0xC8: case 0xC9:	/* keypad 7,8,9 */
2289		case 0xCB: case 0xCC: case 0xCD:	/* keypad 4,5,6 */
2290		case 0xCF: case 0xD0: case 0xD1:	/* keypad 1,2,3 */
2291		case 0xD2:				/* keypad 0 */
2292			goto next_code;
2293
2294		case 0x38:				/* left alt key */
2295			break;
2296		default:
2297			if (chr) {
2298				compose = chr = 0;
2299				sysbeep(BELL_PITCH, BELL_DURATION);
2300				goto next_code;
2301			}
2302			break;
2303		}
2304	}
2305
2306	state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0));
2307	if ((!agrs && (cur_console->status & ALKED))
2308	    || (agrs && !(cur_console->status & ALKED)))
2309		keycode += ALTGR_OFFSET;
2310	key = &key_map.key[keycode];
2311	if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED))
2312	     || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) )
2313		state ^= 1;
2314
2315	/* Check for make/break */
2316	action = key->map[state];
2317	if (scancode & 0x80) { 		/* key released */
2318		if (key->spcl & 0x80) {
2319			switch (action) {
2320			case LSH:
2321				shfts &= ~1;
2322				break;
2323			case RSH:
2324				shfts &= ~2;
2325				break;
2326			case LCTR:
2327				ctls &= ~1;
2328				break;
2329			case RCTR:
2330				ctls &= ~2;
2331				break;
2332			case LALT:
2333				alts &= ~1;
2334				break;
2335			case RALT:
2336				alts &= ~2;
2337				break;
2338			case NLK:
2339				nlkcnt = 0;
2340				break;
2341			case CLK:
2342				clkcnt = 0;
2343				break;
2344			case SLK:
2345				slkcnt = 0;
2346				break;
2347			case ASH:
2348				agrs = 0;
2349				break;
2350			case ALK:
2351				alkcnt = 0;
2352				break;
2353			case META:
2354				metas = 0;
2355				break;
2356			}
2357		}
2358		if (chr && !compose) {
2359			action = chr;
2360			chr = 0;
2361			return(action);
2362		}
2363	} else {
2364		/* key pressed */
2365		if (key->spcl & (0x80>>state)) {
2366			switch (action) {
2367			/* LOCKING KEYS */
2368			case NLK:
2369				if (!nlkcnt) {
2370					nlkcnt++;
2371					if (cur_console->status & NLKED)
2372						cur_console->status &= ~NLKED;
2373					else
2374						cur_console->status |= NLKED;
2375					update_leds(cur_console->status);
2376				}
2377				break;
2378			case CLK:
2379				if (!clkcnt) {
2380					clkcnt++;
2381					if (cur_console->status & CLKED)
2382						cur_console->status &= ~CLKED;
2383					else
2384						cur_console->status |= CLKED;
2385					update_leds(cur_console->status);
2386				}
2387				break;
2388			case SLK:
2389				if (!slkcnt) {
2390					slkcnt++;
2391					if (cur_console->status & SLKED) {
2392						cur_console->status &= ~SLKED;
2393						pcstart(VIRTUAL_TTY(get_scr_num()));
2394					}
2395					else
2396						cur_console->status |= SLKED;
2397					update_leds(cur_console->status);
2398				}
2399				break;
2400 			case ALK:
2401				if (!alkcnt) {
2402					alkcnt++;
2403 					if (cur_console->status & ALKED)
2404 						cur_console->status &= ~ALKED;
2405 					else
2406 						cur_console->status |= ALKED;
2407					update_leds(cur_console->status);
2408				}
2409  				break;
2410
2411			/* NON-LOCKING KEYS */
2412			case NOP:
2413				break;
2414			case RBT:
2415				shutdown_nice();
2416				break;
2417			case DBG:
2418#if DDB > 0			/* try to switch to console 0 */
2419				if (cur_console->smode.mode == VT_AUTO &&
2420		    		    console[0].smode.mode == VT_AUTO)
2421					switch_scr(0);
2422				Debugger("manual escape to debugger");
2423				return(NOKEY);
2424#else
2425				printf("No debugger in kernel\n");
2426#endif
2427				break;
2428			case LSH:
2429				shfts |= 1;
2430				break;
2431			case RSH:
2432				shfts |= 2;
2433				break;
2434			case LCTR:
2435				ctls |= 1;
2436				break;
2437			case RCTR:
2438				ctls |= 2;
2439				break;
2440			case LALT:
2441				alts |= 1;
2442				break;
2443			case RALT:
2444				alts |= 2;
2445				break;
2446			case ASH:
2447				agrs = 1;
2448				break;
2449			case META:
2450				metas = 1;
2451				break;
2452			case NEXT:
2453				switch_scr((get_scr_num()+1)%NCONS);
2454				break;
2455			default:
2456				if (action >= F_SCR && action <= L_SCR) {
2457					switch_scr(action - F_SCR);
2458					break;
2459				}
2460				if (action >= F_FN && action <= L_FN)
2461					action |= FKEY;
2462				return(action);
2463			}
2464		}
2465		else {
2466			if (metas)
2467				action |= MKEY;
2468 			return(action);
2469		}
2470	}
2471	goto next_code;
2472}
2473
2474
2475int
2476getchar(void)
2477{
2478	u_char thechar;
2479	int s;
2480
2481	polling = 1;
2482	s = splhigh();
2483	scput('>');
2484	thechar = (u_char) scgetc(0);
2485	polling = 0;
2486	splx(s);
2487	switch (thechar) {
2488	default:
2489		if (thechar >= scr_map[0x20])
2490			scput(thechar);
2491		return(thechar);
2492	case cr:
2493	case lf:
2494		scput(cr); scput(lf);
2495		return(lf);
2496	case bs:
2497	case del:
2498		scput(bs); scput(scr_map[0x20]); scput(bs);
2499		return(thechar);
2500	case cntld:
2501		scput('^'); scput('D'); scput('\r'); scput('\n');
2502		return(0);
2503	}
2504}
2505
2506
2507u_int
2508sgetc(int noblock)
2509{
2510	return (scgetc(noblock) & 0xff);
2511}
2512
2513
2514int
2515pcmmap(dev_t dev, int offset, int nprot)
2516{
2517	if (offset > 0x20000)
2518		return EINVAL;
2519	return i386_btop((VIDEOMEM + offset));
2520}
2521
2522
2523static void
2524kbd_wait(void)
2525{
2526	int i = 1000;
2527
2528	while (i--) {
2529		if ((inb(KB_STAT) & KB_READY) == 0)
2530			break;
2531		DELAY (10);
2532	}
2533}
2534
2535
2536static void
2537kbd_cmd(u_char command)
2538{
2539	int retry = 5;
2540	do {
2541		int i = 100000;
2542
2543		kbd_wait();
2544#if ASYNCH
2545		kbd_reply = 0;
2546		outb(KB_DATA, command);
2547		while (i--) {
2548			if (kbd_reply == KB_ACK)
2549				return;
2550			if (kbd_reply == KB_RESEND)
2551				break;
2552		}
2553#else
2554		outb(KB_DATA, command);
2555		while (i--) {
2556			if (inb(KB_STAT) & KB_BUF_FULL) {
2557				int val;
2558				DELAY(10);
2559				val = inb(KB_DATA);
2560				if (val == KB_ACK)
2561					return;
2562				if (val == KB_RESEND)
2563					break;
2564			}
2565		}
2566#endif
2567	} while (retry--);
2568}
2569
2570
2571static void
2572set_mode(scr_stat *scp)
2573{
2574	u_char byte;
2575	int s;
2576
2577	if (scp != cur_console)
2578		return;
2579
2580	/* (re)activate cursor */
2581	untimeout((timeout_t)cursor_pos, 0);
2582	cursor_pos(1);
2583
2584	/* change cursor type if set */
2585	if (scp->cursor_start != -1 && scp->cursor_end != -1)
2586		cursor_shape(scp->cursor_start, scp->cursor_end);
2587
2588	/* mode change only on VGA's */
2589	if (!crtc_vga)
2590		return;
2591
2592	/* setup video hardware for the given mode */
2593	s = splhigh();
2594	switch(scp->mode) {
2595	case TEXT80x25:
2596		outb(crtc_addr, 9); byte = inb(crtc_addr+1);
2597		outb(crtc_addr, 9); outb(crtc_addr+1, byte | 0x0F);
2598    		outb(TSIDX, 0x03); outb(TSREG, 0x00);	/* select font 0 */
2599		break;
2600	case TEXT80x50:
2601		outb(crtc_addr, 9); byte = inb(crtc_addr+1);
2602		outb(crtc_addr, 9); outb(crtc_addr+1, (byte & 0xF0) | 0x07);
2603    		outb(TSIDX, 0x03); outb(TSREG, 0x05);	/* select font 1 */
2604		break;
2605	default:
2606		break;
2607	}
2608	splx(s);
2609
2610	/* set border color for this (virtual) console */
2611	set_border(scp->border);
2612	return;
2613}
2614
2615
2616static void
2617set_border(int color)
2618{
2619	inb(crtc_addr+6); 				/* reset flip-flop */
2620	outb(ATC, 0x11); outb(ATC, color);
2621 	inb(crtc_addr+6); 				/* reset flip-flop */
2622 	outb(ATC, 0x20);				/* enable Palette */
2623}
2624
2625
2626static void
2627copy_font(int direction, int segment, int size, char* font)
2628{
2629  	int ch, line, s;
2630	u_char val;
2631
2632 	outb(TSIDX, 0x01); val = inb(TSREG); 		/* blank screen */
2633	outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
2634
2635	/* setup vga for loading fonts (graphics plane mode) */
2636	s = splhigh();
2637	inb(crtc_addr+6);				/* reset flip/flop */
2638	outb(ATC, 0x30); outb(ATC, 0x01);
2639	outb(TSIDX, 0x02); outb(TSREG, 0x04);
2640	outb(TSIDX, 0x04); outb(TSREG, 0x06);
2641	outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
2642	outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
2643	outb(GDCIDX, 0x06); outb(GDCREG, 0x05);		/* addr = a0000, 64kb */
2644	splx(s);
2645    	for (ch=0; ch < 256; ch++)
2646	    for (line=0; line < size; line++)
2647		if (direction)
2648		    *((char *)atdevbase+(segment*0x4000)+(ch*32)+line) =
2649					font[(ch*size)+line];
2650		else
2651		    font[(ch*size)+line] =
2652		    *((char *)atdevbase+(segment*0x4000)+(ch*32)+line);
2653
2654	/* setup vga for text mode again */
2655	s = splhigh();
2656	inb(crtc_addr+6);				/* reset flip/flop */
2657	outb(ATC, 0x30); outb(ATC, 0x0C);
2658	outb(TSIDX, 0x02); outb(TSREG, 0x03);
2659	outb(TSIDX, 0x04); outb(TSREG, 0x02);
2660	outb(GDCIDX, 0x04); outb(GDCREG, 0x00);
2661	outb(GDCIDX, 0x05); outb(GDCREG, 0x10);
2662	if (crtc_addr == MONO_BASE) {
2663		outb(GDCIDX, 0x06); outb(GDCREG, 0x0A);	/* addr = b0000, 32kb */
2664	}
2665	else {
2666		outb(GDCIDX, 0x06); outb(GDCREG, 0x0E);	/* addr = b8000, 32kb */
2667	}
2668	splx(s);
2669 	outb(TSIDX, 0x01); val = inb(TSREG); 		/* unblank screen */
2670	outb(TSIDX, 0x01); outb(TSREG, val & 0xDF);
2671}
2672
2673
2674static void
2675load_palette(void)
2676{
2677	int i;
2678
2679  	outb(PIXMASK, 0xFF);			/* no pixelmask */
2680  	outb(PALWADR, 0x00);
2681  	for (i=0x00; i<0x300; i++)
2682    		 outb(PALDATA, palette[i]);
2683	inb(crtc_addr+6);			/* reset flip/flop */
2684	outb(ATC, 0x20);			/* enable palette */
2685}
2686
2687
2688static void
2689save_palette(void)
2690{
2691	int i;
2692
2693  	outb(PALRADR, 0x00);
2694  	for (i=0x00; i<0x300; i++)
2695    		palette[i] = inb(PALDATA);
2696	inb(crtc_addr+6);			/* reset flip/flop */
2697}
2698
2699
2700static void
2701change_winsize(struct tty *tp, int x, int y)
2702{
2703	if (tp->t_winsize.ws_col != x || tp->t_winsize.ws_row != y) {
2704		tp->t_winsize.ws_col = x;
2705		tp->t_winsize.ws_row = y;
2706		pgsignal(tp->t_pgrp, SIGWINCH, 1);
2707	}
2708}
2709
2710#endif /* NSC */
2711