syscons.c revision 5572
1162922Sariff/*-
2162922Sariff * Copyright (c) 1992-1995 S�ren Schmidt
3162922Sariff * Copyright (c) 1990 The Regents of the University of California.
4182999Smav * All rights reserved.
5162922Sariff *
6162922Sariff * This code is derived from software contributed to Berkeley by
7162922Sariff * William Jolitz and Don Ahn.
8162922Sariff *
9162922Sariff * Redistribution and use in source and binary forms, with or without
10162922Sariff * modification, are permitted provided that the following conditions
11162922Sariff * are met:
12162922Sariff * 1. Redistributions of source code must retain the above copyright
13162922Sariff *    notice, this list of conditions and the following disclaimer
14162922Sariff *    in this position and unchanged.
15162922Sariff * 2. Redistributions in binary form must reproduce the above copyright
16162922Sariff *    notice, this list of conditions and the following disclaimer in the
17162922Sariff *    documentation and/or other materials provided with the distribution.
18162922Sariff * 3. All advertising materials mentioning features or use of this software
19162922Sariff *    must display the following acknowledgement:
20162922Sariff *	This product includes software developed by the University of
21162922Sariff *	California, Berkeley and its contributors.
22162922Sariff * 4. Neither the name of the University nor the names of its contributors
23162922Sariff *    may be used to endorse or promote products derived from this software
24162922Sariff *    without specific prior written permission.
25162922Sariff *
26162922Sariff * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27162922Sariff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28162922Sariff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29162922Sariff * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30162922Sariff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31162922Sariff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32162922Sariff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33162922Sariff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34162922Sariff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35162922Sariff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36162922Sariff * SUCH DAMAGE.
37162922Sariff *
38162922Sariff *	$Id: syscons.c,v 1.91 1995/01/13 03:19:22 ache Exp $
39162922Sariff */
40162922Sariff
41162922Sariff#include "sc.h"
42162922Sariff
43162922Sariff#if NSC > 0
44162922Sariff
45162922Sariff#include <sys/param.h>
46162922Sariff#include <sys/systm.h>
47164614Sariff#include <sys/conf.h>
48162922Sariff#include <sys/ioctl.h>
49162922Sariff#include <sys/proc.h>
50162922Sariff#include <sys/user.h>
51162922Sariff#include <sys/tty.h>
52162922Sariff#include <sys/uio.h>
53162922Sariff#include <sys/callout.h>
54162922Sariff#include <sys/kernel.h>
55162922Sariff#include <sys/syslog.h>
56162922Sariff#include <sys/errno.h>
57162922Sariff#include <sys/malloc.h>
58162922Sariff#include <sys/devconf.h>
59162922Sariff
60162922Sariff#include <machine/clock.h>
61162922Sariff#include <machine/console.h>
62162922Sariff#include <machine/psl.h>
63162922Sariff#include <machine/frame.h>
64182999Smav#include <machine/pc/display.h>
65162922Sariff
66162922Sariff#include <i386/isa/isa.h>
67162922Sariff#include <i386/isa/isa_device.h>
68162922Sariff#include <i386/isa/timerreg.h>
69162922Sariff#include <i386/isa/kbdtables.h>
70162922Sariff#include <i386/i386/cons.h>
71193640Sariff
72193640Sariff#if !defined(MAXCONS)
73193640Sariff#define MAXCONS 12
74193640Sariff#endif
75162922Sariff
76162922Sariff/* this may break on older VGA's but is usefull on real 32 bit systems */
77162922Sariff#define	bcopyw	bcopy
78162922Sariff
79171141Sariff#if defined(HARDFONTS)
80171141Sariff#include <i386/isa/iso8859.font>
81171141Sariff#endif
82162922Sariff
83162922Sariff/* vm things */
84162922Sariff#define	ISMAPPED(pa, width) \
85162922Sariff	(((pa) <= (u_long)0x1000 - (width)) \
86162922Sariff	 || ((pa) >= 0xa0000 && (pa) <= 0x100000 - (width)))
87162922Sariff#define	pa_to_va(pa)	(KERNBASE + (pa))	/* works if ISMAPPED(pa...) */
88162922Sariff
89204351Smav/* status flags */
90162922Sariff#define LOCK_KEY_MASK	0x0000F
91162922Sariff#define LED_MASK	0x00007
92162922Sariff#define UNKNOWN_MODE	0x00010
93169277Sariff#define KBD_RAW_MODE	0x00020
94169277Sariff#define SWITCH_WAIT_REL	0x00040
95169277Sariff#define SWITCH_WAIT_ACQ	0x00080
96169277Sariff#define BUFFER_SAVED	0x00100
97193640Sariff
98162922Sariff/* configuration flags */
99183097Smav#define BLINK_CURSOR	0x00001
100183097Smav#define VISUAL_BELL	0x00002
101183097Smav
102183097Smav/* video hardware memory addresses */
103193640Sariff#define VIDEOMEM	0x000A0000
104183097Smav
105162965Sariff/* misc defines */
106162922Sariff#define MAX_ESC_PAR 	5
107162922Sariff#define	LOAD		1
108162922Sariff#define SAVE		0
109162922Sariff#define	COL		80
110162965Sariff#define	ROW		25
111162965Sariff#define BELL_DURATION	5
112163057Sariff#define BELL_PITCH	800
113163057Sariff#define TIMER_FREQ	1193182			/* should be in isa.h */
114162922Sariff#define CONSOLE_BUFSIZE 1024
115162965Sariff#define PCBURST		128
116163257Sariff#define FONT_8_LOADED	0x001
117163257Sariff#define FONT_14_LOADED	0x002
118163257Sariff#define FONT_16_LOADED	0x004
119163257Sariff#define HISTORY_SIZE	100*80
120163257Sariff
121163257Sariff/* defines related to hardware addresses */
122162965Sariff#define	MONO_BASE	0x3B4			/* crt controller base mono */
123162965Sariff#define	COLOR_BASE	0x3D4			/* crt controller base color */
124162965Sariff#define MISC		0x3C2			/* misc output register */
125169277Sariff#define ATC		IO_VGA+0x00		/* attribute controller */
126169277Sariff#define TSIDX		IO_VGA+0x04		/* timing sequencer idx */
127169277Sariff#define TSREG		IO_VGA+0x05		/* timing sequencer data */
128171141Sariff#define PIXMASK		IO_VGA+0x06		/* pixel write mask */
129171141Sariff#define PALRADR		IO_VGA+0x07		/* palette read address */
130171141Sariff#define PALWADR		IO_VGA+0x08		/* palette write address */
131171141Sariff#define PALDATA		IO_VGA+0x09		/* palette data register */
132171141Sariff#define GDCIDX		IO_VGA+0x0E		/* graph data controller idx */
133171141Sariff#define GDCREG		IO_VGA+0x0F		/* graph data controller data */
134171141Sariff
135171141Sariff/* special characters */
136162922Sariff#define cntlc	0x03
137162922Sariff#define cntld	0x04
138162922Sariff#define bs	0x08
139162922Sariff#define lf	0x0a
140162922Sariff#define cr	0x0d
141162922Sariff#define del	0x7f
142162922Sariff
143211910Sjfvtypedef struct term_stat {
144218149Sjfv	int 		esc;			/* processing escape sequence */
145221789Sjfv	int 		num_param;		/* # of parameters to ESC */
146162922Sariff	int	 	last_param;		/* last parameter # */
147171330Sariff	int 		param[MAX_ESC_PAR];	/* contains ESC parameters */
148162922Sariff	int 		cur_attr;		/* current attributes */
149163136Sariff	int 		std_attr;		/* normal attributes */
150171330Sariff	int 		rev_attr;		/* reverse attributes */
151197017Smav} term_stat;
152197017Smav
153187020Smavtypedef struct scr_stat {
154218149Sjfv	u_short 	*crt_base;		/* address of screen memory */
155184207Smav	u_short 	*scr_buf;		/* buffer when off screen */
156162922Sariff	u_short 	*crtat;			/* cursor address */
157162922Sariff	int 		xpos;			/* current X position */
158162922Sariff	int 		ypos;			/* current Y position */
159162922Sariff	int 		xsize;			/* X size */
160162922Sariff	int 		ysize;			/* Y size */
161162922Sariff	term_stat 	term;			/* terminal emulation stuff */
162173817Sariff	char		cursor_start;		/* cursor start line # */
163173817Sariff	char		cursor_end;		/* cursor end line # */
164173817Sariff	char		cursor_protect;		/* protect cursor */
165173817Sariff	u_short		cursor_saveunder;	/* saved char under cursor */
166173817Sariff	u_char		border;			/* border color */
167173817Sariff	u_short		bell_duration;
168186511Smav	u_short		bell_pitch;
169186511Smav	u_short 	status;			/* status (bitfield) */
170186511Smav	u_short 	mode;			/* mode */
171186511Smav	pid_t 		pid;			/* pid of controlling proc */
172186511Smav	struct proc 	*proc;			/* proc* of controlling proc */
173186511Smav	struct vt_mode 	smode;			/* switch mode */
174186511Smav	u_short		history[HISTORY_SIZE];
175186511Smav	u_short		*history_head;
176186511Smav	u_short		*history_pos;
177186511Smav} scr_stat;
178197018Smav
179197018Smavtypedef struct default_attr {
180197018Smav	int             std_attr;               /* normal attributes */
181197018Smav	int 		rev_attr;		/* reverse attributes */
182162922Sariff} default_attr;
183162922Sariff
184162922Sariffstatic default_attr user_default = {
185162922Sariff	(FG_LIGHTGREY | BG_BLACK) << 8,
186162922Sariff	(FG_BLACK | BG_LIGHTGREY) << 8
187163136Sariff};
188187020Smav
189187020Smavstatic default_attr kernel_default = {
190187020Smav	(FG_WHITE | BG_BLACK) << 8,
191187020Smav	(FG_BLACK | BG_LIGHTGREY) << 8
192187020Smav};
193187020Smav
194187020Smavstatic	scr_stat	main_console;
195187020Smavstatic	scr_stat	*console[MAXCONS];
196187020Smavstatic	scr_stat	*cur_console;
197187020Smavstatic	scr_stat	*new_scp, *old_scp;
198187020Smavstatic	term_stat	kernel_console;
199187020Smavstatic	default_attr	*current_default;
200187020Smav/* SOS
201162922Sariffstatic	int 		console_buffer_count;
202162922Sariffstatic	char 		console_buffer[CONSOLE_BUFSIZE];
203216766Syongari*/
204216766Syongaristatic	char		switch_in_progress = 0;
205216766Syongaristatic	char		blink_in_progress = 0;
206216766Syongaristatic	char 		write_in_progress = 0;
207163136Sariffstatic	char	 	polling = 0;
208163136Sariffstatic 	u_short	 	*crtat = 0;
209163136Sariffstatic	u_int		crtc_addr = MONO_BASE;
210163136Sariffstatic	char		crtc_vga = 0;
211163136Sariffstatic 	u_char		shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0;
212163136Sariffstatic 	u_char		nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0;
213163136Sariffstatic	char		*font_8 = NULL, *font_14 = NULL, *font_16 = NULL;
214163136Sariffstatic  int		fonts_loaded = 0;
215163136Sariffstatic	char		palette[3*256];
216163136Sariffstatic 	const u_int 	n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab);
217186301Smav#if ASYNCH
218186301Smavstatic  u_char		kbd_reply = 0;
219186301Smav#endif
220186301Smavstatic	int	 	delayed_next_scr;
221186301Smav#if 0 /* SOS */
222162922Sariffstatic	char		saved_console = -1;	/* saved console number	*/
223162922Sariff#endif
224165466Sariffstatic	int		configuration = 0;	/* current setup */
225165466Sariffstatic	long		scrn_blank_time = 0;	/* screen saver timeout value */
226165466Sariffstatic	int		scrn_blanked = 0;	/* screen saver active flag */
227162922Sariffstatic	int		scrn_saver = 0;		/* screen saver routine */
228162922Sariffstatic	long 		scrn_time_stamp;
229162922Sariffstatic  u_char		scr_map[256];
230162922Sariffstatic	char 		*video_mode_ptr = NULL;
231162922Sariff
232165281Sariff/* function prototypes */
233166294Sariffint pcprobe(struct isa_device *dev);
234169277Sariffint pcattach(struct isa_device *dev);
235169277Sariffint pcopen(dev_t dev, int flag, int mode, struct proc *p);
236174579Sariffint pcclose(dev_t dev, int flag, int mode, struct proc *p);
237172811Sariffint pcread(dev_t dev, struct uio *uio, int flag);
238162922Sariffint pcwrite(dev_t dev, struct uio *uio, int flag);
239165281Sariffint pcparam(struct tty *tp, struct termios *t);
240165281Sariffint pcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
241162922Sariffvoid pcxint(dev_t dev);
242162922Sariffvoid pcstart(struct tty *tp);
243162922Sariffvoid pccnprobe(struct consdev *cp);
244180532Sdelphijvoid pccninit(struct consdev *cp);
245162922Sariffvoid pccnputc(dev_t dev, char c);
246184483Smavint pccngetc(dev_t dev);
247178155Sariffint pccncheckc(dev_t dev);
248162922Sariffvoid scintr(int unit);
249169277Sariffint pcmmap(dev_t dev, int offset, int nprot);
250169277Sariffint getchar(void);
251162922Sariffstatic void scinit(void);
252162922Sariffstatic void scput(u_char c);
253162922Sariffstatic u_int scgetc(int noblock);
254162922Sariffstatic struct tty *get_tty_ptr(dev_t dev);
255162922Sariffstatic scr_stat *get_scr_stat(dev_t dev);
256162922Sariffstatic scr_stat *alloc_scp();
257162922Sariffstatic void init_scp(scr_stat *scp);
258162922Sariffstatic int get_scr_num();
259162922Sariffstatic void cursor_shape(int start, int end);
260165992Sariffstatic void get_cursor_shape(int *start, int *end);
261173817Sariffstatic void scrn_timer();
262174182Sariffstatic void clear_screen(scr_stat *scp);
263182854Sjoelstatic int switch_scr(scr_stat *scp, u_int next_scr);
264169277Sariffstatic void exchange_scr(void);
265182999Smavstatic void move_crsr(scr_stat *scp, int x, int y);
266189879Smavstatic void scan_esc(scr_stat *scp, u_char c);
267162922Sariffstatic void undraw_cursor(scr_stat *scp);
268162922Sariffstatic void draw_cursor(scr_stat *scp);
269162965Sariffstatic void ansi_put(scr_stat *scp, u_char c);
270162965Sariffstatic u_char *get_fstr(u_int c, u_int *len);
271178155Sariffstatic void update_leds(int which);
272163276Sariffstatic void kbd_wait(void);
273178155Sariffstatic void kbd_cmd(u_char command);
274165281Sariffstatic void set_mode(scr_stat *scp);
275178155Sariffstatic void set_border(int color);
276178155Sariffstatic void set_vgaregs(char *modetable);
277167623Sariffstatic void copy_font(int direction, int segment, int size, char* font);
278169277Sariffstatic void save_palette(void);
279178155Sariffstatic void load_palette(void);
280190630Smavstatic void do_bell(scr_stat *scp, int pitch, int duration);
281178155Sariffstatic void blink_screen(scr_stat *scp);
282178155Sariff
283170518Sariff/* available screen savers */
284178155Sariffstatic void none_saver(int test);
285169277Sariffstatic void blank_saver(int test);
286171141Sariffstatic void fade_saver(int test);
287162965Sariffstatic void star_saver(int test);
288162922Sariffstatic void snake_saver(int test);
289163257Sariffstatic void green_saver(int test);
290163257Sariff
291163257Sariffstatic const struct {
292163257Sariff	char	*name;
293162965Sariff	void	(*routine)();
294164614Sariff} screen_savers[] = {
295164657Sariff	{ "none",	none_saver },	/* 0 */
296164657Sariff	{ "blank",	blank_saver },	/* 1 */
297182854Sjoel	{ "fade",	fade_saver },	/* 2 */
298172811Sariff	{ "star",	star_saver },	/* 3 */
299164657Sariff	{ "snake",	snake_saver },	/* 4 */
300163257Sariff	{ "green",	green_saver },	/* 5 */
301164657Sariff};
302164657Sariff#define SCRN_SAVER(arg)	(*screen_savers[scrn_saver].routine)(arg)
303164657Sariff#define NUM_SCRN_SAVERS	(sizeof(screen_savers) / sizeof(screen_savers[0]))
304164657Sariff
305164614Sariff/* OS specific stuff */
306164750Sariff#if 0
307164750Sariff#define VIRTUAL_TTY(x)	(pccons[x] = ttymalloc(pccons[x]))
308164750Sariffstruct	tty 		*pccons[MAXCONS];
309164750Sariff#else
310164750Sariff#define VIRTUAL_TTY(x)	&pccons[x]
311173817Sariffstruct	tty 		pccons[MAXCONS];
312173817Sariffint			npccons	= MAXCONS;
313173817Sariff#endif
314173817Sariff#define	MONO_BUF	pa_to_va(0xB0000)
315182999Smav#define	CGA_BUF		pa_to_va(0xB8000)
316182999Smavu_short			*Crtat = (u_short *)MONO_BUF;
317182999Smav/*void 	consinit(void) 	{scinit();} SOS */
318182999Smav
319182999Smavstruct	isa_driver scdriver = {
320164828Sariff	pcprobe, pcattach, "sc", 1
321164828Sariff};
322164828Sariff
323164828Sariffint
324164828Sariffpcprobe(struct isa_device *dev)
325164828Sariff{
326199846Smav	int i, retries = 5;
327164828Sariff	unsigned char val;
328165281Sariff
329165281Sariff	/* Enable interrupts and keyboard controller */
330165281Sariff	kbd_wait();
331165281Sariff	outb(KB_STAT, KB_WRITE);
332165281Sariff	kbd_wait();
333165351Sariff	outb(KB_DATA, KB_MODE);
334165351Sariff
335165351Sariff	/* flush any noise in the buffer */
336172811Sariff	while (inb(KB_STAT) & KB_BUF_FULL) {
337165351Sariff		DELAY(10);
338165351Sariff		(void) inb(KB_DATA);
339172811Sariff	}
340172811Sariff
341172811Sariff	/* Reset keyboard hardware */
342182854Sjoel	while (retries--) {
343172811Sariff		kbd_wait();
344172811Sariff		outb(KB_DATA, KB_RESET);
345165770Sariff		for (i=0; i<100000; i++) {
346165770Sariff			DELAY(10);
347165770Sariff			val = inb(KB_DATA);
348173817Sariff			if (val == KB_ACK || val == KB_ECHO)
349165770Sariff				goto gotres;
350165770Sariff			if (val == KB_RESEND)
351165992Sariff				break;
352165992Sariff		}
353165992Sariff	}
354172811Sariffgotres:
355165992Sariff	if (!retries)
356165992Sariff		printf("scprobe: keyboard won't accept RESET command\n");
357172811Sariff	else {
358172811Sariffgotack:
359172811Sariff		DELAY(10);
360172811Sariff		while ((inb(KB_STAT) & KB_BUF_FULL) == 0) DELAY(10);
361172811Sariff		DELAY(10);
362169277Sariff		val = inb(KB_DATA);
363169277Sariff		if (val == KB_ACK)
364169277Sariff			goto gotack;
365170944Sariff		if (val != KB_RESET_DONE)
366169277Sariff			printf("scprobe: keyboard RESET failed %02x\n", val);
367169277Sariff	}
368162922Sariff#ifdef XT_KEYBOARD
369182999Smav	kbd_wait();
370162922Sariff	outb(KB_DATA, 0xF0);
371162922Sariff	kbd_wait();
372162922Sariff	outb(KB_DATA, 1)
373162922Sariff	kbd_wait();
374162922Sariff#endif /* XT_KEYBOARD */
375162922Sariff	return (IO_KBDSIZE);
376162922Sariff}
377162922Sariff
378162922Sariffstatic struct kern_devconf kdc_sc[NSC] = { {
379182999Smav	0, 0, 0,		/* filled in by dev_attach */
380162922Sariff	"sc", 0, { MDDT_ISA, 0, "tty" },
381182999Smav	isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,
382182999Smav	&kdc_isa0,		/* parent */
383169277Sariff	0,			/* parentdata */
384169277Sariff	DC_UNKNOWN,		/* not supported */
385169277Sariff	"Graphics console"
386163057Sariff} };
387163057Sariff
388163057Sariffstatic inline void
389169277Sariffsc_registerdev(struct isa_device *id)
390169277Sariff{
391169277Sariff	if(id->id_unit)
392169277Sariff		kdc_sc[id->id_unit] = kdc_sc[0];
393169277Sariff	kdc_sc[id->id_unit].kdc_unit = id->id_unit;
394169277Sariff	kdc_sc[id->id_unit].kdc_isa = id;
395162922Sariff	dev_attach(&kdc_sc[id->id_unit]);
396169277Sariff}
397169277Sariff
398169277Sariff
399169277Sariffint
400169277Sariffpcattach(struct isa_device *dev)
401169277Sariff{
402182999Smav	if (crtat == 0)
403169277Sariff		scinit();
404169277Sariff
405169277Sariff	configuration = dev->id_flags;
406169277Sariff	printf("sc%d: ", dev->id_unit);
407169277Sariff	if (crtc_vga)
408169277Sariff		if (crtc_addr == MONO_BASE)
409169277Sariff			printf("VGA mono");
410169277Sariff		else
411169277Sariff			printf("VGA color");
412169277Sariff	else
413169277Sariff		if (crtc_addr == MONO_BASE)
414169277Sariff			printf("MDA/hercules");
415169277Sariff		else
416169277Sariff			printf("CGA/EGA");
417169277Sariff	if (MAXCONS > 1)
418171141Sariff		printf(" <%d virtual consoles, flags=%x>\n",
419171141Sariff			MAXCONS, configuration);
420171141Sariff	else
421171141Sariff		printf("\n");
422163057Sariff	console[0]->scr_buf =
423163057Sariff		(u_short *)malloc(console[0]->xsize * console[0]->ysize *
424163057Sariff				  sizeof(u_short), M_DEVBUF, M_NOWAIT);
425163057Sariff	if (crtc_vga) {
426163057Sariff#if defined(HARDFONTS)
427163057Sariff		font_8 = font_8x8;
428163057Sariff		font_14 = font_8x14;
429169277Sariff		font_16 = font_8x16;
430169277Sariff		fonts_loaded = FONT_8_LOADED|FONT_14_LOADED|FONT_16_LOADED;
431169277Sariff		copy_font(LOAD, 1, 8, font_8);
432169277Sariff		copy_font(LOAD, 2, 14, font_14);
433169277Sariff		copy_font(LOAD, 0, 16, font_16);
434165039Sariff#else
435163057Sariff		font_8 = (char *)malloc(8*256, M_DEVBUF, M_NOWAIT);
436163057Sariff		font_14 = (char *)malloc(14*256, M_DEVBUF, M_NOWAIT);
437163136Sariff		font_16 = (char *)malloc(16*256, M_DEVBUF, M_NOWAIT);
438163276Sariff		copy_font(SAVE, 0, 16, font_16);
439169277Sariff		fonts_loaded = FONT_16_LOADED;
440182999Smav#endif
441169277Sariff		save_palette();
442169277Sariff	}
443169277Sariff	/* get screensaver going */
444169277Sariff	scrn_timer();
445169277Sariff	update_leds(console[0]->status);
446169277Sariff	sc_registerdev(dev);
447169277Sariff	return 0;
448169277Sariff}
449165069Sariff
450163057Sariffstatic struct tty
451163057Sariff*get_tty_ptr(dev_t dev)
452163057Sariff{
453163057Sariff	int unit = minor(dev);
454162922Sariff
455162922Sariff	if (unit > MAXCONS)
456162922Sariff		return(NULL);
457162922Sariff	return(VIRTUAL_TTY(unit));
458169277Sariff}
459167648Sariff
460167648Sariffstatic scr_stat
461162922Sariff*get_scr_stat(dev_t dev)
462162922Sariff{
463162922Sariff	int unit = minor(dev);
464162922Sariff
465162922Sariff	if (unit > MAXCONS)
466162922Sariff		return(NULL);
467169277Sariff	return(console[unit]);
468162922Sariff}
469165239Sariff
470162922Sariffstatic int
471182999Smavget_scr_num()
472182999Smav{
473182999Smav	int i = 0;
474162922Sariff
475182999Smav	while ((i < MAXCONS) && (cur_console != console[i])) i++;
476182999Smav	return i < MAXCONS ? i : 0;
477182999Smav}
478182999Smav
479182999Smavint
480182999Smavpcopen(dev_t dev, int flag, int mode, struct proc *p)
481162922Sariff{
482162922Sariff	struct tty *tp = get_tty_ptr(dev);
483193640Sariff
484162922Sariff	if (!tp)
485162922Sariff		return(ENXIO);
486162922Sariff
487162922Sariff	tp->t_oproc = pcstart;
488162922Sariff	tp->t_param = pcparam;
489189086Smav	tp->t_dev = dev;
490194861Smav	if (!(tp->t_state & TS_ISOPEN)) {
491189086Smav		ttychars(tp);
492162922Sariff		tp->t_iflag = TTYDEF_IFLAG;
493162922Sariff		tp->t_oflag = TTYDEF_OFLAG;
494162922Sariff		tp->t_cflag = TTYDEF_CFLAG;
495189086Smav		tp->t_lflag = TTYDEF_LFLAG;
496162922Sariff		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
497211910Sjfv		pcparam(tp, &tp->t_termios);
498218149Sjfv		ttsetwater(tp);
499221794Sjfv	} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
500189086Smav		return(EBUSY);
501189086Smav	tp->t_state |= TS_CARR_ON;
502189086Smav	tp->t_cflag |= CLOCAL;
503189086Smav	if (!console[minor(dev)])
504189086Smav		console[minor(dev)] = alloc_scp();
505197017Smav	return((*linesw[tp->t_line].l_open)(dev, tp));
506197017Smav}
507218149Sjfv
508218149Sjfvint
509189086Smavpcclose(dev_t dev, int flag, int mode, struct proc *p)
510189086Smav{
511195690Smav	struct tty *tp = get_tty_ptr(dev);
512189086Smav	struct scr_stat *scp;
513189086Smav
514189086Smav	if (!tp)
515189086Smav		return(ENXIO);
516189086Smav	scp = get_scr_stat(tp->t_dev);
517189086Smav	if (scp->status & SWITCH_WAIT_ACQ)
518189086Smav		wakeup((caddr_t)&scp->smode);
519189086Smav	scp->pid = 0;
520194861Smav	scp->proc = NULL;
521194861Smav	scp->smode.mode = VT_AUTO;
522194861Smav	/* free scp SOS */
523194861Smav	(*linesw[tp->t_line].l_close)(tp, flag);
524189086Smav	ttyclose(tp);
525189086Smav	return(0);
526189086Smav}
527189086Smav
528197018Smavint
529197018Smavpcread(dev_t dev, struct uio *uio, int flag)
530197018Smav{
531197018Smav	struct tty *tp = get_tty_ptr(dev);
532189086Smav
533189086Smav	if (!tp)
534189086Smav		return(ENXIO);
535189086Smav	return((*linesw[tp->t_line].l_read)(tp, uio, flag));
536189086Smav}
537189086Smav
538189086Smavint
539189086Smavpcwrite(dev_t dev, struct uio *uio, int flag)
540189086Smav{
541189086Smav	struct tty *tp = get_tty_ptr(dev);
542189086Smav
543189086Smav	if (!tp)
544189086Smav		return(ENXIO);
545189086Smav	return((*linesw[tp->t_line].l_write)(tp, uio, flag));
546216766Syongari}
547189086Smav
548189086Smavvoid
549189086Smavscintr(int unit)
550162922Sariff{
551162922Sariff	static struct tty *cur_tty;
552162922Sariff	int c, len;
553162922Sariff	u_char *cp;
554163136Sariff
555163136Sariff	/* make screensaver happy */
556186301Smav	scrn_time_stamp = time.tv_sec;
557162922Sariff	if (scrn_blanked)
558162922Sariff		SCRN_SAVER(0);
559162922Sariff
560162922Sariff	c = scgetc(1);
561169277Sariff
562169277Sariff	cur_tty = VIRTUAL_TTY(get_scr_num());
563169277Sariff
564169277Sariff	if (!(cur_tty->t_state & TS_ISOPEN) || polling)
565169277Sariff		return;
566169277Sariff
567169277Sariff	switch (c & 0xff00) {
568169277Sariff	case 0x0000: /* normal key */
569169277Sariff		(*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
570169277Sariff		break;
571169277Sariff	case NOKEY:	/* nothing there */
572169277Sariff		break;
573169277Sariff	case FKEY:	/* function key, return string */
574162922Sariff		if (cp = get_fstr((u_int)c, (u_int *)&len)) {
575162922Sariff			while (len-- >  0)
576162922Sariff				(*linesw[cur_tty->t_line].l_rint)
577162922Sariff					(*cp++ & 0xFF, cur_tty);
578162922Sariff		}
579162922Sariff		break;
580162922Sariff	case MKEY:	/* meta is active, prepend ESC */
581162922Sariff		(*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
582162922Sariff		(*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
583162922Sariff		break;
584162922Sariff	}
585162922Sariff}
586162922Sariff
587162922Sariffint
588162922Sariffpcparam(struct tty *tp, struct termios *t)
589162922Sariff{
590162922Sariff	int cflag = t->c_cflag;
591162922Sariff
592162922Sariff	/* and copy to tty */
593162922Sariff	tp->t_ispeed = t->c_ispeed;
594162922Sariff	tp->t_ospeed = t->c_ospeed;
595162922Sariff	tp->t_cflag = cflag;
596162922Sariff	return 0;
597162922Sariff}
598162922Sariff
599162922Sariffint
600162922Sariffpcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
601162922Sariff{
602162922Sariff	int i, error;
603162922Sariff	struct tty *tp;
604162922Sariff	struct trapframe *fp;
605162922Sariff	scr_stat *scp;
606162922Sariff
607162922Sariff	tp = get_tty_ptr(dev);
608162922Sariff	if (!tp)
609162922Sariff		return ENXIO;
610162922Sariff	scp = get_scr_stat(tp->t_dev);
611162922Sariff
612162922Sariff	switch (cmd) {	/* process console hardware related ioctl's */
613162922Sariff
614162922Sariff	case GIO_ATTR:		/* get current attributes */
615162922Sariff		*(int*)data = scp->term.cur_attr;
616162922Sariff		return 0;
617162922Sariff
618162922Sariff	case GIO_COLOR:		/* is this a color console ? */
619162922Sariff		if (crtc_addr == COLOR_BASE)
620162922Sariff			*(int*)data = 1;
621162922Sariff		else
622199846Smav			*(int*)data = 0;
623199846Smav		return 0;
624199846Smav
625199846Smav	case CONS_CURRENT:	/* get current adapter type */
626200375Smav		if (crtc_vga)
627199846Smav			*(int*)data = KD_VGA;
628162922Sariff		else
629162922Sariff			if (crtc_addr == MONO_BASE)
630162922Sariff				*(int*)data = KD_MONO;
631169277Sariff			else
632183024Smav				*(int*)data = KD_CGA;
633171330Sariff		return 0;
634183024Smav
635205413Smav	case CONS_GET:		/* get current video mode */
636183024Smav		*(int*)data = scp->mode;
637205413Smav		return 0;
638205413Smav
639170518Sariff	case CONS_BLANKTIME:	/* set screen saver timeout (0 = no saver) */
640183024Smav		scrn_blank_time = *(int*)data;
641183025Smav		return 0;
642205413Smav
643162922Sariff#define	SAVER(p) ((ssaver_t *)(p))
644169277Sariff	case CONS_SSAVER:	/* set screen saver */
645162922Sariff		if (SAVER(data)->num < 0
646163057Sariff		    || SAVER(data)->num >= NUM_SCRN_SAVERS)
647163057Sariff			return EIO;
648169277Sariff		SCRN_SAVER(0);
649197640Smav		scrn_saver = SAVER(data)->num;
650165305Sariff		scrn_blank_time = SAVER(data)->time;
651182999Smav		return 0;
652205413Smav
653162922Sariff	case CONS_GSAVER:	/* get screen saver info */
654162922Sariff		if (SAVER(data)->num < 0)
655169277Sariff			SAVER(data)->num = scrn_saver;
656169277Sariff		else if (SAVER(data)->num >= NUM_SCRN_SAVERS)
657186403Smav			return EIO;
658186403Smav		SAVER(data)->time = scrn_blank_time;
659186403Smav		strcpy(SAVER(data)->name, screen_savers[SAVER(data)->num].name);
660186403Smav		return 0;
661186403Smav
662186403Smav	case CONS_CURSORTYPE:	/* set cursor type blink/noblink */
663169277Sariff		if (*data)
664169277Sariff			configuration |= BLINK_CURSOR;
665174025Sariff		else
666169277Sariff			configuration &= ~BLINK_CURSOR;
667186403Smav		return 0;
668169277Sariff
669170518Sariff	case CONS_BELLTYPE:	/* set bell type sound/visual */
670186403Smav		if (*data)
671186403Smav			configuration |= VISUAL_BELL;
672169277Sariff		else
673162922Sariff			configuration &= ~VISUAL_BELL;
674162922Sariff		return 0;
675162922Sariff
676162922Sariff	case CONS_GETINFO:	/* get current (virtual) console info */
677162922Sariff	{
678162922Sariff		vid_info_t *ptr = (vid_info_t*)data;
679162922Sariff		if (ptr->size == sizeof(struct vid_info)) {
680162922Sariff			ptr->m_num = get_scr_num();
681182999Smav			ptr->mv_col = scp->xpos;
682182999Smav			ptr->mv_row = scp->ypos;
683182999Smav			ptr->mv_csz = scp->xsize;
684182999Smav			ptr->mv_rsz = scp->ysize;
685182999Smav			ptr->mv_norm.fore = (scp->term.std_attr & 0x0f00)>>8;
686182999Smav			ptr->mv_norm.back = (scp->term.std_attr & 0xf000)>>12;
687182999Smav			ptr->mv_rev.fore = (scp->term.rev_attr & 0x0f00)>>8;
688182999Smav			ptr->mv_rev.back = (scp->term.rev_attr & 0xf000)>>12;
689183894Smav			ptr->mv_grfc.fore = 0;		/* not supported */
690183894Smav			ptr->mv_grfc.back = 0;		/* not supported */
691183894Smav			ptr->mv_ovscan = scp->border;
692183894Smav			ptr->mk_keylock = scp->status & LOCK_KEY_MASK;
693183894Smav			return 0;
694183894Smav		}
695183894Smav		return EINVAL;
696182999Smav	}
697183894Smav
698183894Smav	case CONS_GETVERS:	/* get version number */
699183894Smav		*(int*)data = 0x200;	/* version 2.0 */
700183894Smav		return 0;
701183894Smav
702183894Smav        case SW_VGA_C40x25: case SW_VGA_C80x25:	/* VGA TEXT MODES */
703183894Smav        case SW_VGA_M80x25:
704183894Smav        case SW_VGA_C80x30: case SW_VGA_M80x30:
705200375Smav        case SW_VGA_C80x50: case SW_VGA_M80x50:
706182999Smav        case SW_VGA_C80x60: case SW_VGA_M80x60:
707200375Smav        case SW_B40x25:     case SW_C40x25:
708162922Sariff        case SW_B80x25:     case SW_C80x25:
709182999Smav        case SW_ENH_B40x25: case SW_ENH_C40x25:
710183894Smav        case SW_ENH_B80x25: case SW_ENH_C80x25:
711162922Sariff        case SW_ENH_B80x43: case SW_ENH_C80x43:
712162922Sariff
713183894Smav        	if (!crtc_vga || video_mode_ptr == NULL)
714183894Smav        		return ENXIO;
715183894Smav		switch (cmd & 0xff) {
716183894Smav		case M_VGA_C80x60: case M_VGA_M80x60:
717183894Smav			if (!(fonts_loaded & FONT_8_LOADED))
718183894Smav				return EINVAL;
719183894Smav			scp->xsize = 80;
720183894Smav			scp->ysize = 60;
721183894Smav			break;
722162922Sariff		case M_VGA_C80x50: case M_VGA_M80x50:
723162922Sariff			if (!(fonts_loaded & FONT_8_LOADED))
724183894Smav				return EINVAL;
725183894Smav			scp->xsize = 80;
726183894Smav			scp->ysize = 50;
727183894Smav			break;
728183894Smav        	case M_ENH_B80x43: case M_ENH_C80x43:
729183894Smav			if (!(fonts_loaded & FONT_8_LOADED))
730183894Smav				return EINVAL;
731183894Smav			scp->xsize = 80;
732183894Smav			scp->ysize = 43;
733183894Smav			break;
734183894Smav		case M_VGA_C80x30: case M_VGA_M80x30:
735183894Smav			scp->xsize = 80;
736183894Smav			scp->ysize = 30;
737183894Smav			break;
738183894Smav		default:
739183894Smav			if ((cmd & 0xff) > M_VGA_CG320)
740182999Smav				return EINVAL;
741182999Smav			else
742187020Smav            		    scp->xsize = *(video_mode_ptr+((cmd&0xff)*64));
743186146Smav            		    scp->ysize = *(video_mode_ptr+((cmd&0xff)*64)+1)+1;
744182999Smav			break;
745182999Smav		}
746182999Smav		scp->mode = cmd & 0xff;
747182999Smav            	scp->status &= ~UNKNOWN_MODE;	/* text mode */
748182999Smav		free(scp->scr_buf, M_DEVBUF);
749182999Smav		scp->scr_buf = (u_short *)malloc(scp->xsize * scp->ysize *
750186430Smav				sizeof(u_short), M_DEVBUF, M_NOWAIT);
751162922Sariff		if (scp == cur_console)
752186430Smav            		set_mode(scp);
753186430Smav		else
754186430Smav			scp->crt_base = scp->scr_buf;
755200375Smav            	clear_screen(scp);
756205413Smav		if (tp->t_winsize.ws_col != scp->xsize
757223058Smav		    || tp->t_winsize.ws_row != scp->ysize) {
758208934Smav			tp->t_winsize.ws_col = scp->xsize;
759223058Smav			tp->t_winsize.ws_row = scp->ysize;
760223058Smav			pgsignal(tp->t_pgrp, SIGWINCH, 1);
761223058Smav		}
762223058Smav            	return 0;
763223058Smav
764223058Smav        /* GRAPHICS MODES */
765223058Smav        case SW_BG320:      case SW_CG320:      case SW_BG640:
766223058Smav        case SW_CG320_D:    case SW_CG640_E:
767223058Smav        case SW_CG640x350:  case SW_ENH_CG640:
768162922Sariff        case SW_BG640x480:  case SW_CG640x480:  case SW_VGA_CG320:
769162922Sariff
770169277Sariff        	if (!crtc_vga || video_mode_ptr == NULL)
771169277Sariff        		return ENXIO;
772169277Sariff	    	scp->mode = cmd & 0xFF;
773169277Sariff            	scp->status |= UNKNOWN_MODE;	/* graphics mode */
774169277Sariff            	scp->xsize = (*(video_mode_ptr + (scp->mode*64))) * 8;
775169277Sariff            	scp->ysize = (*(video_mode_ptr + (scp->mode*64) + 1) + 1)
776169277Sariff		    	   * (*(video_mode_ptr + (scp->mode*64) + 2));
777169277Sariff            	set_mode(scp);
778169277Sariff            	/* clear_graphics();*/
779169277Sariff
780169277Sariff		if (tp->t_winsize.ws_xpixel != scp->xsize
781169277Sariff		    || tp->t_winsize.ws_ypixel != scp->ysize) {
782169277Sariff			tp->t_winsize.ws_xpixel = scp->xsize;
783186145Smav			tp->t_winsize.ws_ypixel = scp->ysize;
784186145Smav			pgsignal(tp->t_pgrp, SIGWINCH, 1);
785186145Smav		}
786186145Smav            	return 0;
787186145Smav
788186145Smav	case VT_SETMODE:	/* set screen switcher mode */
789186145Smav		bcopy(data, &scp->smode, sizeof(struct vt_mode));
790186145Smav		if (scp->smode.mode == VT_PROCESS) {
791187020Smav			scp->proc = p;
792187020Smav			scp->pid = scp->proc->p_pid;
793187020Smav		}
794187020Smav		return 0;
795187020Smav
796187020Smav	case VT_GETMODE:	/* get screen switcher mode */
797187020Smav		bcopy(&scp->smode, data, sizeof(struct vt_mode));
798187020Smav		return 0;
799187020Smav
800187020Smav	case VT_RELDISP:	/* screen switcher ioctl */
801187020Smav		switch(*data) {
802187020Smav		case VT_FALSE:	/* user refuses to release screen, abort */
803187020Smav			if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
804187020Smav				old_scp->status &= ~SWITCH_WAIT_REL;
805187020Smav				switch_in_progress = 0;
806187020Smav				return 0;
807199258Smav			}
808199258Smav			return EINVAL;
809199258Smav
810199258Smav		case VT_TRUE:	/* user has released screen, go on */
811199258Smav			if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
812199258Smav				scp->status &= ~SWITCH_WAIT_REL;
813199258Smav				exchange_scr();
814199258Smav				if (new_scp->smode.mode == VT_PROCESS) {
815199258Smav					new_scp->status |= SWITCH_WAIT_ACQ;
816199258Smav					psignal(new_scp->proc,
817169277Sariff						new_scp->smode.acqsig);
818162922Sariff				}
819182999Smav				else
820186146Smav					switch_in_progress = 0;
821186146Smav				return 0;
822186146Smav			}
823186146Smav			return EINVAL;
824182999Smav
825169277Sariff		case VT_ACKACQ:	/* acquire acknowledged, switch completed */
826182999Smav			if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) {
827187020Smav				scp->status &= ~SWITCH_WAIT_ACQ;
828187445Smav				switch_in_progress = 0;
829187020Smav				return 0;
830208934Smav			}
831208934Smav			return EINVAL;
832208934Smav
833208934Smav		default:
834187020Smav			return EINVAL;
835187445Smav		}
836182999Smav		/* NOT REACHED */
837182999Smav
838183894Smav	case VT_OPENQRY:	/* return free virtual console */
839222298Smav 		for (i = 0; i < MAXCONS; i++) {
840222298Smav			tp = VIRTUAL_TTY(i);
841222298Smav 			if (!(tp->t_state & TS_ISOPEN)) {
842222298Smav 				*data = i + 1;
843222298Smav 				return 0;
844222298Smav 			}
845222298Smav		}
846183894Smav 		return EINVAL;
847183894Smav
848162922Sariff	case VT_ACTIVATE:	/* switch to screen *data */
849162922Sariff		return switch_scr(scp, (*data) - 1);
850162922Sariff
851162922Sariff	case VT_WAITACTIVE:	/* wait for switch to occur */
852162922Sariff		if (*data > MAXCONS || *data < 0)
853199846Smav			return EINVAL;
854199846Smav		if (minor(dev) == (*data) - 1)
855162922Sariff			return 0;
856169277Sariff		if (*data == 0) {
857183024Smav			if (scp == cur_console)
858171330Sariff				return 0;
859183024Smav		}
860205413Smav		else
861183024Smav			scp = console[(*data) - 1];
862205413Smav		while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH,
863205413Smav			"waitvt", 0)) == ERESTART) ;
864170518Sariff		return error;
865183024Smav
866183024Smav	case VT_GETACTIVE:
867205413Smav		*data = get_scr_num()+1;
868162922Sariff		return 0;
869169277Sariff
870162922Sariff	case KDENABIO:		/* allow io operations */
871162922Sariff	 	fp = (struct trapframe *)p->p_md.md_regs;
872163057Sariff	 	fp->tf_eflags |= PSL_IOPL;
873169277Sariff		return 0;
874197640Smav
875165305Sariff	case KDDISABIO:		/* disallow io operations (default) */
876182999Smav	 	fp = (struct trapframe *)p->p_md.md_regs;
877205413Smav	 	fp->tf_eflags &= ~PSL_IOPL;
878186403Smav	 	return 0;
879186403Smav
880186403Smav        case KDSETMODE:		/* set current mode of this (virtual) console */
881186403Smav		switch (*data) {
882186403Smav		case KD_TEXT:	/* switch to TEXT (known) mode */
883169277Sariff				/* restore fonts & palette ! */
884169277Sariff			if (crtc_vga) {
885174025Sariff				if (fonts_loaded & FONT_16_LOADED)
886186403Smav					copy_font(LOAD, 0, 16, font_16);
887186403Smav				if (fonts_loaded & FONT_8_LOADED)
888169277Sariff					copy_font(LOAD, 1, 8, font_8);
889186403Smav				if (fonts_loaded & FONT_14_LOADED)
890186403Smav					copy_font(LOAD, 2, 14, font_14);
891170518Sariff				load_palette();
892186403Smav			}
893162922Sariff			/* FALL THROUGH */
894200375Smav
895200375Smav		case KD_TEXT1:	/* switch to TEXT (known) mode */
896183894Smav				/* no restore fonts & palette */
897183894Smav			scp->status &= ~UNKNOWN_MODE;
898183894Smav        		if (crtc_vga && video_mode_ptr)
899183894Smav				set_mode(scp);
900183894Smav			clear_screen(scp);
901183894Smav			return 0;
902183894Smav
903183894Smav		case KD_GRAPHICS:/* switch to GRAPHICS (unknown) mode */
904162922Sariff			scp->status |= UNKNOWN_MODE;
905183894Smav			return 0;
906162922Sariff		default:
907162922Sariff			return EINVAL;
908183894Smav		}
909183894Smav		/* NOT REACHED */
910183894Smav
911183894Smav	case KDGETMODE:		/* get current mode of this (virtual) console */
912183894Smav		*data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT;
913183894Smav		return 0;
914182999Smav
915182999Smav	case KDSBORDER:		/* set border color of this (virtual) console */
916183894Smav		if (!crtc_vga)
917183894Smav			return ENXIO;
918183894Smav		scp->border = *data;
919166796Sariff		if (scp == cur_console)
920183894Smav			set_border(scp->border);
921183894Smav		return 0;
922183894Smav
923183894Smav	case KDSKBSTATE:	/* set keyboard state (locks) */
924183894Smav		if (*data >= 0 && *data <= LOCK_KEY_MASK) {
925183894Smav			scp->status &= ~LOCK_KEY_MASK;
926183894Smav			scp->status |= *data;
927183894Smav			if (scp == cur_console)
928183894Smav				update_leds(scp->status);
929183894Smav			return 0;
930183894Smav		}
931183894Smav		return EINVAL;
932183894Smav
933183894Smav	case KDGKBSTATE:	/* get keyboard state (locks) */
934183894Smav		*data = scp->status & LOCK_KEY_MASK;
935183894Smav		return 0;
936183894Smav
937183894Smav	case KDSETRAD:		/* set keyboard repeat & delay rates */
938183894Smav		if (*data & 0x80)
939183894Smav			return EINVAL;
940183894Smav		i = spltty();
941183894Smav		kbd_cmd(KB_SETRAD);
942183894Smav		kbd_cmd(*data);
943183894Smav		splx(i);
944183894Smav		return 0;
945183894Smav
946183894Smav	case KDSKBMODE:		/* set keyboard mode */
947186430Smav		switch (*data) {
948186430Smav		case K_RAW:	/* switch to RAW scancode mode */
949186430Smav			scp->status |= KBD_RAW_MODE;
950200375Smav			return 0;
951205413Smav
952223058Smav		case K_XLATE:	/* switch to XLT ascii mode */
953208934Smav			if (scp == cur_console && scp->status == KBD_RAW_MODE)
954223058Smav				shfts = ctls = alts = agrs = metas = 0;
955223058Smav			scp->status &= ~KBD_RAW_MODE;
956223058Smav			return 0;
957223058Smav		default:
958223058Smav			return EINVAL;
959223058Smav		}
960223058Smav		/* NOT REACHED */
961223058Smav
962223058Smav	case KDGKBMODE:		/* get keyboard mode */
963169277Sariff		*data = (scp->status & KBD_RAW_MODE) ? K_RAW : K_XLATE;
964169277Sariff		return 0;
965169277Sariff
966169277Sariff	case KDMKTONE:		/* sound the bell */
967169277Sariff		if (*(int*)data) {
968169277Sariff  			do_bell(scp, (*(int*)data)&0xffff,
969169277Sariff				(((*(int*)data)>>16)&0xffff)*hz/1000);
970169277Sariff		}
971169277Sariff		else
972169277Sariff			do_bell(scp, scp->bell_pitch, scp->bell_duration);
973169277Sariff		return 0;
974169277Sariff
975186145Smav	case KIOCSOUND:		/* make tone (*data) hz */
976186145Smav		if (scp == cur_console) {
977186145Smav			if (*(int*)data) {
978186145Smav			int pitch = TIMER_FREQ/(*(int*)data);
979186145Smav				/* set command for counter 2, 2 byte write */
980186145Smav				if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) {
981186145Smav					return EBUSY;
982186145Smav				}
983187020Smav				/* set pitch */
984187020Smav				outb(TIMER_CNTR2, pitch);
985187020Smav				outb(TIMER_CNTR2, (pitch>>8));
986187020Smav				/* enable counter 2 output to speaker */
987187020Smav				outb(IO_PPI, inb(IO_PPI) | 3);
988187020Smav			}
989187020Smav			else {
990187020Smav				/* disable counter 2 output to speaker */
991187020Smav				outb(IO_PPI, inb(IO_PPI) & 0xFC);
992187020Smav				release_timer2();
993187020Smav			}
994187020Smav		}
995187020Smav		return 0;
996187020Smav
997187020Smav	case KDGKBTYPE:		/* get keyboard type */
998187020Smav		*data = 0;	/* type not known (yet) */
999199258Smav		return 0;
1000199258Smav
1001199258Smav	case KDSETLED:		/* set keyboard LED status */
1002199258Smav		if (*data >= 0 && *data <= LED_MASK) {
1003199258Smav			scp->status &= ~LED_MASK;
1004199258Smav			scp->status |= *data;
1005199258Smav			if (scp == cur_console)
1006199258Smav				update_leds(scp->status);
1007199258Smav			return 0;
1008199258Smav		}
1009186146Smav		return EINVAL;
1010186146Smav
1011186146Smav	case KDGETLED:		/* get keyboard LED status */
1012186146Smav		*data = scp->status & LED_MASK;
1013187020Smav		return 0;
1014187445Smav
1015187020Smav	case GETFKEY:		/* get functionkey string */
1016187445Smav		if (*(u_short*)data < n_fkey_tab) {
1017187020Smav		 	fkeyarg_t *ptr = (fkeyarg_t*)data;
1018208934Smav			bcopy(&fkey_tab[ptr->keynum].str,
1019208934Smav			      ptr->keydef,
1020208934Smav			      fkey_tab[ptr->keynum].len);
1021208934Smav			ptr->flen = fkey_tab[ptr->keynum].len;
1022222298Smav			return 0;
1023222298Smav		}
1024222298Smav		else
1025222298Smav			return EINVAL;
1026222298Smav
1027222298Smav	case SETFKEY:		/* set functionkey string */
1028222298Smav		if (*(u_short*)data < n_fkey_tab) {
1029187020Smav		 	fkeyarg_t *ptr = (fkeyarg_t*)data;
1030186146Smav			bcopy(ptr->keydef,
1031162922Sariff			      &fkey_tab[ptr->keynum].str,
1032162922Sariff			      min(ptr->flen, MAXFK));
1033169277Sariff			fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK);
1034200375Smav			return 0;
1035162922Sariff		}
1036162922Sariff		else
1037182999Smav			return EINVAL;
1038182999Smav
1039162922Sariff	case GIO_SCRNMAP: 	/* get output translation table */
1040169277Sariff		bcopy(&scr_map, data, sizeof(scr_map));
1041182999Smav		return 0;
1042182999Smav
1043183894Smav	case PIO_SCRNMAP:	/* set output translation table */
1044183894Smav		bcopy(data, &scr_map, sizeof(scr_map));
1045162922Sariff		return 0;
1046162922Sariff
1047162922Sariff	case GIO_KEYMAP: 	/* get keyboard translation table */
1048162922Sariff		bcopy(&key_map, data, sizeof(key_map));
1049162922Sariff		return 0;
1050162922Sariff
1051162922Sariff	case PIO_KEYMAP:	/* set keyboard translation table */
1052162922Sariff		bcopy(data, &key_map, sizeof(key_map));
1053182999Smav		return 0;
1054162922Sariff
1055162922Sariff	case PIO_FONT8x8:	/* set 8x8 dot font */
1056162922Sariff		if (!crtc_vga)
1057162922Sariff			return ENXIO;
1058169277Sariff		bcopy(data, font_8, 8*256);
1059162922Sariff		fonts_loaded |= FONT_8_LOADED;
1060162922Sariff		copy_font(LOAD, 1, 8, font_8);
1061162922Sariff		return 0;
1062162922Sariff
1063162922Sariff	case GIO_FONT8x8:	/* get 8x8 dot font */
1064162922Sariff		if (!crtc_vga)
1065162922Sariff			return ENXIO;
1066162922Sariff		if (fonts_loaded & FONT_8_LOADED) {
1067182999Smav			bcopy(font_8, data, 8*256);
1068182999Smav			return 0;
1069182999Smav		}
1070182999Smav		else
1071162922Sariff			return ENXIO;
1072162922Sariff
1073162922Sariff	case PIO_FONT8x14:	/* set 8x14 dot font */
1074162922Sariff		if (!crtc_vga)
1075162922Sariff			return ENXIO;
1076162922Sariff		bcopy(data, font_14, 14*256);
1077162922Sariff		fonts_loaded |= FONT_14_LOADED;
1078162922Sariff		copy_font(LOAD, 2, 14, font_14);
1079162922Sariff		return 0;
1080162922Sariff
1081162922Sariff	case GIO_FONT8x14:	/* get 8x14 dot font */
1082182999Smav		if (!crtc_vga)
1083182999Smav			return ENXIO;
1084162922Sariff		if (fonts_loaded & FONT_14_LOADED) {
1085162922Sariff			bcopy(font_14, data, 14*256);
1086162922Sariff			return 0;
1087162922Sariff		}
1088182999Smav		else
1089162922Sariff			return ENXIO;
1090162922Sariff
1091162922Sariff	case PIO_FONT8x16:	/* set 8x16 dot font */
1092162922Sariff		if (!crtc_vga)
1093164614Sariff			return ENXIO;
1094164614Sariff		bcopy(data, font_16, 16*256);
1095164614Sariff		fonts_loaded |= FONT_16_LOADED;
1096182999Smav		copy_font(LOAD, 0, 16, font_16);
1097182999Smav		return 0;
1098162922Sariff
1099162922Sariff	case GIO_FONT8x16:	/* get 8x16 dot font */
1100162922Sariff		if (!crtc_vga)
1101182999Smav			return ENXIO;
1102182999Smav		if (fonts_loaded & FONT_16_LOADED) {
1103182999Smav			bcopy(font_16, data, 16*256);
1104182999Smav			return 0;
1105162922Sariff		}
1106162922Sariff		else
1107182999Smav			return ENXIO;
1108162922Sariff#if 0	/* this should really go away !! */
1109162922Sariff	case CONSOLE_X_MODE_ON:	/* just to be compatible */
1110162922Sariff		if (saved_console < 0) {
1111162922Sariff			saved_console = get_scr_num();
1112182999Smav			switch_scr(scp, minor(dev));
1113162922Sariff	 		fp = (struct trapframe *)p->p_md.md_regs;
1114162922Sariff	 		fp->tf_eflags |= PSL_IOPL;
1115163257Sariff			scp->status |= UNKNOWN_MODE;
1116162922Sariff			scp->status |= KBD_RAW_MODE;
1117162922Sariff			return 0;
1118162922Sariff		}
1119162922Sariff		return EAGAIN;
1120162922Sariff
1121162922Sariff	case CONSOLE_X_MODE_OFF:/* just to be compatible */
1122162922Sariff	 	fp = (struct trapframe *)p->p_md.md_regs;
1123162922Sariff	 	fp->tf_eflags &= ~PSL_IOPL;
1124162922Sariff		if (crtc_vga) {
1125162922Sariff			if (fonts_loaded & FONT_16_LOADED)
1126162922Sariff				copy_font(LOAD, 0, 16, font_16);
1127162922Sariff			if (fonts_loaded & FONT_8_LOADED)
1128162922Sariff				copy_font(LOAD, 1, 8, font_8);
1129162922Sariff			if (fonts_loaded & FONT_14_LOADED)
1130162922Sariff				copy_font(LOAD, 2, 14, font_14);
1131162922Sariff			load_palette();
1132162922Sariff			set_mode(scp);
1133162922Sariff		}
1134162922Sariff		scp->status &= ~UNKNOWN_MODE;
1135162922Sariff		clear_screen(scp);
1136162922Sariff		scp->status &= ~KBD_RAW_MODE;
1137182999Smav		switch_scr(scp, saved_console);
1138162922Sariff		saved_console = -1;
1139162922Sariff		return 0;
1140162922Sariff
1141162922Sariff	 case CONSOLE_X_BELL:	/* more compatibility */
1142162922Sariff                /*
1143162922Sariff                 * if set, data is a pointer to a length 2 array of
1144162922Sariff                 * integers. data[0] is the pitch in Hz and data[1]
1145162922Sariff                 * is the duration in msec.
1146162922Sariff                 */
1147162922Sariff               	if (data)
1148162922Sariff    			do_bell(scp, TIMER_FREQ/((int*)data)[0],
1149162922Sariff				((int*)data)[1]*hz/1000);
1150162922Sariff               	else
1151162922Sariff			do_bell(scp, scp->bell_pitch, scp->bell_duration);
1152162922Sariff               	return 0;
1153182999Smav#endif
1154162922Sariff	default:
1155162922Sariff		break;
1156182999Smav	}
1157182999Smav
1158162922Sariff	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1159162922Sariff	if (error >= 0)
1160162922Sariff		return(error);
1161162922Sariff	error = ttioctl(tp, cmd, data, flag);
1162162922Sariff	if (error >= 0)
1163162922Sariff		return(error);
1164182999Smav	return(ENOTTY);
1165162922Sariff}
1166182999Smav
1167162922Sariffvoid
1168182999Smavpcxint(dev_t dev)
1169182999Smav{
1170182999Smav	struct tty *tp = get_tty_ptr(dev);
1171182999Smav
1172182999Smav	if (!tp)
1173162922Sariff		return;
1174182999Smav	tp->t_state &= ~TS_BUSY;
1175162922Sariff	if (tp->t_line)
1176162922Sariff		(*linesw[tp->t_line].l_start)(tp);
1177162922Sariff	else
1178182999Smav		pcstart(tp);
1179162922Sariff}
1180162922Sariff
1181182999Smavvoid
1182182999Smavpcstart(struct tty *tp)
1183182999Smav{
1184162922Sariff	struct clist *rbp;
1185162922Sariff	int i, s, len;
1186162922Sariff	u_char buf[PCBURST];
1187182999Smav	scr_stat *scp = get_scr_stat(tp->t_dev);
1188162922Sariff
1189162922Sariff	if (scp->status & SLKED)
1190162922Sariff		return;
1191182999Smav	s = spltty();
1192182999Smav	if (!(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) {
1193162922Sariff		tp->t_state |= TS_BUSY;
1194162922Sariff		splx(s);
1195162922Sariff		rbp = &tp->t_outq;
1196162922Sariff		scp->cursor_protect = 1;
1197162922Sariff		undraw_cursor(scp);
1198162922Sariff		while (rbp->c_cc) {
1199162922Sariff			len = q_to_b(rbp, buf, PCBURST);
1200162922Sariff			for (i=0; i<len; i++)
1201182999Smav				if (buf[i]) ansi_put(scp, buf[i]);
1202182999Smav		}
1203182999Smav		draw_cursor(scp);
1204182999Smav		scp->cursor_protect = 0;
1205182999Smav		s = spltty();
1206182999Smav		tp->t_state &= ~TS_BUSY;
1207182999Smav#if 0
1208182999Smav		if (rbp->c_cc) {
1209182999Smav			tp->t_state |= TS_TIMEOUT;
1210162922Sariff			timeout((timeout_func_t)ttrstrt, (caddr_t)tp, 1);
1211171141Sariff		}
1212182999Smav#endif
1213171141Sariff		if (rbp->c_cc <= tp->t_lowat) {
1214182999Smav			if (tp->t_state & TS_ASLEEP) {
1215182999Smav				tp->t_state &= ~TS_ASLEEP;
1216182999Smav				wakeup((caddr_t)rbp);
1217182999Smav			}
1218182999Smav			selwakeup(&tp->t_wsel);
1219171141Sariff		}
1220182999Smav	}
1221182999Smav	splx(s);
1222182999Smav}
1223162922Sariff
1224182999Smavvoid
1225162922Sariffpccnprobe(struct consdev *cp)
1226182999Smav{
1227182999Smav	int maj;
1228182999Smav
1229182999Smav	/* locate the major number */
1230182999Smav	for (maj = 0; maj < nchrdev; maj++)
1231182999Smav		if ((void*)cdevsw[maj].d_open == (void*)pcopen)
1232162922Sariff			break;
1233182999Smav
1234182999Smav	/* initialize required fields */
1235162922Sariff	cp->cn_dev = makedev(maj, 0);
1236182999Smav	cp->cn_pri = CN_INTERNAL;
1237182999Smav}
1238182999Smav
1239163057Sariffvoid
1240163057Sariffpccninit(struct consdev *cp)
1241182999Smav{
1242169277Sariff	scinit();
1243162922Sariff}
1244162922Sariff
1245169277Sariffvoid
1246162922Sariffpccnputc(dev_t dev, char c)
1247169277Sariff{
1248169277Sariff	if (c == '\n')
1249169277Sariff		scput('\r');
1250169277Sariff	scput(c);
1251169277Sariff}
1252169277Sariff
1253162922Sariffint
1254182999Smavpccngetc(dev_t dev)
1255182999Smav{
1256182999Smav	int s = spltty();		/* block scintr while we poll */
1257182999Smav	int c = scgetc(0);
1258182999Smav	splx(s);
1259182999Smav	return(c);
1260182999Smav}
1261182999Smav
1262182999Smavint
1263182999Smavpccncheckc(dev_t dev)
1264182999Smav{
1265169277Sariff	return (scgetc(1) & 0xff);
1266182999Smav}
1267182999Smav
1268182999Smavstatic void
1269182999Smavnone_saver(int test)
1270182999Smav{
1271162922Sariff}
1272182999Smav
1273182999Smavstatic void
1274163057Sarifffade_saver(int test)
1275163057Sariff{
1276182999Smav	static int count = 0;
1277182999Smav	int i;
1278182999Smav
1279182999Smav	if (test) {
1280182999Smav		scrn_blanked = 1;
1281182999Smav		if (count < 64) {
1282169277Sariff  			outb(PIXMASK, 0xFF);		/* no pixelmask */
1283169277Sariff  			outb(PALWADR, 0x00);
1284169277Sariff    			outb(PALDATA, 0);
1285169277Sariff    			outb(PALDATA, 0);
1286169277Sariff    			outb(PALDATA, 0);
1287169277Sariff  			for (i = 3; i < 768; i++) {
1288162922Sariff  				if (palette[i] - count > 15)
1289162922Sariff    					outb(PALDATA, palette[i]-count);
1290182999Smav				else
1291182999Smav    					outb(PALDATA, 15);
1292182999Smav			}
1293182999Smav			inb(crtc_addr+6);		/* reset flip/flop */
1294182999Smav			outb(ATC, 0x20);		/* enable palette */
1295182999Smav			count++;
1296182999Smav		}
1297182999Smav	}
1298182999Smav	else {
1299182999Smav		count = scrn_blanked = 0;
1300182999Smav		load_palette();
1301182999Smav	}
1302182999Smav}
1303182999Smav
1304182999Smavstatic void
1305182999Smavblank_saver(int test)
1306182999Smav{
1307182999Smav	u_char val;
1308182999Smav	if (test) {
1309182999Smav		scrn_blanked = 1;
1310182999Smav  		outb(TSIDX, 0x01); val = inb(TSREG);
1311182999Smav		outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1312182999Smav	}
1313182999Smav	else {
1314182999Smav		scrn_blanked = 0;
1315182999Smav  		outb(TSIDX, 0x01); val = inb(TSREG);
1316182999Smav		outb(TSIDX, 0x01); outb(TSREG, val & 0xDF);
1317182999Smav	}
1318182999Smav}
1319182999Smav
1320182999Smavstatic void
1321182999Smavgreen_saver(int test)
1322182999Smav{
1323182999Smav	u_char val;
1324182999Smav	if (test) {
1325182999Smav		scrn_blanked = 1;
1326182999Smav  		outb(TSIDX, 0x01); val = inb(TSREG);
1327182999Smav		outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1328182999Smav		outb(crtc_addr, 0x17); val = inb(crtc_addr + 1);
1329182999Smav		outb(crtc_addr + 1, val & ~0x80);
1330182999Smav	}
1331182999Smav	else {
1332182999Smav		scrn_blanked = 0;
1333182999Smav  		outb(TSIDX, 0x01); val = inb(TSREG);
1334182999Smav		outb(TSIDX, 0x01); outb(TSREG, val & 0xDF);
1335182999Smav                outb(crtc_addr, 0x17); val = inb(crtc_addr + 1);
1336182999Smav                outb(crtc_addr + 1, val | 0x80);
1337182999Smav	}
1338182999Smav}
1339182999Smav
1340182999Smav#define NUM_STARS	50
1341182999Smav
1342182999Smav/*
1343182999Smav * Alternate saver that got its inspiration from a well known utility
1344182999Smav * package for an inferior^H^H^H^H^H^Hfamous OS.
1345182999Smav */
1346182999Smavstatic void
1347182999Smavstar_saver(int test)
1348182999Smav{
1349169277Sariff	scr_stat	*scp = cur_console;
1350182999Smav	int		cell, i;
1351182999Smav	char 		pattern[] = {"...........++++***   "};
1352182999Smav	char		colors[] = {FG_DARKGREY, FG_LIGHTGREY,
1353182999Smav				    FG_WHITE, FG_LIGHTCYAN};
1354182999Smav	static u_short 	stars[NUM_STARS][2];
1355182999Smav
1356169277Sariff	if (test) {
1357182999Smav		if (!scrn_blanked) {
1358182999Smav			bcopyw(Crtat, scp->scr_buf,
1359182999Smav			      scp->xsize * scp->ysize * 2);
1360182999Smav			fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], Crtat,
1361182999Smav			      scp->xsize * scp->ysize);
1362182999Smav			set_border(0);
1363182999Smav			i = scp->ysize * scp->xsize + 5;
1364182999Smav			outb(crtc_addr, 14);
1365182999Smav			outb(crtc_addr+1, i >> 8);
1366182999Smav			outb(crtc_addr, 15);
1367182999Smav			outb(crtc_addr+1, i & 0xff);
1368169277Sariff			scrn_blanked = 1;
1369162922Sariff 			for(i=0; i<NUM_STARS; i++) {
1370162922Sariff  				stars[i][0] =
1371162922Sariff					random() % (scp->xsize*scp->ysize);
1372182999Smav  				stars[i][1] = 0;
1373182999Smav 			}
1374182999Smav		}
1375162922Sariff   		cell = random() % NUM_STARS;
1376162922Sariff		*((u_short*)(Crtat + stars[cell][0])) =
1377162922Sariff			scr_map[pattern[stars[cell][1]]] |
1378162922Sariff			        colors[random()%sizeof(colors)] << 8;
1379162922Sariff		if ((stars[cell][1]+=(random()%4)) >= sizeof(pattern)-1) {
1380182999Smav    			stars[cell][0] = random() % (scp->xsize*scp->ysize);
1381162922Sariff   			stars[cell][1] = 0;
1382162922Sariff		}
1383162922Sariff	}
1384162922Sariff	else {
1385162922Sariff		if (scrn_blanked) {
1386162922Sariff			bcopyw(scp->scr_buf, Crtat, scp->xsize*scp->ysize*2);
1387163057Sariff			set_border(scp->border);
1388182999Smav			scrn_blanked = 0;
1389162922Sariff		}
1390162922Sariff	}
1391182999Smav}
1392182999Smav
1393182999Smavstatic void
1394182999Smavsnake_saver(int test)
1395162965Sariff{
1396182999Smav	const char	saves[] = {"FreeBSD-2.0"};
1397162922Sariff	static u_char	*savs[sizeof(saves)-1];
1398162965Sariff	static int	dirx, diry;
1399162922Sariff	int		f;
1400162922Sariff	scr_stat	*scp = cur_console;
1401162922Sariff
1402162922Sariff	if (test) {
1403162922Sariff		if (!scrn_blanked) {
1404162922Sariff			bcopyw(Crtat, scp->scr_buf,
1405162922Sariff			      scp->xsize * scp->ysize * 2);
1406162922Sariff			fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20],
1407182999Smav			      Crtat, scp->xsize * scp->ysize);
1408162922Sariff			set_border(0);
1409162922Sariff			dirx = (scp->xpos ? 1 : -1);
1410162922Sariff			diry = (scp->ypos ?
1411162922Sariff				scp->xsize : -scp->xsize);
1412164614Sariff			for (f=0; f< sizeof(saves)-1; f++)
1413162922Sariff				savs[f] = (u_char *)Crtat + 2 *
1414162922Sariff					  (scp->xpos+scp->ypos*scp->xsize);
1415162922Sariff			*(savs[0]) = scr_map[*saves];
1416162922Sariff			f = scp->ysize * scp->xsize + 5;
1417162922Sariff			outb(crtc_addr, 14);
1418162922Sariff			outb(crtc_addr+1, f >> 8);
1419162922Sariff			outb(crtc_addr, 15);
1420171330Sariff			outb(crtc_addr+1, f & 0xff);
1421164614Sariff			scrn_blanked = 1;
1422162922Sariff		}
1423162922Sariff		if (scrn_blanked++ < 4)
1424162922Sariff			return;
1425162922Sariff		scrn_blanked = 1;
1426162922Sariff		*(savs[sizeof(saves)-2]) = scr_map[0x20];
1427162922Sariff		for (f=sizeof(saves)-2; f > 0; f--)
1428162922Sariff			savs[f] = savs[f-1];
1429162922Sariff		f = (savs[0] - (u_char *)Crtat) / 2;
1430163057Sariff		if ((f % scp->xsize) == 0 ||
1431163057Sariff		    (f % scp->xsize) == scp->xsize - 1 ||
1432182999Smav		    (random() % 50) == 0)
1433163057Sariff			dirx = -dirx;
1434163057Sariff		if ((f / scp->xsize) == 0 ||
1435163057Sariff		    (f / scp->xsize) == scp->ysize - 1 ||
1436163057Sariff		    (random() % 20) == 0)
1437162922Sariff			diry = -diry;
1438162922Sariff		savs[0] += 2*dirx + 2*diry;
1439162922Sariff		for (f=sizeof(saves)-2; f>=0; f--)
1440163057Sariff			*(savs[f]) = scr_map[saves[f]];
1441162922Sariff	}
1442162922Sariff	else {
1443162922Sariff		if (scrn_blanked) {
1444162922Sariff			bcopyw(scp->scr_buf, Crtat,
1445162922Sariff			      scp->xsize * scp->ysize * 2);
1446164614Sariff			set_border(scp->border);
1447162922Sariff			scrn_blanked = 0;
1448162922Sariff		}
1449162922Sariff	}
1450162922Sariff}
1451164614Sariff
1452164614Sariffstatic void
1453162922Sariffcursor_shape(int start, int end)
1454162922Sariff{
1455162922Sariff	outb(crtc_addr, 10);
1456162922Sariff	outb(crtc_addr+1, start & 0xFF);
1457162922Sariff	outb(crtc_addr, 11);
1458162922Sariff	outb(crtc_addr+1, end & 0xFF);
1459162922Sariff}
1460162922Sariff
1461162922Sariff#if !defined(FAT_CURSOR)
1462162922Sariffstatic void
1463162922Sariffget_cursor_shape(int *start, int *end)
1464162922Sariff{
1465162922Sariff	outb(crtc_addr, 10);
1466164614Sariff	*start = inb(crtc_addr+1) & 0x1F;
1467171141Sariff	outb(crtc_addr, 11);
1468182999Smav	*end = inb(crtc_addr+1) & 0x1F;
1469162922Sariff}
1470162922Sariff#endif
1471162922Sariff
1472162922Sariffstatic void
1473164614Sariffscrn_timer()
1474164614Sariff{
1475164614Sariff	timeout((timeout_func_t)scrn_timer, 0, hz/5);
1476164614Sariff	if (cur_console->status & UNKNOWN_MODE)
1477171141Sariff		return;
1478162922Sariff	if (!cur_console->cursor_protect && configuration & BLINK_CURSOR) {
1479162922Sariff		if (cur_console->cursor_saveunder)
1480163057Sariff			undraw_cursor(cur_console);
1481162922Sariff		else
1482162922Sariff			draw_cursor(cur_console);
1483162922Sariff	}
1484162922Sariff	if (scrn_blank_time && (time.tv_sec > scrn_time_stamp+scrn_blank_time))
1485171141Sariff		SCRN_SAVER(1);
1486171141Sariff}
1487162922Sariff
1488163057Sariffstatic void
1489162922Sariffclear_screen(scr_stat *scp)
1490162922Sariff{
1491162922Sariff	move_crsr(scp, 0, 0);
1492163057Sariff	fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base,
1493164614Sariff	       scp->xsize * scp->ysize);
1494164614Sariff}
1495171141Sariff
1496171141Sariffstatic int
1497162922Sariffswitch_scr(scr_stat *scp, u_int next_scr)
1498162922Sariff{
1499162922Sariff	if (switch_in_progress &&
1500162922Sariff	    (cur_console->proc != pfind(cur_console->pid)))
1501162922Sariff		switch_in_progress = 0;
1502162922Sariff
1503162922Sariff    	if (next_scr >= MAXCONS || switch_in_progress
1504162922Sariff	    || (cur_console->smode.mode == VT_AUTO
1505164614Sariff	       	&& cur_console->status & UNKNOWN_MODE)) {
1506163057Sariff		do_bell(scp, BELL_PITCH, BELL_DURATION);
1507182999Smav		return EINVAL;
1508182999Smav	}
1509182999Smav
1510182999Smav	/* is the wanted virtual console open ? */
1511182999Smav	if (next_scr) {
1512162922Sariff		struct tty *tp = VIRTUAL_TTY(next_scr);
1513162922Sariff		if (!(tp->t_state & TS_ISOPEN)) {
1514164614Sariff			do_bell(scp, BELL_PITCH, BELL_DURATION);
1515164614Sariff			return EINVAL;
1516162922Sariff		}
1517162922Sariff	}
1518162922Sariff	/* delay switch if actively updating screen */
1519164614Sariff	if (write_in_progress || blink_in_progress) {
1520162922Sariff		delayed_next_scr = next_scr+1;
1521182999Smav		return 0;
1522182999Smav	}
1523182999Smav	switch_in_progress = 1;
1524182999Smav	old_scp = cur_console;
1525171141Sariff	new_scp = console[next_scr];
1526171141Sariff	wakeup((caddr_t)&new_scp->smode);
1527162922Sariff	if (new_scp == old_scp) {
1528162922Sariff		switch_in_progress = 0;
1529162922Sariff		return 0;
1530182999Smav	}
1531162922Sariff
1532162922Sariff	/* has controlling process died? */
1533162922Sariff	if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid)))
1534162922Sariff		old_scp->smode.mode = VT_AUTO;
1535182999Smav	if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid)))
1536162922Sariff		new_scp->smode.mode = VT_AUTO;
1537162922Sariff
1538162922Sariff	/* check the modes and switch approbiatly */
1539162922Sariff	if (old_scp->smode.mode == VT_PROCESS) {
1540162922Sariff		old_scp->status |= SWITCH_WAIT_REL;
1541162922Sariff		psignal(old_scp->proc, old_scp->smode.relsig);
1542162922Sariff	}
1543162922Sariff	else {
1544162922Sariff		exchange_scr();
1545162922Sariff		if (new_scp->smode.mode == VT_PROCESS) {
1546162922Sariff			new_scp->status |= SWITCH_WAIT_ACQ;
1547162922Sariff			psignal(new_scp->proc, new_scp->smode.acqsig);
1548162922Sariff		}
1549162922Sariff		else
1550162922Sariff			switch_in_progress = 0;
1551169277Sariff	}
1552162922Sariff	return 0;
1553162922Sariff}
1554162922Sariff
1555162922Sariffstatic void
1556162922Sariffexchange_scr(void)
1557169277Sariff{
1558169277Sariff	bcopyw(Crtat, old_scp->scr_buf, old_scp->xsize * old_scp->ysize * 2);
1559169277Sariff	old_scp->crt_base = old_scp->scr_buf;
1560169277Sariff	move_crsr(old_scp, old_scp->xpos, old_scp->ypos);
1561169277Sariff	cur_console = new_scp;
1562169277Sariff	if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)){
1563162922Sariff        	if (crtc_vga && video_mode_ptr)
1564162922Sariff			set_mode(new_scp);
1565162922Sariff	}
1566162922Sariff	new_scp->crt_base = Crtat;
1567162922Sariff	move_crsr(new_scp, new_scp->xpos, new_scp->ypos);
1568162922Sariff	bcopyw(new_scp->scr_buf, Crtat, new_scp->xsize * new_scp->ysize * 2);
1569162922Sariff	update_leds(new_scp->status);
1570162922Sariff	if ((old_scp->status & UNKNOWN_MODE) && crtc_vga) {
1571162922Sariff		if (fonts_loaded & FONT_16_LOADED)
1572162922Sariff			copy_font(LOAD, 0, 16, font_16);
1573162922Sariff		if (fonts_loaded & FONT_8_LOADED)
1574162922Sariff			copy_font(LOAD, 1, 8, font_8);
1575162922Sariff		if (fonts_loaded & FONT_14_LOADED)
1576162922Sariff			copy_font(LOAD, 2, 14, font_14);
1577162922Sariff		load_palette();
1578162922Sariff	}
1579182999Smav	if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE)
1580182999Smav		shfts = ctls = alts = agrs = metas = 0;
1581182999Smav	delayed_next_scr = 0;
1582182999Smav}
1583182999Smav
1584162922Sariffstatic void
1585162922Sariffmove_crsr(scr_stat *scp, int x, int y)
1586162922Sariff{
1587162922Sariff	if (x < 0 || y < 0 || x >= scp->xsize || y >= scp->ysize)
1588162922Sariff		return;
1589162922Sariff	scp->xpos = x;
1590163057Sariff	scp->ypos = y;
1591162922Sariff	scp->crtat = scp->crt_base + scp->ypos * scp->xsize + scp->xpos;
1592162922Sariff}
1593162922Sariff
1594162922Sariffstatic void
1595162922Sariffscan_esc(scr_stat *scp, u_char c)
1596162922Sariff{
1597162922Sariff	static u_char ansi_col[16] =
1598162922Sariff		{0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15};
1599162922Sariff	int i, n;
1600162922Sariff	u_short *src, *dst, count;
1601162922Sariff
1602162922Sariff	if (scp->term.esc == 1) {
1603162922Sariff		switch (c) {
1604162922Sariff
1605162922Sariff		case '[': 	/* Start ESC [ sequence */
1606162922Sariff			scp->term.esc = 2;
1607162922Sariff			scp->term.last_param = -1;
1608162922Sariff			for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
1609162922Sariff				scp->term.param[i] = 1;
1610162922Sariff			scp->term.num_param = 0;
1611162922Sariff			return;
1612162922Sariff
1613162922Sariff		case 'M':	/* Move cursor up 1 line, scroll if at top */
1614162922Sariff			if (scp->ypos > 0)
1615162922Sariff				move_crsr(scp, scp->xpos, scp->ypos - 1);
1616162922Sariff			else {
1617162922Sariff				bcopyw(scp->crt_base,
1618162922Sariff					scp->crt_base + scp->xsize,
1619162922Sariff					(scp->ysize - 1) * scp->xsize *
1620162922Sariff					sizeof(u_short));
1621162922Sariff				fillw(scp->term.cur_attr | scr_map[0x20],
1622162922Sariff				      scp->crt_base, scp->xsize);
1623162922Sariff			}
1624162922Sariff			break;
1625162922Sariff#if notyet
1626162922Sariff		case 'Q':
1627162922Sariff			scp->term.esc = 4;
1628162922Sariff			break;
1629162922Sariff#endif
1630162922Sariff		case 'c':	/* Clear screen & home */
1631196762Smav			clear_screen(scp);
1632163057Sariff			break;
1633162922Sariff		}
1634162922Sariff	}
1635162922Sariff	else if (scp->term.esc == 2) {
1636162922Sariff		if (c >= '0' && c <= '9') {
1637162922Sariff		    if (scp->term.num_param < MAX_ESC_PAR) {
1638162922Sariff			if (scp->term.last_param != scp->term.num_param) {
1639162922Sariff		    	    scp->term.last_param = scp->term.num_param;
1640162922Sariff		    	    scp->term.param[scp->term.num_param] = 0;
1641162922Sariff			}
1642162922Sariff			else
1643162922Sariff		    	    scp->term.param[scp->term.num_param] *= 10;
1644162922Sariff		    	scp->term.param[scp->term.num_param] += c - '0';
1645162922Sariff		    	return;
1646162922Sariff		    }
1647162922Sariff		}
1648162922Sariff		scp->term.num_param = scp->term.last_param + 1;
1649162922Sariff		switch (c) {
1650162922Sariff
1651162922Sariff		case ';':
1652162922Sariff			if (scp->term.num_param < MAX_ESC_PAR)
1653162922Sariff				return;
1654162922Sariff			break;
1655162922Sariff
1656162922Sariff		case '=':
1657162922Sariff			scp->term.esc = 3;
1658162922Sariff			scp->term.last_param = -1;
1659162922Sariff			for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
1660162922Sariff				scp->term.param[i] = 1;
1661162922Sariff			scp->term.num_param = 0;
1662162922Sariff			return;
1663162922Sariff
1664162922Sariff		case 'A': /* up n rows */
1665162922Sariff			n = scp->term.param[0]; if (n < 1) n = 1;
1666196762Smav			move_crsr(scp, scp->xpos, scp->ypos - n);
1667196762Smav			break;
1668196762Smav
1669196762Smav		case 'B': /* down n rows */
1670196762Smav			n = scp->term.param[0]; if (n < 1) n = 1;
1671196762Smav			move_crsr(scp, scp->xpos, scp->ypos + n);
1672182999Smav			break;
1673182999Smav
1674162922Sariff		case 'C': /* right n columns */
1675162922Sariff			n = scp->term.param[0]; if (n < 1) n = 1;
1676162922Sariff			move_crsr(scp, scp->xpos + n, scp->ypos);
1677162922Sariff			break;
1678162922Sariff
1679162922Sariff		case 'D': /* left n columns */
1680162922Sariff			n = scp->term.param[0]; if (n < 1) n = 1;
1681162922Sariff			move_crsr(scp, scp->xpos - n, scp->ypos);
1682162922Sariff			break;
1683162922Sariff
1684162922Sariff		case 'E': /* cursor to start of line n lines down */
1685162922Sariff			n = scp->term.param[0]; if (n < 1) n = 1;
1686162922Sariff			move_crsr(scp, 0, scp->ypos + n);
1687162922Sariff			break;
1688162922Sariff
1689162922Sariff		case 'F': /* cursor to start of line n lines up */
1690162922Sariff			n = scp->term.param[0]; if (n < 1) n = 1;
1691162922Sariff			move_crsr(scp, 0, scp->ypos - n);
1692162922Sariff			break;
1693162922Sariff
1694162922Sariff		case 'f': /* System V consoles .. */
1695162922Sariff		case 'H': /* Cursor move */
1696162922Sariff			if (scp->term.num_param == 0)
1697162922Sariff				move_crsr(scp, 0, 0);
1698162922Sariff			else if (scp->term.num_param == 2)
1699162922Sariff				move_crsr(scp, scp->term.param[1] - 1,
1700162922Sariff					  scp->term.param[0] - 1);
1701162922Sariff			break;
1702162922Sariff
1703162922Sariff		case 'J': /* Clear all or part of display */
1704162922Sariff			if (scp->term.num_param == 0)
1705162922Sariff				n = 0;
1706169277Sariff			else
1707162922Sariff				n = scp->term.param[0];
1708162922Sariff			switch (n) {
1709169277Sariff			case 0: /* clear form cursor to end of display */
1710162922Sariff				fillw(scp->term.cur_attr | scr_map[0x20],
1711162922Sariff				      scp->crtat, scp->crt_base +
1712162922Sariff				      scp->xsize * scp->ysize -
1713162922Sariff				      scp->crtat);
1714162922Sariff				break;
1715194861Smav			case 1: /* clear from beginning of display to cursor */
1716194861Smav				fillw(scp->term.cur_attr | scr_map[0x20],
1717162922Sariff				      scp->crt_base,
1718162922Sariff				      scp->crtat - scp->crt_base);
1719194861Smav				break;
1720194861Smav			case 2: /* clear entire display */
1721162922Sariff				clear_screen(scp);
1722162922Sariff				break;
1723162922Sariff			}
1724169277Sariff			break;
1725162922Sariff
1726169277Sariff		case 'K': /* Clear all or part of line */
1727162922Sariff			if (scp->term.num_param == 0)
1728162922Sariff				n = 0;
1729162922Sariff			else
1730162922Sariff				n = scp->term.param[0];
1731162922Sariff			switch (n) {
1732162922Sariff			case 0: /* clear form cursor to end of line */
1733162922Sariff				fillw(scp->term.cur_attr | scr_map[0x20],
1734167773Sariff				      scp->crtat, scp->xsize - scp->xpos);
1735162922Sariff				break;
1736162922Sariff			case 1: /* clear from beginning of line to cursor */
1737162922Sariff				fillw(scp->term.cur_attr|scr_map[0x20],
1738162922Sariff				      scp->crtat - (scp->xsize - scp->xpos),
1739162922Sariff				      (scp->xsize - scp->xpos) + 1);
1740162965Sariff				break;
1741169277Sariff			case 2: /* clear entire line */
1742171330Sariff				fillw(scp->term.cur_attr|scr_map[0x20],
1743171330Sariff				      scp->crtat - (scp->xsize - scp->xpos),
1744162922Sariff				      scp->xsize);
1745162922Sariff				break;
1746162922Sariff			}
1747167773Sariff			break;
1748162922Sariff
1749162922Sariff		case 'L':	/* Insert n lines */
1750169277Sariff			n = scp->term.param[0]; if (n < 1) n = 1;
1751169277Sariff			if (n > scp->ysize - scp->ypos)
1752162922Sariff				n = scp->ysize - scp->ypos;
1753162922Sariff			src = scp->crt_base + scp->ypos * scp->xsize;
1754162922Sariff			dst = src + n * scp->xsize;
1755162922Sariff			count = scp->ysize - (scp->ypos + n);
1756169277Sariff			bcopyw(src, dst, count * scp->xsize * sizeof(u_short));
1757162922Sariff			fillw(scp->term.cur_attr | scr_map[0x20], src,
1758167773Sariff			      n * scp->xsize);
1759167773Sariff			break;
1760162922Sariff
1761162922Sariff		case 'M':	/* Delete n lines */
1762167773Sariff			n = scp->term.param[0]; if (n < 1) n = 1;
1763162922Sariff			if (n > scp->ysize - scp->ypos)
1764162922Sariff				n = scp->ysize - scp->ypos;
1765183097Smav			dst = scp->crt_base + scp->ypos * scp->xsize;
1766169277Sariff			src = dst + n * scp->xsize;
1767169277Sariff			count = scp->ysize - (scp->ypos + n);
1768169277Sariff			bcopyw(src, dst, count * scp->xsize * sizeof(u_short));
1769169277Sariff			src = dst + count * scp->xsize;
1770162922Sariff			fillw(scp->term.cur_attr | scr_map[0x20], src,
1771169277Sariff			      n * scp->xsize);
1772167773Sariff			break;
1773169277Sariff
1774167773Sariff		case 'P':	/* Delete n chars */
1775162922Sariff			n = scp->term.param[0]; if (n < 1) n = 1;
1776162922Sariff			if (n > scp->xsize - scp->xpos)
1777162922Sariff				n = scp->xsize - scp->xpos;
1778162922Sariff			dst = scp->crtat;
1779162922Sariff			src = dst + n;
1780169277Sariff			count = scp->xsize - (scp->xpos + n);
1781162922Sariff			bcopyw(src, dst, count * sizeof(u_short));
1782162922Sariff			src = dst + count;
1783162922Sariff			fillw(scp->term.cur_attr | scr_map[0x20], src, n);
1784162922Sariff			break;
1785162922Sariff
1786169277Sariff		case '@':	/* Insert n chars */
1787162922Sariff			n = scp->term.param[0]; if (n < 1) n = 1;
1788167773Sariff			if (n > scp->xsize - scp->xpos)
1789169277Sariff				n = scp->xsize - scp->xpos;
1790162922Sariff			src = scp->crtat;
1791162922Sariff			dst = src + n;
1792162922Sariff			count = scp->xsize - (scp->xpos + n);
1793169277Sariff			bcopyw(src, dst, count * sizeof(u_short));
1794162922Sariff			fillw(scp->term.cur_attr | scr_map[0x20], src, n);
1795167773Sariff			break;
1796167773Sariff
1797162922Sariff		case 'S':	/* scroll up n lines */
1798167773Sariff			n = scp->term.param[0]; if (n < 1)  n = 1;
1799167773Sariff			if (n > scp->ysize)
1800167773Sariff				n = scp->ysize;
1801167773Sariff			bcopyw(scp->crt_base + (scp->xsize * n),
1802162922Sariff			      scp->crt_base,
1803167773Sariff			      scp->xsize * (scp->ysize - n) *
1804162922Sariff			      sizeof(u_short));
1805167773Sariff			fillw(scp->term.cur_attr | scr_map[0x20],
1806162922Sariff			      scp->crt_base + scp->xsize *
1807162922Sariff			      (scp->ysize - n),
1808162922Sariff			      scp->xsize * n);
1809162922Sariff			break;
1810162922Sariff
1811162922Sariff		case 'T':	/* scroll down n lines */
1812162922Sariff			n = scp->term.param[0]; if (n < 1)  n = 1;
1813162922Sariff			if (n > scp->ysize)
1814162922Sariff				n = scp->ysize;
1815162922Sariff			bcopyw(scp->crt_base,
1816162922Sariff			      scp->crt_base + (scp->xsize * n),
1817162922Sariff			      scp->xsize * (scp->ysize - n) *
1818162922Sariff			      sizeof(u_short));
1819162922Sariff			fillw(scp->term.cur_attr | scr_map[0x20],
1820162922Sariff			      scp->crt_base, scp->xsize * n);
1821162922Sariff			break;
1822162922Sariff
1823162922Sariff		case 'X':	/* delete n characters in line */
1824162922Sariff			n = scp->term.param[0]; if (n < 1)  n = 1;
1825162922Sariff			if (n > scp->xsize - scp->xpos)
1826162922Sariff				n = scp->xsize - scp->xpos;
1827162922Sariff			fillw(scp->term.cur_attr | scr_map[0x20],
1828162922Sariff                              scp->crt_base + scp->xpos +
1829162922Sariff			      ((scp->xsize*scp->ypos) * sizeof(u_short)), n);
1830162922Sariff			break;
1831162922Sariff
1832162922Sariff		case 'Z':	/* move n tabs backwards */
1833162922Sariff			n = scp->term.param[0]; if (n < 1)  n = 1;
1834162922Sariff			if ((i = scp->xpos & 0xf8) == scp->xpos)
1835162922Sariff				i -= 8*n;
1836162922Sariff			else
1837162922Sariff				i -= 8*(n-1);
1838162922Sariff			if (i < 0)
1839162922Sariff				i = 0;
1840162922Sariff			move_crsr(scp, i, scp->ypos);
1841162922Sariff			break;
1842162922Sariff
1843162922Sariff		case '`': 	/* move cursor to column n */
1844162922Sariff			n = scp->term.param[0]; if (n < 1)  n = 1;
1845162922Sariff			move_crsr(scp, n - 1, scp->ypos);
1846162922Sariff			break;
1847162922Sariff
1848164614Sariff		case 'a': 	/* move cursor n columns to the right */
1849162922Sariff			n = scp->term.param[0]; if (n < 1)  n = 1;
1850162922Sariff			move_crsr(scp, scp->xpos + n, scp->ypos);
1851162922Sariff			break;
1852162922Sariff
1853162922Sariff		case 'd': 	/* move cursor to row n */
1854162922Sariff			n = scp->term.param[0]; if (n < 1)  n = 1;
1855162922Sariff			move_crsr(scp, scp->xpos, n - 1);
1856162922Sariff			break;
1857162922Sariff
1858162922Sariff		case 'e': 	/* move cursor n rows down */
1859162922Sariff			n = scp->term.param[0]; if (n < 1)  n = 1;
1860162922Sariff			move_crsr(scp, scp->xpos, scp->ypos + n);
1861162922Sariff			break;
1862162922Sariff
1863162922Sariff		case 'm': 	/* change attribute */
1864171330Sariff			if (scp->term.num_param == 0) {
1865171330Sariff				scp->term.cur_attr = scp->term.std_attr;
1866171330Sariff				break;
1867171330Sariff			}
1868171330Sariff			for (i = 0; i < scp->term.num_param; i++) {
1869171330Sariff				switch (n = scp->term.param[i]) {
1870171330Sariff				case 0:	/* back to normal */
1871171330Sariff					scp->term.cur_attr = scp->term.std_attr;
1872162922Sariff					break;
1873162922Sariff				case 1:	/* highlight (bold) */
1874162922Sariff					scp->term.cur_attr &= 0xFF00;
1875162922Sariff					scp->term.cur_attr |= 0x0800;
1876162922Sariff					break;
1877167773Sariff				case 4: /* highlight (underline) */
1878162922Sariff					scp->term.cur_attr &= 0xFF00;
1879182999Smav					scp->term.cur_attr |= 0x0800;
1880182999Smav					break;
1881162922Sariff				case 5: /* blink */
1882162922Sariff					scp->term.cur_attr &= 0xFF00;
1883162922Sariff					scp->term.cur_attr |= 0x8000;
1884162922Sariff					break;
1885167773Sariff				case 7: /* reverse video */
1886162922Sariff					scp->term.cur_attr = scp->term.rev_attr;
1887162922Sariff					break;
1888162922Sariff				case 30: case 31: /* set fg color */
1889162922Sariff				case 32: case 33: case 34:
1890167773Sariff				case 35: case 36: case 37:
1891164614Sariff					scp->term.cur_attr =
1892164614Sariff						(scp->term.cur_attr & 0xF8FF)
1893162922Sariff						| (ansi_col[(n-30) & 7] << 8);
1894162922Sariff					break;
1895162922Sariff				case 40: case 41: /* set bg color */
1896162922Sariff				case 42: case 43: case 44:
1897162922Sariff				case 45: case 46: case 47:
1898162922Sariff					scp->term.cur_attr =
1899162922Sariff						(scp->term.cur_attr & 0x8FFF)
1900162922Sariff						| (ansi_col[(n-40) & 7] << 12);
1901162922Sariff					break;
1902162922Sariff				}
1903162922Sariff			}
1904162922Sariff			break;
1905162922Sariff
1906162922Sariff		case 'x':
1907164614Sariff			if (scp->term.num_param == 0)
1908162922Sariff				n = 0;
1909162922Sariff			else
1910162922Sariff				n = scp->term.param[0];
1911162922Sariff			switch (n) {
1912188656Smav			case 0: 	/* reset attributes */
1913171330Sariff				scp->term.cur_attr = scp->term.std_attr =
1914164614Sariff				    current_default->std_attr;
1915164614Sariff				scp->term.rev_attr = current_default->rev_attr;
1916171330Sariff				break;
1917162922Sariff			case 1: 	/* set ansi background */
1918162922Sariff				scp->term.cur_attr = scp->term.std_attr =
1919162922Sariff				    (scp->term.std_attr & 0x0F00) |
1920162922Sariff				    (ansi_col[(scp->term.param[1])&0x0F]<<12);
1921162922Sariff				break;
1922162922Sariff			case 2: 	/* set ansi foreground */
1923162922Sariff				scp->term.cur_attr = scp->term.std_attr =
1924162922Sariff				    (scp->term.std_attr & 0xF000) |
1925162922Sariff				    (ansi_col[(scp->term.param[1])&0x0F]<<8);
1926162922Sariff				break;
1927162922Sariff			case 3: 	/* set ansi attribute directly */
1928162922Sariff				scp->term.cur_attr = scp->term.std_attr =
1929162922Sariff				    (scp->term.param[1]&0xFF)<<8;
1930162922Sariff				break;
1931162922Sariff			case 5: 	/* set ansi reverse video background */
1932162922Sariff				scp->term.rev_attr =
1933162922Sariff				    (scp->term.rev_attr & 0x0F00) |
1934162922Sariff				    (ansi_col[(scp->term.param[1])&0x0F]<<12);
1935162922Sariff				break;
1936162922Sariff			case 6: 	/* set ansi reverse video foreground */
1937162922Sariff				scp->term.rev_attr =
1938162922Sariff				    (scp->term.rev_attr & 0xF000) |
1939162922Sariff				    (ansi_col[(scp->term.param[1])&0x0F]<<8);
1940162922Sariff				break;
1941162922Sariff			case 7: 	/* set ansi reverse video directly */
1942162922Sariff				scp->term.rev_attr =
1943162922Sariff				    (scp->term.param[1]&0xFF)<<8;
1944162922Sariff				break;
1945162922Sariff			}
1946162922Sariff			break;
1947162922Sariff
1948162922Sariff		case 'z':	/* switch to (virtual) console n */
1949162922Sariff			if (scp->term.num_param == 1)
1950162922Sariff				switch_scr(scp, scp->term.param[0]);
1951162922Sariff			break;
1952162922Sariff		}
1953162922Sariff	}
1954162922Sariff	else if (scp->term.esc == 3) {
1955162922Sariff		if (c >= '0' && c <= '9') {
1956162922Sariff			if (scp->term.num_param < MAX_ESC_PAR) {
1957162922Sariff				if (scp->term.last_param != scp->term.num_param) {
1958162922Sariff					scp->term.last_param = scp->term.num_param;
1959162922Sariff					scp->term.param[scp->term.num_param] = 0;
1960162922Sariff				}
1961162922Sariff				else
1962162922Sariff					scp->term.param[scp->term.num_param] *= 10;
1963162922Sariff				scp->term.param[scp->term.num_param] += c - '0';
1964162922Sariff				return;
1965162922Sariff			}
1966162922Sariff		}
1967162922Sariff		scp->term.num_param = scp->term.last_param + 1;
1968162922Sariff		switch (c) {
1969162922Sariff
1970162922Sariff		case ';':
1971162922Sariff			if (scp->term.num_param < MAX_ESC_PAR)
1972162922Sariff				return;
1973162922Sariff			break;
1974162922Sariff
1975162922Sariff		case 'A':	/* set display border color */
1976162922Sariff			if (scp->term.num_param == 1)
1977162922Sariff				scp->border=scp->term.param[0] & 0xff;
1978162922Sariff				if (scp == cur_console)
1979162922Sariff					set_border(scp->border);
1980162922Sariff			break;
1981162922Sariff
1982162922Sariff		case 'B':	/* set bell pitch and duration */
1983162922Sariff			if (scp->term.num_param == 2) {
1984162922Sariff				scp->bell_pitch = scp->term.param[0];
1985162922Sariff				scp->bell_duration = scp->term.param[1]*10;
1986162922Sariff			}
1987162922Sariff			break;
1988162922Sariff
1989162922Sariff		case 'C': 	/* set cursor type & shape */
1990162922Sariff			if (scp->term.num_param == 1) {
1991162922Sariff				if (scp->term.param[0] & 0x01)
1992162922Sariff					configuration |= BLINK_CURSOR;
1993162922Sariff				else
1994162922Sariff					configuration &= ~BLINK_CURSOR;
1995162922Sariff			}
1996162922Sariff#if 0
1997162922Sariff			else if (scp->term.num_param == 2) {
1998162922Sariff				scp->cursor_start = scp->term.param[0] & 0x1F;
1999162922Sariff				scp->cursor_end = scp->term.param[1] & 0x1F;
2000162922Sariff				if (scp == cur_console)
2001162922Sariff					cursor_shape(scp->cursor_start,
2002162922Sariff						     scp->cursor_end);
2003162922Sariff			}
2004162922Sariff#endif
2005162922Sariff			break;
2006162922Sariff
2007182999Smav		case 'F':	/* set ansi foreground */
2008182999Smav			if (scp->term.num_param == 1)
2009162922Sariff				scp->term.cur_attr = scp->term.std_attr =
2010182999Smav					(scp->term.std_attr & 0xF000)
2011162922Sariff					| ((scp->term.param[0] & 0x0F) << 8);
2012182999Smav			break;
2013182999Smav
2014162922Sariff		case 'G': 	/* set ansi background */
2015182999Smav			if (scp->term.num_param == 1)
2016162922Sariff				scp->term.cur_attr = scp->term.std_attr =
2017162922Sariff					(scp->term.std_attr & 0x0F00)
2018169277Sariff					| ((scp->term.param[0] & 0x0F) << 12);
2019162922Sariff			break;
2020162922Sariff
2021162922Sariff		case 'H':	/* set ansi reverse video foreground */
2022162922Sariff			if (scp->term.num_param == 1)
2023162922Sariff				scp->term.rev_attr =
2024162922Sariff					(scp->term.rev_attr & 0xF000)
2025162922Sariff					| ((scp->term.param[0] & 0x0F) << 8);
2026162922Sariff			break;
2027169277Sariff
2028162922Sariff		case 'I': 	/* set ansi reverse video background */
2029162922Sariff			if (scp->term.num_param == 1)
2030162922Sariff				scp->term.rev_attr =
2031162922Sariff					(scp->term.rev_attr & 0x0F00)
2032162922Sariff					| ((scp->term.param[0] & 0x0F) << 12);
2033162922Sariff			break;
2034162922Sariff		}
2035162922Sariff	}
2036162922Sariff	scp->term.esc = 0;
2037162922Sariff}
2038162922Sariff
2039162922Sariffstatic void
2040162922Sariffundraw_cursor(scr_stat *scp)
2041162922Sariff{
2042162922Sariff	if (scp->cursor_saveunder) {
2043162922Sariff		*scp->crtat = scp->cursor_saveunder;
2044162922Sariff		scp->cursor_saveunder = NULL;
2045162922Sariff	}
2046162922Sariff}
2047162922Sariff
2048162922Sariffstatic void
2049162922Sariffdraw_cursor(scr_stat *scp)
2050162922Sariff{
2051162922Sariff	scp->cursor_saveunder = *scp->crtat;
2052162922Sariff	if ((scp->cursor_saveunder & 0x7000) == 0x7000) {
2053162922Sariff		*scp->crtat &= 0x8fff;
2054162922Sariff		if(!(scp->cursor_saveunder & 0x0700))
2055162922Sariff			*scp->crtat |= 0x0700;
2056162922Sariff	} else {
2057162922Sariff		*scp->crtat |= 0x7000;
2058162922Sariff		if ((scp->cursor_saveunder & 0x0f00) == 0x0700)
2059162922Sariff			*scp->crtat &= 0xf8ff;
2060162922Sariff	}
2061162922Sariff}
2062172811Sariff
2063162922Sariffstatic void
2064172811Sariffansi_put(scr_stat *scp, u_char c)
2065162922Sariff{
2066162922Sariff	if (scp->status & UNKNOWN_MODE)
2067182999Smav		return;
2068162922Sariff
2069162922Sariff	/* make screensaver happy */
2070162922Sariff	if (scp == cur_console) {
2071162922Sariff		scrn_time_stamp = time.tv_sec;
2072162922Sariff		if (scrn_blanked)
2073162922Sariff			SCRN_SAVER(0);
2074182999Smav	}
2075162922Sariff	write_in_progress++;
2076162922Sariff	if (scp->term.esc)
2077162922Sariff		scan_esc(scp, c);
2078162922Sariff	else switch(c) {
2079162922Sariff	case 0x1B:	/* start escape sequence */
2080162922Sariff		scp->term.esc = 1;
2081162922Sariff		scp->term.num_param = 0;
2082162922Sariff		break;
2083162922Sariff	case 0x07:
2084164614Sariff		do_bell(scp, scp->bell_pitch, scp->bell_duration);
2085164614Sariff		break;
2086162922Sariff	case '\t':	/* non-destructive tab */
2087162922Sariff		scp->crtat += (8 - scp->xpos % 8);
2088162922Sariff		scp->xpos += (8 - scp->xpos % 8);
2089162922Sariff		break;
2090182999Smav	case '\b':      /* non-destructive backspace */
2091162922Sariff		if (scp->crtat > scp->crt_base) {
2092162922Sariff			scp->crtat--;
2093162922Sariff			if (scp->xpos > 0)
2094163057Sariff				scp->xpos--;
2095162922Sariff			else {
2096162922Sariff				scp->xpos += scp->xsize - 1;
2097162922Sariff				scp->ypos--;
2098162922Sariff			}
2099162922Sariff		}
2100162922Sariff		break;
2101162922Sariff	case '\r':	/* return to pos 0 */
2102182999Smav		move_crsr(scp, 0, scp->ypos);
2103162922Sariff		break;
2104162922Sariff	case '\n':	/* newline, same pos */
2105162922Sariff		scp->crtat += scp->xsize;
2106162922Sariff		scp->ypos++;
2107162922Sariff		break;
2108162922Sariff	case '\f':	/* form feed, clears screen */
2109162922Sariff		clear_screen(scp);
2110162922Sariff		break;
2111162922Sariff	default:
2112163057Sariff		/* Print only printables */
2113184089Smav		*scp->crtat = (scp->term.cur_attr | scr_map[c]);
2114162922Sariff		scp->crtat++;
2115162922Sariff		if (++scp->xpos >= scp->xsize) {
2116162922Sariff			scp->xpos = 0;
2117162922Sariff			scp->ypos++;
2118162922Sariff		}
2119162922Sariff		break;
2120162922Sariff	}
2121182999Smav	/* do we have to scroll ?? */
2122182999Smav	if (scp->crtat >= scp->crt_base + scp->ysize * scp->xsize) {
2123182999Smav		/* process history lines begin */
2124182999Smav		if (scp->history_head+scp->xsize > scp->history+HISTORY_SIZE) {
2125182999Smav			bcopy(scp->history + scp->xsize, scp->history,
2126182999Smav			      (HISTORY_SIZE - scp->xsize) * sizeof(u_short));
2127182999Smav			bcopyw(scp->crt_base, scp->history_head - scp->xsize,
2128182999Smav				scp->xsize * sizeof(u_short));
2129182999Smav		}
2130182999Smav		else {
2131182999Smav			bcopyw(scp->crt_base, scp->history_head,
2132184089Smav				scp->xsize * sizeof(u_short));
2133182999Smav			scp->history_head += scp->xsize;
2134182999Smav		}
2135184089Smav		/* process history lines end */
2136182999Smav
2137182999Smav		bcopyw(scp->crt_base + scp->xsize, scp->crt_base,
2138182999Smav			scp->xsize * (scp->ysize - 1) * sizeof(u_short));
2139182999Smav		fillw(scp->term.cur_attr | scr_map[0x20],
2140182999Smav			scp->crt_base + scp->xsize * (scp->ysize - 1),
2141182999Smav			scp->xsize);
2142182999Smav		scp->crtat -= scp->xsize;
2143182999Smav		scp->ypos--;
2144182999Smav	}
2145182999Smav	write_in_progress--;
2146182999Smav	if (delayed_next_scr)
2147182999Smav		switch_scr(scp, delayed_next_scr - 1);
2148162922Sariff}
2149162922Sariff
2150162922Sariffstatic void
2151162922Sariffscinit(void)
2152162922Sariff{
2153162922Sariff	u_short volatile *cp = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short), was;
2154183097Smav	unsigned cursorat;
2155182999Smav	int i;
2156163057Sariff
2157162922Sariff	/*
2158182999Smav	 * catch that once in a blue moon occurence when scinit is called
2159182999Smav	 * TWICE, adding the CGA_BUF offset again -> poooff
2160182999Smav	 */
2161182999Smav	if (crtat != 0)
2162183024Smav		return;
2163182999Smav	/*
2164182999Smav	 * Crtat initialized to point to MONO buffer, if not present change
2165162922Sariff	 * to CGA_BUF offset. ONLY ADD the difference since locore.s adds
2166162922Sariff	 * in the remapped offset at the "right" time
2167182999Smav	 */
2168182999Smav	was = *cp;
2169182999Smav	*cp = (u_short) 0xA55A;
2170162922Sariff	if (*cp != 0xA55A)
2171162922Sariff		crtc_addr = MONO_BASE;
2172182999Smav	else {
2173182999Smav		*cp = was;
2174182999Smav		crtc_addr = COLOR_BASE;
2175182999Smav		Crtat = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short);
2176162922Sariff	}
2177162922Sariff
2178162922Sariff	/* extract cursor location */
2179182999Smav	outb(crtc_addr,14);
2180162922Sariff	cursorat = inb(crtc_addr+1)<<8 ;
2181182999Smav	outb(crtc_addr,15);
2182162922Sariff	cursorat |= inb(crtc_addr+1);
2183162922Sariff	crtat = Crtat + cursorat;
2184162965Sariff
2185162965Sariff	/* move hardware cursor out of the way */
2186162922Sariff	outb(crtc_addr,14);
2187162922Sariff	outb(crtc_addr+1, 0xff);
2188162965Sariff	outb(crtc_addr,15);
2189162922Sariff	outb(crtc_addr+1, 0xff);
2190162922Sariff
2191182999Smav	/* is this a VGA or higher ? */
2192182999Smav	outb(crtc_addr, 7);
2193162922Sariff	if (inb(crtc_addr) == 7) {
2194182999Smav		u_long	pa;
2195182999Smav		u_long	segoff;
2196182999Smav
2197162922Sariff		crtc_vga = 1;
2198182999Smav
2199182999Smav		/*
2200182999Smav		 * Get the BIOS video mode pointer.
2201182999Smav		 */
2202182999Smav		segoff = *(u_long *)pa_to_va(0x4a8);
2203182999Smav		pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff));
2204182999Smav		if (ISMAPPED(pa, sizeof(u_long))) {
2205182999Smav			segoff = *(u_long *)pa_to_va(pa);
2206182999Smav			pa = (((segoff & 0xffff0000) >> 12)
2207182999Smav			      + (segoff & 0xffff));
2208182999Smav			if (ISMAPPED(pa, 64))
2209182999Smav				video_mode_ptr = (char *)pa_to_va(pa);
2210182999Smav		}
2211182999Smav	}
2212182999Smav	current_default = &user_default;
2213182999Smav	console[0] = &main_console;
2214182999Smav	init_scp(console[0]);
2215182999Smav	console[0]->crt_base = Crtat;
2216182999Smav	console[0]->crtat = crtat;
2217182999Smav	console[0]->xpos = cursorat % COL;
2218182999Smav	console[0]->ypos = cursorat / COL;
2219182999Smav	cur_console = console[0];
2220182999Smav	for (i=1; i<MAXCONS; i++)
2221182999Smav		console[i] = NULL;
2222162922Sariff	kernel_console.esc = 0;
2223162922Sariff	kernel_console.std_attr = kernel_default.std_attr;
2224162922Sariff	kernel_console.rev_attr = kernel_default.rev_attr;
2225162922Sariff	kernel_console.cur_attr = kernel_default.std_attr;
2226162922Sariff	/* initialize mapscrn array to a one to one map */
2227162922Sariff	for (i=0; i<sizeof(scr_map); i++)
2228162922Sariff		scr_map[i] = i;
2229169277Sariff}
2230162922Sariff
2231162922Sariffstatic scr_stat
2232169277Sariff*alloc_scp()
2233162922Sariff{
2234169277Sariff	scr_stat *scp;
2235169277Sariff
2236162922Sariff	scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_NOWAIT);
2237162922Sariff	init_scp(scp);
2238162922Sariff	scp->crt_base = scp->crtat = scp->scr_buf =
2239169277Sariff		(u_short *)malloc(scp->xsize*scp->ysize*2, M_DEVBUF, M_NOWAIT);
2240162922Sariff        if (crtc_vga && video_mode_ptr)
2241169277Sariff		set_mode(scp);
2242162922Sariff	clear_screen(scp);
2243162922Sariff	return scp;
2244162922Sariff}
2245162922Sariff
2246169277Sariffstatic void
2247162922Sariffinit_scp(scr_stat *scp)
2248169277Sariff{
2249169277Sariff	scp->mode = M_VGA_C80x25;
2250169277Sariff	scp->xsize = COL;
2251169277Sariff	scp->ysize = ROW;
2252169277Sariff	scp->term.esc = 0;
2253169277Sariff	scp->term.std_attr = current_default->std_attr;
2254169277Sariff	scp->term.rev_attr = current_default->rev_attr;
2255162922Sariff	scp->term.cur_attr = scp->term.std_attr;
2256162922Sariff	scp->border = BG_BLACK;
2257162922Sariff	scp->cursor_start = -1;
2258169277Sariff	scp->cursor_end = -1;
2259169277Sariff	scp->cursor_protect = 0;
2260169277Sariff	scp->cursor_saveunder = scr_map[0x20];
2261169277Sariff	scp->bell_pitch = BELL_PITCH;
2262169277Sariff	scp->bell_duration = BELL_DURATION;
2263169277Sariff	scp->status = (*(char *)pa_to_va(0x417) & 0x20) ? NLKED : 0;
2264169277Sariff	scp->pid = 0;
2265169277Sariff	scp->proc = NULL;
2266169277Sariff	scp->smode.mode = VT_AUTO;
2267169277Sariff	scp->history_head = scp->history_pos = scp->history;
2268169277Sariff}
2269169277Sariff
2270169277Sariffstatic void
2271169277Sariffscput(u_char c)
2272169277Sariff{
2273169277Sariff	scr_stat *scp = console[0];
2274182999Smav	term_stat save;
2275169277Sariff
2276182999Smav	if (crtat == 0)
2277169277Sariff		scinit();
2278169277Sariff/* SOS
2279169277Sariff	if (!write_in_progress) {
2280169277Sariff		++write_in_progress;
2281169277Sariff*/
2282162922Sariff		save = scp->term;
2283169277Sariff		scp->term = kernel_console;
2284169277Sariff		current_default = &kernel_default;
2285169277Sariff		scp->cursor_protect = 1;
2286169277Sariff		undraw_cursor(scp);
2287169277Sariff		ansi_put(scp, c);
2288169277Sariff		draw_cursor(scp);
2289169277Sariff		scp->cursor_protect = 0;
2290169277Sariff		kernel_console = scp->term;
2291169277Sariff		current_default = &user_default;
2292169277Sariff		scp->term = save;
2293169277Sariff/* SOS
2294182999Smav		--write_in_progress;
2295169277Sariff	} else {
2296182999Smav		if (console_buffer_count < CONSOLE_BUFSIZE)
2297169277Sariff			console_buffer[console_buffer_count++] = c;
2298169277Sariff	}
2299182999Smav*/
2300169277Sariff}
2301162922Sariff
2302169277Sariffstatic u_char
2303162922Sariff*get_fstr(u_int c, u_int *len)
2304162922Sariff{
2305162922Sariff	u_int i;
2306169277Sariff
2307169277Sariff	if (!(c & FKEY))
2308162922Sariff		return(NULL);
2309162922Sariff	i = (c & 0xFF) - F_FN;
2310162922Sariff	if (i > n_fkey_tab)
2311182999Smav		return(NULL);
2312182999Smav	*len = fkey_tab[i].len;
2313182999Smav	return(fkey_tab[i].str);
2314182999Smav}
2315182999Smav
2316182999Smavstatic void
2317182999Smavupdate_leds(int which)
2318182999Smav{
2319182999Smav	int s;
2320182999Smav  	static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
2321182999Smav
2322182999Smav	/* replace CAPS led with ALTGR led for ALTGR keyboards */
2323182999Smav	if (key_map.n_keys > ALTGR_OFFSET) {
2324182999Smav		if (which & ALKED)
2325182999Smav			which |= CLKED;
2326182999Smav		else
2327182999Smav			which &= ~CLKED;
2328182999Smav	}
2329182999Smav	s = spltty();
2330182999Smav	kbd_cmd(KB_SETLEDS);
2331182999Smav	kbd_cmd(xlate_leds[which & LED_MASK]);
2332182999Smav	splx(s);
2333182999Smav}
2334182999Smav
2335182999Smav/*
2336182999Smav * scgetc(noblock) - get character from keyboard.
2337182999Smav * If noblock = 0 wait until a key is pressed.
2338182999Smav * Else return NOKEY.
2339182999Smav */
2340182999Smavu_int
2341182999Smavscgetc(int noblock)
2342182999Smav{
2343182999Smav	u_char scancode, keycode;
2344182999Smav	u_int state, action;
2345182999Smav	struct key_t *key;
2346182999Smav	static u_char esc_flag = 0, compose = 0;
2347182999Smav	static u_int chr = 0;
2348182999Smav
2349182999Smavnext_code:
2350182999Smav	kbd_wait();
2351182999Smav	/* First see if there is something in the keyboard port */
2352182999Smav	if (inb(KB_STAT) & KB_BUF_FULL)
2353182999Smav		scancode = inb(KB_DATA);
2354182999Smav	else if (noblock)
2355182999Smav		return(NOKEY);
2356182999Smav	else
2357182999Smav		goto next_code;
2358182999Smav
2359182999Smav	if (cur_console->status & KBD_RAW_MODE)
2360182999Smav		return scancode;
2361182999Smav#if ASYNCH
2362182999Smav	if (scancode == KB_ACK || scancode == KB_RESEND) {
2363182999Smav		kbd_reply = scancode;
2364182999Smav		if (noblock)
2365182999Smav			return(NOKEY);
2366182999Smav		goto next_code;
2367182999Smav	}
2368182999Smav#endif
2369182999Smav	keycode = scancode & 0x7F;
2370182999Smav	switch (esc_flag) {
2371182999Smav	case 0x00:		/* normal scancode */
2372182999Smav		switch(scancode) {
2373182999Smav		case 0xB8:	/* left alt  (compose key) */
2374182999Smav			if (compose) {
2375182999Smav				compose = 0;
2376182999Smav				if (chr > 255) {
2377182999Smav					do_bell(cur_console,
2378182999Smav						BELL_PITCH, BELL_DURATION);
2379182999Smav					chr = 0;
2380182999Smav				}
2381182999Smav			}
2382182999Smav			break;
2383182999Smav		case 0x38:
2384182999Smav			if (!compose) {
2385182999Smav				compose = 1;
2386182999Smav				chr = 0;
2387182999Smav			}
2388162922Sariff			break;
2389162922Sariff		case 0xE0:
2390162922Sariff		case 0xE1:
2391166965Sariff			esc_flag = scancode;
2392162922Sariff			goto next_code;
2393182999Smav		}
2394182999Smav		break;
2395162922Sariff	case 0xE0:		/* 0xE0 prefix */
2396162922Sariff		esc_flag = 0;
2397162922Sariff		switch (keycode) {
2398162922Sariff		case 0x1C:	/* right enter key */
2399182999Smav			keycode = 0x59;
2400162922Sariff			break;
2401162922Sariff		case 0x1D:	/* right ctrl key */
2402162922Sariff			keycode = 0x5A;
2403162922Sariff			break;
2404166965Sariff		case 0x35:	/* keypad divide key */
2405166965Sariff			keycode = 0x5B;
2406182999Smav			break;
2407182999Smav		case 0x37:	/* print scrn key */
2408182999Smav			keycode = 0x5C;
2409182999Smav			break;
2410182999Smav		case 0x38:	/* right alt key (alt gr) */
2411182999Smav			keycode = 0x5D;
2412182999Smav			break;
2413162965Sariff		case 0x47:	/* grey home key */
2414165281Sariff			keycode = 0x5E;
2415165281Sariff			break;
2416165281Sariff		case 0x48:	/* grey up arrow key */
2417165281Sariff			keycode = 0x5F;
2418165281Sariff			break;
2419165281Sariff		case 0x49:	/* grey page up key */
2420165281Sariff			keycode = 0x60;
2421165281Sariff			break;
2422165281Sariff		case 0x4B:	/* grey left arrow key */
2423165281Sariff			keycode = 0x61;
2424167610Sariff			break;
2425167610Sariff		case 0x4D:	/* grey right arrow key */
2426165281Sariff			keycode = 0x62;
2427165281Sariff			break;
2428162965Sariff		case 0x4F:	/* grey end key */
2429162965Sariff			keycode = 0x63;
2430162922Sariff			break;
2431162965Sariff		case 0x50:	/* grey down arrow key */
2432162922Sariff			keycode = 0x64;
2433162922Sariff			break;
2434162922Sariff		case 0x51:	/* grey page down key */
2435162922Sariff			keycode = 0x65;
2436162922Sariff			break;
2437162922Sariff		case 0x52:	/* grey insert key */
2438162922Sariff			keycode = 0x66;
2439162922Sariff			break;
2440162922Sariff		case 0x53:	/* grey delete key */
2441162922Sariff			keycode = 0x67;
2442162922Sariff			break;
2443162922Sariff
2444162922Sariff		/* the following 3 are only used on the MS "Natural" keyboard */
2445162922Sariff 		case 0x5b:	/* left Window key */
2446162922Sariff 			keycode = 0x69;
2447162922Sariff 			break;
2448162922Sariff 		case 0x5c:	/* right Window key */
2449162922Sariff 			keycode = 0x6a;
2450162922Sariff 			break;
2451162922Sariff 		case 0x5d:	/* menu key */
2452162922Sariff 			keycode = 0x6b;
2453162922Sariff 			break;
2454162922Sariff		default:	/* ignore everything else */
2455166965Sariff			goto next_code;
2456172811Sariff		}
2457172811Sariff		break;
2458166965Sariff	case 0xE1:		/* 0xE1 prefix */
2459166965Sariff		esc_flag = 0;
2460166965Sariff		if (keycode == 0x1D)
2461166965Sariff			esc_flag = 0x1D;
2462166965Sariff		goto next_code;
2463166965Sariff		/* NOT REACHED */
2464166965Sariff	case 0x1D:		/* pause / break */
2465169277Sariff		esc_flag = 0;
2466169277Sariff		if (keycode != 0x45)
2467169277Sariff			goto next_code;
2468169277Sariff		keycode = 0x68;
2469169277Sariff		break;
2470169277Sariff	}
2471166965Sariff
2472186430Smav	/* if scroll-lock pressed allow history browsing */
2473166965Sariff	if (cur_console->status & SLKED) {
2474166965Sariff		cur_console->cursor_protect = 1;
2475166965Sariff		undraw_cursor(cur_console);
2476166965Sariff		if (!(cur_console->status & BUFFER_SAVED)) {
2477166965Sariff			bcopyw(Crtat, cur_console->scr_buf,
2478166965Sariff			      cur_console->xsize * cur_console->ysize *
2479166965Sariff			      sizeof(u_short));
2480166965Sariff			cur_console->status |= BUFFER_SAVED;
2481166965Sariff			cur_console->history_pos = cur_console->history_head;
2482166965Sariff		}
2483166965Sariff		switch (scancode) {
2484166965Sariff		case 0x50:	/* down arrow key */
2485167454Sariff	    	    if (cur_console->history_pos < cur_console->history_head) {
2486167454Sariff			bcopyw(cur_console->crt_base+cur_console->xsize,
2487167454Sariff			       cur_console->crt_base,
2488167454Sariff		               cur_console->xsize * (cur_console->ysize - 1) *
2489167454Sariff			       sizeof(u_short));
2490167454Sariff			if (cur_console->history_pos +
2491166965Sariff		    	    (cur_console->xsize*cur_console->ysize) <
2492186430Smav			    cur_console->history_head) {
2493169277Sariff			    /* from history buffer */
2494169277Sariff			    bcopyw(cur_console->history_pos +
2495169277Sariff		      	             cur_console->xsize*(cur_console->ysize),
2496169277Sariff		  		   cur_console->crt_base +
2497169277Sariff		  		     cur_console->xsize*(cur_console->ysize-1),
2498169277Sariff	          		   cur_console->xsize * sizeof(u_short));
2499169277Sariff			    }
2500169277Sariff			else {
2501169277Sariff			    /* from screen buffer */
2502169277Sariff	    		    bcopyw(cur_console->scr_buf +
2503169277Sariff		      	    	     cur_console->xsize * cur_console->ysize -
2504169277Sariff				     (cur_console->history_head -
2505169277Sariff				     cur_console->history_pos),
2506169277Sariff		  	    	   cur_console->crt_base +
2507169277Sariff				     cur_console->xsize*(cur_console->ysize-1),
2508169277Sariff	              	    	   cur_console->xsize * sizeof(u_short));
2509169277Sariff			}
2510178324Sariff			cur_console->history_pos += cur_console->xsize;
2511178324Sariff		    }
2512178324Sariff		    else
2513178324Sariff			do_bell(cur_console, BELL_PITCH, BELL_DURATION);
2514178324Sariff		    goto next_code;
2515178324Sariff
2516178324Sariff		case 0x48:	/* up arrow key */
2517178324Sariff		    if (cur_console->history_pos > cur_console->history) {
2518178324Sariff		        bcopyw(cur_console->crt_base,
2519178324Sariff		               cur_console->crt_base + cur_console->xsize,
2520169277Sariff		               cur_console->xsize * cur_console->ysize *
2521169277Sariff		                 sizeof(u_short));
2522169277Sariff		        bcopyw(cur_console->history_pos - cur_console->xsize,
2523169277Sariff			       cur_console->crt_base,
2524169277Sariff		               cur_console->xsize * sizeof(u_short));
2525169277Sariff		        cur_console->history_pos -= cur_console->xsize;
2526169277Sariff		    }
2527169277Sariff		    else
2528169277Sariff		    	do_bell(cur_console, BELL_PITCH, BELL_DURATION);
2529169277Sariff		    goto next_code;
2530169277Sariff		}
2531169277Sariff	}
2532169277Sariff
2533169277Sariff	if (compose) {
2534169277Sariff		switch (scancode) {
2535169277Sariff		/* key pressed process it */
2536169277Sariff		case 0x47: case 0x48: case 0x49:	/* keypad 7,8,9 */
2537182999Smav			chr = (scancode - 0x40) + chr*10;
2538182999Smav			goto next_code;
2539182999Smav		case 0x4B: case 0x4C: case 0x4D:	/* keypad 4,5,6 */
2540182999Smav			chr = (scancode - 0x47) + chr*10;
2541171141Sariff			goto next_code;
2542190630Smav		case 0x4F: case 0x50: case 0x51:	/* keypad 1,2,3 */
2543190630Smav			chr = (scancode - 0x4E) + chr*10;
2544169277Sariff			goto next_code;
2545190630Smav		case 0x52:				/* keypad 0 */
2546190630Smav			chr *= 10;
2547190630Smav			goto next_code;
2548190630Smav
2549182999Smav		/* key release, no interest here */
2550169277Sariff		case 0xC7: case 0xC8: case 0xC9:	/* keypad 7,8,9 */
2551190630Smav		case 0xCB: case 0xCC: case 0xCD:	/* keypad 4,5,6 */
2552190630Smav		case 0xCF: case 0xD0: case 0xD1:	/* keypad 1,2,3 */
2553190630Smav		case 0xD2:				/* keypad 0 */
2554190630Smav			goto next_code;
2555190630Smav
2556169277Sariff		case 0x38:				/* left alt key */
2557182999Smav			break;
2558182999Smav		default:
2559169277Sariff			if (chr) {
2560182999Smav				compose = chr = 0;
2561182999Smav				do_bell(cur_console, BELL_PITCH, BELL_DURATION);
2562182999Smav				goto next_code;
2563182999Smav			}
2564182999Smav			break;
2565182999Smav		}
2566182999Smav	}
2567182999Smav
2568182999Smav	state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0));
2569169277Sariff	if ((!agrs && (cur_console->status & ALKED))
2570182999Smav	    || (agrs && !(cur_console->status & ALKED)))
2571182999Smav		keycode += ALTGR_OFFSET;
2572182999Smav	key = &key_map.key[keycode];
2573182999Smav	if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED))
2574182999Smav	     || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) )
2575182999Smav		state ^= 1;
2576182999Smav
2577189879Smav	/* Check for make/break */
2578189879Smav	action = key->map[state];
2579174578Sariff	if (scancode & 0x80) { 		/* key released */
2580189879Smav		if (key->spcl & 0x80) {
2581189879Smav			switch (action) {
2582174578Sariff			case LSH:
2583174578Sariff				shfts &= ~1;
2584189879Smav				break;
2585162922Sariff			case RSH:
2586162922Sariff				shfts &= ~2;
2587182999Smav				break;
2588182999Smav			case LCTR:
2589182999Smav				ctls &= ~1;
2590182999Smav				break;
2591182999Smav			case RCTR:
2592182999Smav				ctls &= ~2;
2593182999Smav				break;
2594182999Smav			case LALT:
2595182999Smav				alts &= ~1;
2596182999Smav				break;
2597182999Smav			case RALT:
2598182999Smav				alts &= ~2;
2599182999Smav				break;
2600166965Sariff			case NLK:
2601166965Sariff				nlkcnt = 0;
2602166965Sariff				break;
2603182999Smav			case CLK:
2604166965Sariff				clkcnt = 0;
2605166965Sariff				break;
2606166965Sariff			case SLK:
2607162922Sariff				slkcnt = 0;
2608162922Sariff				break;
2609162922Sariff			case ASH:
2610166965Sariff				agrs = 0;
2611166965Sariff				break;
2612166965Sariff			case ALK:
2613166965Sariff				alkcnt = 0;
2614166965Sariff				break;
2615166965Sariff			case META:
2616166965Sariff				metas = 0;
2617166965Sariff				break;
2618166965Sariff			}
2619166965Sariff		}
2620182999Smav		if (chr && !compose) {
2621166965Sariff			action = chr;
2622166965Sariff			chr = 0;
2623166965Sariff			return(action);
2624166965Sariff		}
2625166965Sariff	} else {
2626166965Sariff		/* key pressed */
2627166965Sariff		if (key->spcl & (0x80>>state)) {
2628166965Sariff			switch (action) {
2629182999Smav			/* LOCKING KEYS */
2630166965Sariff			case NLK:
2631166965Sariff				if (!nlkcnt) {
2632166965Sariff					nlkcnt++;
2633166965Sariff					if (cur_console->status & NLKED)
2634166965Sariff						cur_console->status &= ~NLKED;
2635166965Sariff					else
2636162922Sariff						cur_console->status |= NLKED;
2637162922Sariff					update_leds(cur_console->status);
2638162922Sariff				}
2639162922Sariff				break;
2640162922Sariff			case CLK:
2641186912Smav				if (!clkcnt) {
2642162922Sariff					clkcnt++;
2643162922Sariff					if (cur_console->status & CLKED)
2644186912Smav						cur_console->status &= ~CLKED;
2645162922Sariff					else
2646162922Sariff						cur_console->status |= CLKED;
2647162922Sariff					update_leds(cur_console->status);
2648162922Sariff				}
2649166965Sariff				break;
2650162922Sariff			case SLK:
2651162922Sariff				if (!slkcnt) {
2652162922Sariff				    slkcnt++;
2653182999Smav				    if (cur_console->status & SLKED) {
2654162922Sariff					cur_console->status &= ~SLKED;
2655162922Sariff					if (cur_console->status & BUFFER_SAVED){
2656162922Sariff					    bcopyw(cur_console->scr_buf, Crtat,
2657162922Sariff					    	   cur_console->xsize *
2658162922Sariff					    	     cur_console->ysize *
2659162922Sariff						     sizeof(u_short));
2660162922Sariff					    cur_console->status&=~BUFFER_SAVED;
2661162965Sariff					    cur_console->history_pos =
2662162922Sariff					        cur_console->history_head;
2663182999Smav					    draw_cursor(cur_console);
2664182999Smav					    cur_console->cursor_protect = 0;
2665162922Sariff					}
2666186912Smav					pcstart(VIRTUAL_TTY(get_scr_num()));
2667186912Smav				    }
2668186912Smav				    else
2669186912Smav				        cur_console->status |= SLKED;
2670162922Sariff				    update_leds(cur_console->status);
2671162922Sariff				}
2672162922Sariff				break;
2673162922Sariff 			case ALK:
2674186912Smav				if (!alkcnt) {
2675186912Smav					alkcnt++;
2676186912Smav 					if (cur_console->status & ALKED)
2677186912Smav 						cur_console->status &= ~ALKED;
2678186912Smav 					else
2679162922Sariff 						cur_console->status |= ALKED;
2680162922Sariff					update_leds(cur_console->status);
2681162922Sariff				}
2682182999Smav  				break;
2683182999Smav
2684182999Smav			/* NON-LOCKING KEYS */
2685182999Smav			case NOP:
2686182999Smav				break;
2687182999Smav			case RBT:
2688182999Smav				shutdown_nice();
2689182999Smav				break;
2690182999Smav			case SUSP:
2691182999Smav				break;
2692182999Smav
2693182999Smav			case DBG:
2694182999Smav#ifdef DDB			/* try to switch to console 0 */
2695182999Smav				if (cur_console->smode.mode == VT_AUTO &&
2696182999Smav		    		    console[0]->smode.mode == VT_AUTO)
2697182999Smav					switch_scr(cur_console, 0);
2698182999Smav				Debugger("manual escape to debugger");
2699182999Smav				return(NOKEY);
2700182999Smav#else
2701182999Smav				printf("No debugger in kernel\n");
2702182999Smav#endif
2703182999Smav				break;
2704187721Smav			case LSH:
2705187721Smav				shfts |= 1;
2706187721Smav				break;
2707187721Smav			case RSH:
2708187721Smav				shfts |= 2;
2709187721Smav				break;
2710182999Smav			case LCTR:
2711182999Smav				ctls |= 1;
2712187721Smav				break;
2713182999Smav			case RCTR:
2714182999Smav				ctls |= 2;
2715182999Smav				break;
2716182999Smav			case LALT:
2717182999Smav				alts |= 1;
2718182999Smav				break;
2719182999Smav			case RALT:
2720182999Smav				alts |= 2;
2721182999Smav				break;
2722182999Smav			case ASH:
2723182999Smav				agrs = 1;
2724182999Smav				break;
2725182999Smav			case META:
2726182999Smav				metas = 1;
2727182999Smav				break;
2728182999Smav			case NEXT:
2729182999Smav				switch_scr(cur_console,
2730182999Smav					   (get_scr_num() + 1) % MAXCONS);
2731182999Smav				break;
2732182999Smav			case BTAB:
2733182999Smav				action = F(16);
2734182999Smav			default:
2735182999Smav				if (action >= F_SCR && action <= L_SCR) {
2736182999Smav					switch_scr(cur_console, action - F_SCR);
2737182999Smav					break;
2738182999Smav				}
2739182999Smav				if (action >= F_FN && action <= L_FN)
2740182999Smav					action |= FKEY;
2741182999Smav				return(action);
2742182999Smav			}
2743182999Smav		}
2744182999Smav		else {
2745182999Smav			if (metas)
2746182999Smav				action |= MKEY;
2747162922Sariff 			return(action);
2748162922Sariff		}
2749162922Sariff	}
2750162922Sariff	goto next_code;
2751162922Sariff}
2752162922Sariff
2753162922Sariffint
2754162922Sariffgetchar(void)
2755162922Sariff{
2756182999Smav	u_char thechar;
2757182999Smav	int s;
2758162922Sariff
2759162922Sariff	polling = 1;
2760162922Sariff	s = splhigh();
2761162922Sariff	scput('>');
2762162922Sariff	thechar = (u_char) scgetc(0);
2763162922Sariff	polling = 0;
2764162922Sariff	splx(s);
2765162922Sariff	switch (thechar) {
2766162922Sariff	default:
2767162922Sariff		if (thechar >= scr_map[0x20])
2768162922Sariff			scput(thechar);
2769162922Sariff		return(thechar);
2770162922Sariff	case cr:
2771162922Sariff	case lf:
2772162922Sariff		scput(cr); scput(lf);
2773162922Sariff		return(lf);
2774162922Sariff	case bs:
2775162922Sariff	case del:
2776162922Sariff		scput(bs); scput(scr_map[0x20]); scput(bs);
2777162922Sariff		return(thechar);
2778162922Sariff	case cntld:
2779162922Sariff		scput('^'); scput('D'); scput('\r'); scput('\n');
2780162922Sariff		return(0);
2781162922Sariff	}
2782162922Sariff}
2783162922Sariff
2784162922Sariffint
2785162922Sariffpcmmap(dev_t dev, int offset, int nprot)
2786162922Sariff{
2787162922Sariff	if (offset > 0x20000 - PAGE_SIZE)
2788162922Sariff		return -1;
2789162922Sariff	return i386_btop((VIDEOMEM + offset));
2790162922Sariff}
2791162922Sariff
2792162922Sariffstatic void
2793162922Sariffkbd_wait(void)
2794162922Sariff{
2795162922Sariff	int i = 1000;
2796162922Sariff
2797162922Sariff	while (i--) {
2798162922Sariff		if ((inb(KB_STAT) & KB_READY) == 0)
2799162922Sariff			break;
2800162922Sariff		DELAY (10);
2801162922Sariff	}
2802162922Sariff}
2803162922Sariff
2804162922Sariffstatic void
2805162922Sariffkbd_cmd(u_char command)
2806162922Sariff{
2807162922Sariff	int retry = 5;
2808162922Sariff	do {
2809162922Sariff		int i = 100000;
2810162922Sariff
2811162922Sariff		kbd_wait();
2812162922Sariff#if ASYNCH
2813162922Sariff		kbd_reply = 0;
2814162922Sariff		outb(KB_DATA, command);
2815162922Sariff		while (i--) {
2816162922Sariff			if (kbd_reply == KB_ACK)
2817162922Sariff				return;
2818162922Sariff			if (kbd_reply == KB_RESEND)
2819162922Sariff				break;
2820162922Sariff		}
2821162922Sariff#else
2822162922Sariff		outb(KB_DATA, command);
2823162922Sariff		while (i--) {
2824162922Sariff			if (inb(KB_STAT) & KB_BUF_FULL) {
2825162922Sariff				int val;
2826162922Sariff				DELAY(10);
2827162922Sariff				val = inb(KB_DATA);
2828162922Sariff				if (val == KB_ACK)
2829162922Sariff					return;
2830162922Sariff				if (val == KB_RESEND)
2831162922Sariff					break;
2832162922Sariff			}
2833162922Sariff		}
2834162922Sariff#endif
2835162922Sariff	} while (retry--);
2836162922Sariff}
2837162922Sariff
2838162922Sariffstatic void
2839162922Sariffset_mode(scr_stat *scp)
2840162922Sariff{
2841162922Sariff	char *modetable;
2842162922Sariff	char special_modetable[64];
2843162922Sariff	int mode, font_size;
2844162922Sariff
2845162922Sariff	if (scp != cur_console)
2846162922Sariff		return;
2847162922Sariff
2848162922Sariff	/* setup video hardware for the given mode */
2849162922Sariff	switch (scp->mode) {
2850162922Sariff	case M_VGA_M80x60:
2851162922Sariff		bcopyw(video_mode_ptr+(64*M_VGA_M80x25),&special_modetable, 64);
2852162922Sariff		special_modetable[2] = 8;
2853162922Sariff		special_modetable[19] = 7;
2854162922Sariff		special_modetable[16] = 0xdf; /* 480 lines */
2855162922Sariff		special_modetable[28] = 0xdf; /* 480 lines */
2856162922Sariff		modetable = special_modetable;
2857162922Sariff		goto setup_mode;
2858162922Sariff
2859164614Sariff	case M_VGA_C80x60:
2860164614Sariff		bcopyw(video_mode_ptr+(64*M_VGA_C80x25),&special_modetable, 64);
2861164614Sariff		special_modetable[2] = 8;
2862164614Sariff		special_modetable[19] = 7;
2863164614Sariff		special_modetable[16] = 0xdf; /* 480 lines */
2864164614Sariff		special_modetable[28] = 0xdf; /* 480 lines */
2865171330Sariff		modetable = special_modetable;
2866164614Sariff		goto setup_mode;
2867164614Sariff
2868164614Sariff	case M_VGA_M80x50:
2869169277Sariff		bcopyw(video_mode_ptr+(64*M_VGA_M80x25),&special_modetable, 64);
2870169277Sariff		special_modetable[2] = 8;
2871169277Sariff		special_modetable[19] = 7;
2872169277Sariff		modetable = special_modetable;
2873169277Sariff		goto setup_mode;
2874164614Sariff
2875164614Sariff       	case M_VGA_C80x50:
2876164614Sariff		bcopyw(video_mode_ptr+(64*M_VGA_C80x25),&special_modetable, 64);
2877164614Sariff		special_modetable[2] = 8;
2878164614Sariff		special_modetable[19] = 7;
2879164614Sariff		modetable = special_modetable;
2880164614Sariff		goto setup_mode;
2881164614Sariff
2882164614Sariff       	case M_ENH_B80x43:
2883164614Sariff		bcopyw(video_mode_ptr+(64*M_ENH_B80x25),&special_modetable, 64);
2884164614Sariff		special_modetable[2] = 8;
2885164614Sariff		special_modetable[19] = 7;
2886164614Sariff		special_modetable[28] = 87;
2887162922Sariff		modetable = special_modetable;
2888164614Sariff		goto setup_mode;
2889164614Sariff
2890164614Sariff	case M_ENH_C80x43:
2891171141Sariff		bcopyw(video_mode_ptr+(64*M_ENH_C80x25),&special_modetable, 64);
2892182999Smav		special_modetable[2] = 8;
2893164614Sariff		special_modetable[19] = 7;
2894164614Sariff		special_modetable[28] = 87;
2895164614Sariff		modetable = special_modetable;
2896164614Sariff		goto setup_mode;
2897164614Sariff
2898182999Smav       	case M_VGA_M80x30:
2899164614Sariff		bcopyw(video_mode_ptr+(64*M_VGA_M80x25),&special_modetable, 64);
2900164614Sariff		special_modetable[16] = 0xdf; /* 480 lines */
2901164614Sariff		special_modetable[28] = 0xdf; /* 480 lines */
2902164614Sariff		modetable = special_modetable;
2903171141Sariff		goto setup_mode;
2904182999Smav
2905182999Smav       	case M_VGA_C80x30:
2906182999Smav		bcopyw(video_mode_ptr+(64*M_VGA_C80x25),&special_modetable, 64);
2907182999Smav		special_modetable[16] = 0xdf; /* 480 lines */
2908182999Smav		special_modetable[28] = 0xdf; /* 480 lines */
2909182999Smav		modetable = special_modetable;
2910182999Smav		goto setup_mode;
2911164614Sariff
2912164614Sariff       	case M_VGA_C40x25: case M_VGA_C80x25:	/* VGA TEXT MODES */
2913182999Smav	case M_VGA_M80x25:
2914182999Smav       	case M_B40x25:     case M_C40x25:
2915182999Smav       	case M_B80x25:     case M_C80x25:
2916164614Sariff       	case M_ENH_B40x25: case M_ENH_C40x25:
2917164614Sariff       	case M_ENH_B80x25: case M_ENH_C80x25:
2918164614Sariff
2919182999Smav		modetable = video_mode_ptr + (scp->mode * 64);
2920182999Smavsetup_mode:
2921182999Smav		set_vgaregs(modetable);
2922182999Smav		font_size = *(modetable + 2);
2923164614Sariff
2924164614Sariff		/* set font type (size) */
2925164614Sariff 		switch (font_size) {
2926164614Sariff 		case 0x08:
2927164614Sariff 	    		outb(TSIDX, 0x03); outb(TSREG, 0x05);	/* font 1 */
2928164614Sariff 			break;
2929164614Sariff 		case 0x0E:
2930164614Sariff 	    		outb(TSIDX, 0x03); outb(TSREG, 0x0A);	/* font 2 */
2931164614Sariff 			break;
2932164614Sariff 		case 0x10:
2933164614Sariff 	    		outb(TSIDX, 0x03); outb(TSREG, 0x00);	/* font 0 */
2934171141Sariff 			break;
2935164614Sariff 		default:
2936164614Sariff 	    		outb(TSIDX, 0x03); outb(TSREG, 0x05);	/* font 1 */
2937164614Sariff 		}
2938169277Sariff		break;
2939164614Sariff
2940164614Sariff	case M_BG320:      case M_CG320:      case M_BG640:
2941169277Sariff	case M_CG320_D:    case M_CG640_E:
2942164614Sariff	case M_CG640x350:  case M_ENH_CG640:
2943171141Sariff	case M_BG640x480:  case M_CG640x480:  case M_VGA_CG320:
2944171141Sariff
2945164614Sariff 		set_vgaregs(video_mode_ptr + (scp->mode * 64));
2946164614Sariff		break;
2947164614Sariff
2948164614Sariff	default:
2949164614Sariff		/* call user defined function XXX */
2950164614Sariff		break;
2951164614Sariff	}
2952164614Sariff
2953164614Sariff	/* set border color for this (virtual) console */
2954164614Sariff	set_border(scp->border);
2955164614Sariff	return;
2956164614Sariff}
2957164614Sariff
2958164614Sariffstatic void
2959164614Sariffset_border(int color)
2960164614Sariff{
2961164614Sariff	inb(crtc_addr+6); 				/* reset flip-flop */
2962164614Sariff	outb(ATC, 0x11); outb(ATC, color);
2963164614Sariff 	inb(crtc_addr+6); 				/* reset flip-flop */
2964164614Sariff 	outb(ATC, 0x20);				/* enable Palette */
2965164614Sariff}
2966164614Sariff
2967164614Sariffstatic void
2968164614Sariffset_vgaregs(char *modetable)
2969164614Sariff{
2970164614Sariff	int i, s = splhigh();
2971164614Sariff
2972164614Sariff	outb(TSIDX, 0x00); outb(TSREG, 0x01);	/* stop sequencer */
2973164614Sariff	outb(TSIDX, 0x07); outb(TSREG, 0x00);	/* unlock registers */
2974164614Sariff	for (i=0; i<4; i++) {			/* program sequencer */
2975164614Sariff		outb(TSIDX, i+1);
2976164614Sariff		outb(TSREG, modetable[i+5]);
2977164614Sariff	}
2978164614Sariff	outb(MISC, modetable[9]);		/* set dot-clock */
2979164614Sariff	outb(TSIDX, 0x00); outb(TSREG, 0x03);	/* start sequencer */
2980164614Sariff	outb(crtc_addr, 0x11);
2981164614Sariff	outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F);
2982164614Sariff	for (i=0; i<25; i++) {			/* program crtc */
2983164614Sariff		outb(crtc_addr, i);
2984164614Sariff		if (i == 14 || i == 15)		/* no hardware cursor */
2985164614Sariff			outb(crtc_addr+1, 0xff);
2986164614Sariff		else
2987164614Sariff			outb(crtc_addr+1, modetable[i+10]);
2988164614Sariff	}
2989164614Sariff	inb(crtc_addr+6); 			/* reset flip-flop */
2990164614Sariff	for (i=0; i<20; i++) {			/* program attribute ctrl */
2991164614Sariff		outb(ATC, i);
2992164614Sariff		outb(ATC, modetable[i+35]);
2993164614Sariff	}
2994164614Sariff	for (i=0; i<9; i++) {			/* program graph data ctrl */
2995164614Sariff		outb(GDCIDX, i);
2996164614Sariff		outb(GDCREG, modetable[i+55]);
2997164614Sariff	}
2998166796Sariff	inb(crtc_addr+6); 			/* reset flip-flop */
2999164614Sariff	outb(ATC ,0x20);			/* enable palette */
3000169277Sariff	splx(s);
3001164614Sariff}
3002164614Sariff
3003164614Sariffstatic void
3004171141Sariffcopy_font(int direction, int segment, int size, char* font)
3005171141Sariff{
3006169277Sariff  	int ch, line, s;
3007164614Sariff	u_char val;
3008164614Sariff
3009164614Sariff 	outb(TSIDX, 0x01); val = inb(TSREG); 		/* blank screen */
3010164614Sariff	outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
3011182999Smav
3012182999Smav	/* setup vga for loading fonts (graphics plane mode) */
3013182999Smav	inb(crtc_addr+6);				/* reset flip/flop */
3014182999Smav	outb(ATC, 0x30); outb(ATC, 0x01);
3015182999Smav	outb(TSIDX, 0x02); outb(TSREG, 0x04);
3016182999Smav	outb(TSIDX, 0x04); outb(TSREG, 0x06);
3017182999Smav	outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
3018182999Smav	outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
3019182999Smav	outb(GDCIDX, 0x06); outb(GDCREG, 0x05);		/* addr = a0000, 64kb */
3020182999Smav    	for (ch=0; ch < 256; ch++)
3021193640Sariff	    for (line=0; line < size; line++)
3022182999Smav		if (direction)
3023182999Smav		    *(char *)pa_to_va(VIDEOMEM+(segment*0x4000)+(ch*32)+line) =
3024182999Smav					font[(ch*size)+line];
3025182999Smav		else
3026182999Smav		    font[(ch*size)+line] =
3027182999Smav		    *(char *)pa_to_va(VIDEOMEM+(segment*0x4000)+(ch*32)+line);
3028182999Smav	/* setup vga for text mode again */
3029182999Smav	s = splhigh();
3030182999Smav	inb(crtc_addr+6);				/* reset flip/flop */
3031182999Smav	outb(ATC, 0x30); outb(ATC, 0x0C);
3032182999Smav	outb(TSIDX, 0x02); outb(TSREG, 0x03);
3033182999Smav	outb(TSIDX, 0x04); outb(TSREG, 0x02);
3034182999Smav	outb(GDCIDX, 0x04); outb(GDCREG, 0x00);
3035182999Smav	outb(GDCIDX, 0x05); outb(GDCREG, 0x10);
3036182999Smav	if (crtc_addr == MONO_BASE) {
3037182999Smav		outb(GDCIDX, 0x06); outb(GDCREG, 0x0A);	/* addr = b0000, 32kb */
3038182999Smav	}
3039182999Smav	else {
3040182999Smav		outb(GDCIDX, 0x06); outb(GDCREG, 0x0E);	/* addr = b8000, 32kb */
3041182999Smav	}
3042182999Smav	splx(s);
3043182999Smav 	outb(TSIDX, 0x01); val = inb(TSREG); 		/* unblank screen */
3044182999Smav	outb(TSIDX, 0x01); outb(TSREG, val & 0xDF);
3045182999Smav}
3046182999Smav
3047182999Smavstatic void
3048182999Smavsave_palette(void)
3049162922Sariff{
3050162922Sariff	int i;
3051162922Sariff
3052162922Sariff  	outb(PALRADR, 0x00);
3053162922Sariff  	for (i=0x00; i<0x300; i++)
3054162922Sariff    		palette[i] = inb(PALDATA);
3055162922Sariff	inb(crtc_addr+6);			/* reset flip/flop */
3056162922Sariff}
3057162922Sariff
3058162922Sariffstatic void
3059171330Sariffload_palette(void)
3060164614Sariff{
3061182999Smav	int i;
3062182999Smav
3063164614Sariff  	outb(PIXMASK, 0xFF);			/* no pixelmask */
3064182999Smav  	outb(PALWADR, 0x00);
3065182999Smav  	for (i=0x00; i<0x300; i++)
3066182999Smav    		 outb(PALDATA, palette[i]);
3067162922Sariff	inb(crtc_addr+6);			/* reset flip/flop */
3068162922Sariff	outb(ATC, 0x20);			/* enable palette */
3069162922Sariff}
3070162922Sariff
3071162922Sariffstatic void
3072162922Sariffdo_bell(scr_stat *scp, int pitch, int duration)
3073162922Sariff{
3074162922Sariff	if (scp == cur_console) {
3075182999Smav		if (configuration & VISUAL_BELL) {
3076162922Sariff			if (blink_in_progress)
3077182999Smav				return;
3078182999Smav			undraw_cursor(scp);
3079182999Smav			bcopy(scp->crt_base, scp->scr_buf,
3080182999Smav			      scp->xsize * scp->ysize * sizeof(u_short));
3081182999Smav			blink_in_progress = 4;
3082182999Smav			timeout((timeout_func_t)blink_screen, scp, hz/10);
3083182999Smav		}
3084182999Smav		else
3085182999Smav			sysbeep(pitch, duration);
3086182999Smav	}
3087162922Sariff}
3088162922Sariff
3089162922Sariffstatic void
3090162922Sariffblink_screen(scr_stat *scp)
3091162922Sariff{
3092162922Sariff	if (blink_in_progress > 1) {
3093162922Sariff		if (blink_in_progress & 1)
3094162922Sariff			fillw(kernel_default.std_attr | scr_map[0x20],
3095162922Sariff			      scp->crt_base, scp->xsize * scp->ysize);
3096162922Sariff		else
3097162922Sariff			fillw(kernel_default.rev_attr | scr_map[0x20],
3098162922Sariff			      scp->crt_base, scp->xsize * scp->ysize);
3099162922Sariff		blink_in_progress--;
3100162922Sariff		timeout((timeout_func_t)blink_screen, scp, hz/10);
3101162922Sariff	}
3102162922Sariff	else {
3103162922Sariff		bcopy(scp->scr_buf, scp->crt_base,
3104162922Sariff		      scp->xsize * scp->ysize * sizeof(u_short));
3105162922Sariff		draw_cursor(scp);
3106162922Sariff		blink_in_progress = 0;
3107162922Sariff	}
3108162922Sariff}
3109162922Sariff
3110162922Sariff#endif /* NSC */
3111162922Sariff