syscons.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,498 行 · 第 1/5 页

C
2,498
字号
/*- * Copyright (c) 1992-1998 S鴕en Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer, *    without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *	$Id: syscons.c,v 1.293.2.3 1999/05/09 11:02:19 yokota Exp $ */#include "sc.h"#include "splash.h"#ifdef __i386__#include "apm.h"#endif#include "opt_ddb.h"#include "opt_devfs.h"#ifdef __i386__#include "opt_vesa.h"#include "opt_vm86.h"#endif#include "opt_syscons.h"#if NSC > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/reboot.h>#include <sys/conf.h>#include <sys/proc.h>#include <sys/signalvar.h>#include <sys/tty.h>#include <sys/kernel.h>#include <sys/malloc.h>#ifdef	DEVFS#include <sys/devfsext.h>#endif#include <machine/bootinfo.h>#include <machine/clock.h>#include <machine/cons.h>#include <machine/console.h>#include <machine/mouse.h>#include <machine/md_var.h>#include <machine/psl.h>#include <machine/frame.h>#include <machine/pc/display.h>#ifdef __i386__#include <machine/pc/vesa.h>#include <machine/apm_bios.h>#include <machine/random.h>#endif#include <vm/vm.h>#include <vm/vm_param.h>#include <vm/pmap.h>#include <dev/kbd/kbdreg.h>#include <dev/fb/fbreg.h>#include <dev/fb/vgareg.h>#include <dev/fb/splashreg.h>#include <dev/syscons/syscons.h>#ifndef __i386__#include <isa/isareg.h>#else#include <i386/isa/isa.h>#include <i386/isa/isa_device.h>#include <i386/isa/timerreg.h>#endif#if !defined(MAXCONS)#define MAXCONS 16#endif#if !defined(SC_MAX_HISTORY_SIZE)#define SC_MAX_HISTORY_SIZE	(1000 * MAXCONS)#endif#if !defined(SC_HISTORY_SIZE)#define SC_HISTORY_SIZE		(ROW * 4)#endif#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE#undef SC_MAX_HISTORY_SIZE#define SC_MAX_HISTORY_SIZE	(SC_HISTORY_SIZE * MAXCONS)#endif#if !defined(SC_MOUSE_CHAR)#define SC_MOUSE_CHAR		(0xd0)#endif#define COLD 0#define WARM 1#define DEFAULT_BLANKTIME	(5*60)		/* 5 minutes */#define MAX_BLANKTIME		(7*24*60*60)	/* 7 days!? *//* for backward compatibility */#define OLD_CONS_MOUSECTL	_IOWR('c', 10, old_mouse_info_t)typedef struct old_mouse_data {    int x;    int y;    int buttons;} old_mouse_data_t;typedef struct old_mouse_info {    int operation;    union {	struct old_mouse_data data;	struct mouse_mode mode;    } u;} old_mouse_info_t;static default_attr user_default = {    (FG_LIGHTGREY | BG_BLACK) << 8,    (FG_BLACK | BG_LIGHTGREY) << 8};static default_attr kernel_default = {    (FG_WHITE | BG_BLACK) << 8,    (FG_BLACK | BG_LIGHTGREY) << 8};static  scr_stat    	main_console;static  scr_stat    	*console[MAXCONS];#ifdef DEVFSstatic	void		*sc_devfs_token[MAXCONS];static	void		*sc_mouse_devfs_token;static	void		*sc_console_devfs_token;#endif	scr_stat    	*cur_console;static  scr_stat    	*new_scp, *old_scp;static  term_stat   	kernel_console;static  default_attr    *current_default;static  int		sc_flags;static  char        	init_done = COLD;static  u_short		sc_buffer[ROW*COL];static  char		shutdown_in_progress = FALSE;static  char        	font_loading_in_progress = FALSE;static  char        	switch_in_progress = FALSE;static  char        	write_in_progress = FALSE;static  char        	blink_in_progress = FALSE;static  int        	blinkrate = 0;static	int		adapter = -1;static	int		keyboard = -1;static	keyboard_t	*kbd;static  int     	delayed_next_scr = FALSE;static  long        	scrn_blank_time = 0;    /* screen saver timeout value */static	int     	scrn_blanked = FALSE;	/* screen saver active flag */static  long		scrn_time_stamp;static	int		saver_mode = CONS_LKM_SAVER; /* LKM/user saver */static	int		run_scrn_saver = FALSE;	/* should run the saver? */static	int		scrn_idle = FALSE;	/* about to run the saver */#if NSPLASH > 0static	int		scrn_saver_failed;#endif	u_char      	scr_map[256];	u_char      	scr_rmap[256];static	int		initial_video_mode;	/* initial video mode # */	int     	fonts_loaded = 0#ifdef STD8X16FONT	| FONT_16#endif	;	u_char		font_8[256*8];	u_char		font_14[256*14];#ifdef STD8X16FONTextern#endif	u_char		font_16[256*16];	u_char        	palette[256*3];static	u_char 		*cut_buffer;static	int		cut_buffer_size;static	int		mouse_level;		/* sysmouse protocol level */static	mousestatus_t	mouse_status = { 0, 0, 0, 0, 0, 0 };static  u_short 	mouse_and_mask[16] = {				0xc000, 0xe000, 0xf000, 0xf800,				0xfc00, 0xfe00, 0xff00, 0xff80,				0xfe00, 0x1e00, 0x1f00, 0x0f00,				0x0f00, 0x0000, 0x0000, 0x0000			};static  u_short 	mouse_or_mask[16] = {				0x0000, 0x4000, 0x6000, 0x7000,				0x7800, 0x7c00, 0x7e00, 0x6800,				0x0c00, 0x0c00, 0x0600, 0x0600,				0x0000, 0x0000, 0x0000, 0x0000			};	int		sc_history_size = SC_HISTORY_SIZE;static	int		extra_history_size = 			    SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS;static void    		none_saver(int blank) { }static void    		(*current_saver)(int blank) = none_saver;       d_ioctl_t  	*sc_user_ioctl;static int		sticky_splash = FALSE;static struct 		{			    u_int8_t	cursor_start;			    u_int8_t	cursor_end;			    u_int8_t	shift_state;			} bios_value;/* OS specific stuff */#ifdef not_yet_done#define VIRTUAL_TTY(x)  (sccons[x] = ttymalloc(sccons[x]))struct  CONSOLE_TTY 	(sccons[MAXCONS] = ttymalloc(sccons[MAXCONS]))struct  MOUSE_TTY 	(sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1]))struct  tty         	*sccons[MAXCONS+2];#else#define VIRTUAL_TTY(x)  &sccons[x]#define CONSOLE_TTY 	&sccons[MAXCONS]#define MOUSE_TTY 	&sccons[MAXCONS+1]static struct tty     	sccons[MAXCONS+2];#endif#define SC_MOUSE 	128#define SC_CONSOLE	255vm_offset_t         	Crtat;static const int	nsccons = MAXCONS+2;#define WRAPHIST(scp, pointer, offset)\    ((scp)->history + ((((pointer) - (scp)->history) + (scp)->history_size \    + (offset)) % (scp)->history_size))#define ISSIGVALID(sig)	((sig) > 0 && (sig) < NSIG)/* some useful macros */#define kbd_read_char(kbd, wait)					\		(*kbdsw[(kbd)->kb_index]->read_char)((kbd), (wait))#define kbd_check_char(kbd)						\		(*kbdsw[(kbd)->kb_index]->check_char)((kbd))#define kbd_enable(kbd)							\		(*kbdsw[(kbd)->kb_index]->enable)((kbd))#define kbd_disable(kbd)						\		(*kbdsw[(kbd)->kb_index]->disable)((kbd))#define kbd_lock(kbd, lockf)						\		(*kbdsw[(kbd)->kb_index]->lock)((kbd), (lockf))#define kbd_ioctl(kbd, cmd, arg)					\	    (((kbd) == NULL) ?						\		ENODEV : (*kbdsw[(kbd)->kb_index]->ioctl)((kbd), (cmd), (arg)))#define kbd_clear_state(kbd)						\		(*kbdsw[(kbd)->kb_index]->clear_state)((kbd))#define kbd_get_fkeystr(kbd, fkey, len)					\		(*kbdsw[(kbd)->kb_index]->get_fkeystr)((kbd), (fkey), (len))#define kbd_poll(kbd, on)						\		(*kbdsw[(kbd)->kb_index]->poll)((kbd), (on))/* prototypes */static kbd_callback_func_t sckbdevent;static int scparam(struct tty *tp, struct termios *t);static int scvidprobe(int unit, int flags, int cons);static int sckbdprobe(int unit, int flags, int cons);static void scstart(struct tty *tp);static void scmousestart(struct tty *tp);static void scinit(void);static void scshutdown(int howto, void *arg);static u_int scgetc(keyboard_t *kbd, u_int flags);#define SCGETC_CN	1#define SCGETC_NONBLOCK	2static int sccngetch(int flags);static void sccnupdate(scr_stat *scp);static scr_stat *alloc_scp(void);static void init_scp(scr_stat *scp);static void get_bios_values(void);static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark);static int get_scr_num(void);static timeout_t scrn_timer;static void scrn_update(scr_stat *scp, int show_cursor);#if NSPLASH > 0static int scsplash_callback(int);static void scsplash_saver(int show);static int add_scrn_saver(void (*this_saver)(int));static int remove_scrn_saver(void (*this_saver)(int));static int set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border);static int restore_scrn_saver_mode(scr_stat *scp, int changemode);static void stop_scrn_saver(void (*saver)(int));static int wait_scrn_saver_stop(void);#define scsplash_stick(stick)		(sticky_splash = (stick))#else /* !NSPLASH */#define stop_scrn_saver(saver)#define wait_scrn_saver_stop()		0#define scsplash_stick(stick)#endif /* NSPLASH */static int switch_scr(scr_stat *scp, u_int next_scr);static void exchange_scr(void);static void scan_esc(scr_stat *scp, u_char c);static void ansi_put(scr_stat *scp, u_char *buf, int len);static void draw_cursor_image(scr_stat *scp); static void remove_cursor_image(scr_stat *scp); static void move_crsr(scr_stat *scp, int x, int y);static void history_to_screen(scr_stat *scp);static int history_up_line(scr_stat *scp);static int history_down_line(scr_stat *scp);static int mask2attr(struct term_stat *term);static int save_kbd_state(scr_stat *scp);static int update_kbd_state(int state, int mask);static int update_kbd_leds(int which);static void set_destructive_cursor(scr_stat *scp);static void set_mouse_pos(scr_stat *scp);static int skip_spc_right(scr_stat *scp, u_short *p);static int skip_spc_left(scr_stat *scp, u_short *p);static void mouse_cut(scr_stat *scp);static void mouse_cut_start(scr_stat *scp);static void mouse_cut_end(scr_stat *scp);static void mouse_cut_word(scr_stat *scp);static void mouse_cut_line(scr_stat *scp);static void mouse_cut_extend(scr_stat *scp);static void mouse_paste(scr_stat *scp);static void draw_mouse_image(scr_stat *scp); static void remove_mouse_image(scr_stat *scp); static void draw_cutmarking(scr_stat *scp); static void remove_cutmarking(scr_stat *scp); static void do_bell(scr_stat *scp, int pitch, int duration);static timeout_t blink_screen;#define	CDEV_MAJOR	12#ifdef __i386__static cn_probe_t	sccnprobe;static cn_init_t	sccninit;static cn_getc_t	sccngetc;static cn_checkc_t	sccncheckc;static cn_putc_t	sccnputc;CONS_DRIVER(sc, sccnprobe, sccninit, sccngetc, sccncheckc, sccnputc);#else /* !__i386__ */static cn_getc_t	sccngetc;static cn_checkc_t	sccncheckc;static cn_putc_t	sccnputc;struct consdev sc_cons = {    NULL, NULL, sccngetc, sccncheckc, sccnputc,    NULL, makedev(CDEV_MAJOR, 0), CN_NORMAL,};#endif /* __i386__ */static	d_open_t	scopen;static	d_close_t	scclose;static	d_read_t	scread;static	d_write_t	scwrite;static	d_ioctl_t	scioctl;static	d_mmap_t	scmmap;struct cdevsw	sc_cdevsw = {	scopen,		scclose,	scread,		scwrite,	scioctl,	nullstop,	noreset,	scdevtotty,	ttpoll,		scmmap,		nostrategy,	"sc",	NULL,		-1,		nodump,		nopsize,	D_TTY,};#ifdef __i386__#define fillw_io(p, b, c)	fillw((p), (void *)(b), (c))#endif#ifdef __alpha__static voidfillw(int pat, void *base, size_t cnt){    u_short *sp = base;    while (cnt--)	*sp++ = pat;}static voidfillw_io(int pat, u_int32_t base, size_t cnt){    while (cnt--) {	writew(base, pat);	base += 2;    }}#endifstatic voiddraw_cursor_image(scr_stat *scp){    u_short cursor_image;    vm_offset_t ptr;    u_short prev_image;    if (ISPIXELSC(scp)) {	sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, 	  scp->cursor_pos - scp->scr_buf, 1);	return;    }    ptr = scp->adp->va_window + 2*(scp->cursor_pos - scp->scr_buf);    /* do we have a destructive cursor ? */    if (sc_flags & CHAR_CURSOR) {	prev_image = scp->cursor_saveunder;	cursor_image = readw(ptr) & 0x00ff;	if (cursor_image == DEAD_CHAR) 	    cursor_image = prev_image & 0x00ff;	cursor_image |= *(scp->cursor_pos) & 0xff00;	scp->cursor_saveunder = cursor_image;	/* update the cursor bitmap if the char under the cursor has changed */	if (prev_image != cursor_image) 	    set_destructive_cursor(scp);	/* modify cursor_image */	if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){	    /* 	     * When the mouse pointer is at the same position as the cursor,	     * the cursor bitmap needs to be updated even if the char under 	     * the cursor hasn't changed, because the mouse pionter may 	     * have moved by a few dots within the cursor cel.	     */	    if ((prev_image == cursor_image) 		    && (cursor_image != *(scp->cursor_pos)))	        set_destructive_cursor(scp);	    cursor_image &= 0xff00;	    cursor_image |= DEAD_CHAR;	}    } else {	cursor_image = (readw(ptr) & 0x00ff) | (*(scp->cursor_pos) & 0xff00);	scp->cursor_saveunder = cursor_image;	if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){	    if ((cursor_image & 0x7000) == 0x7000) {		cursor_image &= 0x8fff;		if(!(cursor_image & 0x0700))		    cursor_image |= 0x0700;	    } else {		cursor_image |= 0x7000;		if ((cursor_image & 0x0700) == 0x0700)		    cursor_image &= 0xf0ff;	    }	}    }    writew(ptr, cursor_image);}static voidremove_cursor_image(scr_stat *scp){    if (ISPIXELSC(scp))	sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, 		 scp->cursor_oldpos - scp->scr_buf, 0);    else	writew(scp->adp->va_window + 2*(scp->cursor_oldpos - scp->scr_buf),	       scp->cursor_saveunder);}static voidmove_crsr(scr_stat *scp, int x, int y){    if (x < 0)	x = 0;    if (y < 0)	y = 0;    if (x >= scp->xsize)	x = scp->xsize-1;    if (y >= scp->ysize)	y = scp->ysize-1;    scp->xpos = x;    scp->ypos = y;    scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos;}intsc_probe_unit(int unit, int flags){    if (!scvidprobe(unit, flags, FALSE)) {	if (bootverbose)	    printf("sc%d: no video adapter is found.\n", unit);	return ENXIO;    }    return ((sckbdprobe(unit, flags, FALSE)) ? 0 : ENXIO);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?