syscons.c

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

C
2,455
字号
/*- * Copyright (c) 1992-1995 Sxren 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 *    in this position and unchanged. * 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 withough 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.117.4.16 1997/02/05 05:41:50 davidg Exp $ */#include "sc.h"#include "apm.h"#if NSC > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/conf.h>#include <sys/ioctl.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/tty.h>#include <sys/uio.h>#include <sys/callout.h>#include <sys/kernel.h>#include <sys/syslog.h>#include <sys/errno.h>#include <sys/malloc.h>#include <sys/devconf.h>#include <machine/clock.h>#include <machine/console.h>#include <machine/psl.h>#include <machine/frame.h>#include <machine/pc/display.h>#include <machine/apm_bios.h>#include <machine/random.h>#include <i386/isa/isa.h>#include <i386/isa/isa_device.h>#include <i386/isa/timerreg.h>#include <i386/isa/kbdtables.h>#include <i386/i386/cons.h>#include <i386/isa/syscons.h>#if !defined(MAXCONS)#define MAXCONS 16#endif/* this may break on older VGA's but is usefull on real 32 bit systems */#define bcopyw  bcopystatic 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];	scr_stat    	*cur_console;static  scr_stat    	*new_scp, *old_scp;static  term_stat   	kernel_console;static  default_attr    *current_default;static  char        	init_done = FALSE;static  int     	configuration = 0;static  char        	switch_in_progress = FALSE;static  char        	blink_in_progress = FALSE;static  char        	write_in_progress = FALSE;	u_int       	crtc_addr = MONO_BASE;static  char        	crtc_vga = FALSE;static  u_char      	shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0;static  u_char      	nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0;static  char        	*font_8 = NULL, *font_14 = NULL, *font_16 = NULL;static  int     	fonts_loaded = 0;	char        	palette[3*256];static  const u_int     n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab);static  int     	delayed_next_scr = FALSE;static  long        	scrn_blank_time = 0;    /* screen saver timeout value */	int     	scrn_blanked = FALSE;   /* screen saver active flag */static  int     	scrn_saver = 0;    	/* screen saver routine */static  long       	scrn_time_stamp;	u_char      	scr_map[256];static  char        	*video_mode_ptr = NULL;#if ASYNCHstatic  u_char      	kbd_reply = 0;#endifstatic  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};void    none_saver(int blank) { }void    (*current_saver)() = none_saver;/* 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  tty         	*sccons[MAXCONS+1];#else#define VIRTUAL_TTY(x)  &sccons[x]#define CONSOLE_TTY 	&sccons[MAXCONS]struct  tty         	sccons[MAXCONS+1];int			nsccons = MAXCONS+1;#endif#define MONO_BUF    	pa_to_va(0xB0000)#define CGA_BUF     	pa_to_va(0xB8000)u_short         	*Crtat = (u_short *)MONO_BUF;#define WRAPHIST(scp, pointer, offset)\    ((scp->history) + ((((pointer) - (scp->history)) + (scp->history_size)\    + (offset)) % (scp->history_size)))struct  isa_driver scdriver = {    scprobe, scattach, "sc", 1};intscprobe(struct isa_device *dev){    int i, j, retries = 5;    unsigned char val;    int xt_keyboard = 0;    /* Enable interrupts and keyboard controller */    kbd_wait();    outb(KB_STAT, KB_WRITE);    kbd_wait();    outb(KB_DATA, KB_MODE);    /* flush any noise in the buffer */    while (inb(KB_STAT) & KB_BUF_FULL) {	DELAY(10);	(void) inb(KB_DATA);    }    /* Reset keyboard hardware */    while (retries--) {	kbd_wait();	outb(KB_DATA, KB_RESET);	for (i=0; i<100000; i++) {	    DELAY(10);	    val = inb(KB_DATA);	    if (val == KB_ACK || val == KB_ECHO)		goto gotres;	    if (val == KB_RESEND)		break;	}    }gotres:    if (retries < 0)	printf("scprobe: keyboard won't accept RESET command\n");    else {	i = 10;			/* At most 10 retries. */gotack:	DELAY(100);	j = 1000;		/* Wait at most 1 s. */	while ((inb(KB_STAT) & KB_BUF_FULL) == 0 && --j > 0) DELAY(1000);	DELAY(1000);	val = inb(KB_DATA);	if (val == KB_ACK && --i > 0)	    goto gotack;	if (val != KB_RESET_DONE)	    printf("scprobe: keyboard RESET failed (result = 0x%02x)\n", val);    }    /*     * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards     * such as those on the IBM ThinkPad laptop computers can be used     * with the standard console driver.     */    if ( dev->id_flags & XT_KEYBD )        xt_keyboard = 1;#ifdef XT_KEYBOARD    xt_keyboard = 1;#endif    if ( xt_keyboard ) {        kbd_wait();        outb(KB_DATA, 0xF0);        kbd_wait();        outb(KB_DATA, 1);        kbd_wait();    }    return (IO_KBDSIZE);}static struct kern_devconf kdc_sc[NSC] = {    0, 0, 0,        		/* filled in by dev_attach */    "sc", 0, { MDDT_ISA, 0, "tty" },    isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,    &kdc_isa0,      		/* parent */    0,          		/* parentdata */    DC_BUSY,        		/* the console is almost always busy */    "Graphics console",    DC_CLS_DISPLAY		/* class */};static inline voidsc_registerdev(struct isa_device *id){    if(id->id_unit)	kdc_sc[id->id_unit] = kdc_sc[0];    kdc_sc[id->id_unit].kdc_unit = id->id_unit;    kdc_sc[id->id_unit].kdc_isa = id;    dev_attach(&kdc_sc[id->id_unit]);}#if NAPM > 0static intscresume(void *dummy){	shfts = 0;	ctls = 0;	alts = 0;	agrs = 0;	metas = 0;	return 0;}#endifintscattach(struct isa_device *dev){    scr_stat *scp;    scinit();    configuration = dev->id_flags;    scp = console[0];    if (crtc_vga) {	font_8 = (char *)malloc(8*256, M_DEVBUF, M_NOWAIT);	font_14 = (char *)malloc(14*256, M_DEVBUF, M_NOWAIT);	font_16 = (char *)malloc(16*256, M_DEVBUF, M_NOWAIT);	copy_font(SAVE, FONT_16, font_16);	fonts_loaded = FONT_16;	scp->font = FONT_16;	save_palette();    }    scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short),				     M_DEVBUF, M_NOWAIT);    /* copy screen to buffer */    bcopyw(Crtat, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short));    scp->cursor_pos = scp->scr_buf + scp->xpos + scp->ypos * scp->xsize;    scp->mouse_pos = scp->scr_buf;    /* initialize history buffer & pointers */    scp->history_head = scp->history_pos = scp->history =	(u_short *)malloc(scp->history_size*sizeof(u_short),			  M_DEVBUF, M_NOWAIT);    bzero(scp->history_head, scp->history_size*sizeof(u_short));    /* initialize cursor stuff */    draw_cursor(scp, TRUE);    if (crtc_vga && (configuration & CHAR_CURSOR))	set_destructive_cursor(scp, TRUE);    /* get screen update going */    scrn_timer();    update_leds(scp->status);    sc_registerdev(dev);    printf("sc%d: ", dev->id_unit);    if (crtc_vga)	if (crtc_addr == MONO_BASE)	    printf("VGA mono");	else	    printf("VGA color");    else	if (crtc_addr == MONO_BASE)	    printf("MDA/hercules");	else	    printf("CGA/EGA");    printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, configuration);#if NAPM > 0    scp->r_hook.ah_fun = scresume;    scp->r_hook.ah_arg = NULL;    scp->r_hook.ah_name = "system keyboard";    scp->r_hook.ah_order = APM_MID_ORDER;    apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook);#endif    return 0;}struct tty*scdevtotty(dev_t dev){    int unit = minor(dev);    if (!init_done)	return(NULL);    if (unit > MAXCONS || unit < 0)	return(NULL);    if (unit == MAXCONS)	return CONSOLE_TTY;    return VIRTUAL_TTY(unit);}static scr_stat*get_scr_stat(dev_t dev){    int unit = minor(dev);    if (unit > MAXCONS || unit < 0)	return(NULL);    if (unit == MAXCONS)	return console[0];    return console[unit];}static intget_scr_num(){    int i = 0;    while ((i < MAXCONS) && (cur_console != console[i]))	i++;    return i < MAXCONS ? i : 0;}intscopen(dev_t dev, int flag, int mode, struct proc *p){    struct tty *tp = scdevtotty(dev);    if (!tp)	return(ENXIO);    tp->t_oproc = scstart;    tp->t_param = scparam;    tp->t_dev = dev;    if (!(tp->t_state & TS_ISOPEN)) {	ttychars(tp);	tp->t_iflag = TTYDEF_IFLAG;	tp->t_oflag = TTYDEF_OFLAG;	tp->t_cflag = TTYDEF_CFLAG;	tp->t_lflag = TTYDEF_LFLAG;	tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;	scparam(tp, &tp->t_termios);	ttsetwater(tp);	(*linesw[tp->t_line].l_modem)(tp, 1);    }    else	if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)	    return(EBUSY);    if (!console[minor(dev)])	console[minor(dev)] = alloc_scp();    return((*linesw[tp->t_line].l_open)(dev, tp));}intscclose(dev_t dev, int flag, int mode, struct proc *p){    struct tty *tp = scdevtotty(dev);    struct scr_stat *scp;    if (!tp)	return(ENXIO);    if (minor(dev) < MAXCONS) {	scp = get_scr_stat(tp->t_dev);	if (scp->status & SWITCH_WAIT_ACQ)	    wakeup((caddr_t)&scp->smode);#if not_yet_done	if (scp == &main_console) {	    scp->pid = 0;	    scp->proc = NULL;	    scp->smode.mode = VT_AUTO;	}	else {	    free(scp->scr_buf, M_DEVBUF);	    free(scp->history, M_DEVBUF);	    free(scp, M_DEVBUF);	    console[minor(dev)] = NULL;	}#else	scp->pid = 0;	scp->proc = NULL;	scp->smode.mode = VT_AUTO;#endif    }    spltty();    (*linesw[tp->t_line].l_close)(tp, flag);    ttyclose(tp);    spl0();    return(0);}intscread(dev_t dev, struct uio *uio, int flag){    struct tty *tp = scdevtotty(dev);    if (!tp)	return(ENXIO);    return((*linesw[tp->t_line].l_read)(tp, uio, flag));}intscwrite(dev_t dev, struct uio *uio, int flag){    struct tty *tp = scdevtotty(dev);    if (!tp)	return(ENXIO);    return((*linesw[tp->t_line].l_write)(tp, uio, flag));}voidscintr(int unit){    static struct tty *cur_tty;    int c, len;    u_char *cp;    /* make screensaver happy */    scrn_time_stamp = time.tv_sec;    if (scrn_blanked) {	(*current_saver)(FALSE);	cur_console->start = 0;	cur_console->end = cur_console->xsize * cur_console->ysize;    }    c = scgetc(1);    cur_tty = VIRTUAL_TTY(get_scr_num());    if (!(cur_tty->t_state & TS_ISOPEN))	if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN))	    return;    switch (c & 0xff00) {    case 0x0000: /* normal key */	(*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);	break;    case NOKEY: /* nothing there */	break;    case FKEY:  /* function key, return string */	if (cp = get_fstr((u_int)c, (u_int *)&len)) {	    while (len-- >  0)		(*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty);	}	break;    case MKEY:  /* meta is active, prepend ESC */	(*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);	(*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);	break;    case BKEY:  /* backtab fixed sequence (esc [ Z) */	(*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);	(*linesw[cur_tty->t_line].l_rint)('[', cur_tty);	(*linesw[cur_tty->t_line].l_rint)('Z', cur_tty);	break;    }}intscparam(struct tty *tp, struct termios *t){    tp->t_ispeed = t->c_ispeed;    tp->t_ospeed = t->c_ospeed;    tp->t_cflag = t->c_cflag;    return 0;}

⌨️ 快捷键说明

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