syscons.c

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

C
2,455
字号
intscioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p){    int i, error;    struct tty *tp;    struct trapframe *fp;    scr_stat *scp;    tp = scdevtotty(dev);    if (!tp)	return ENXIO;    scp = get_scr_stat(tp->t_dev);    switch (cmd) {  		/* process console hardware related ioctl's */    case GIO_ATTR:      	/* get current attributes */	*(int*)data = scp->term.cur_attr;	return 0;    case GIO_COLOR:     	/* is this a color console ? */	if (crtc_addr == COLOR_BASE)	    *(int*)data = 1;	else	    *(int*)data = 0;	return 0;    case CONS_CURRENT:  	/* get current adapter type */	if (crtc_vga)	    *(int*)data = KD_VGA;	else	    if (crtc_addr == MONO_BASE)		*(int*)data = KD_MONO;	    else		*(int*)data = KD_CGA;	return 0;    case CONS_GET:      	/* get current video mode */	*(int*)data = scp->mode;	return 0;    case CONS_BLANKTIME:    	/* set screen saver timeout (0 = no saver) */	scrn_blank_time = *(int*)data;	return 0;    case CONS_CURSORTYPE:   	/* set cursor type blink/noblink */	if ((*(int*)data) & 0x01)	    configuration |= BLINK_CURSOR;	else	    configuration &= ~BLINK_CURSOR;	if ((*(int*)data) & 0x02) {	    configuration |= CHAR_CURSOR;	    set_destructive_cursor(scp, TRUE);	} else	    configuration &= ~CHAR_CURSOR;	return 0;    case CONS_BELLTYPE: 	/* set bell type sound/visual */	if (*data)	    configuration |= VISUAL_BELL;	else	    configuration &= ~VISUAL_BELL;	return 0;    case CONS_HISTORY:  	/* set history size */	if (*data) {	    free(scp->history, M_DEVBUF);	    scp->history_size = *(int*)data;	    if (scp->history_size < scp->ysize)		scp->history = NULL;	    else {		scp->history_size *= scp->xsize;		scp->history_head = scp->history_pos = scp->history =		    (u_short *)malloc(scp->history_size*sizeof(u_short),				      M_DEVBUF, M_WAITOK);		bzero(scp->history_head, scp->history_size*sizeof(u_short));	    }	    return 0;	}	else	    return EINVAL;    case CONS_MOUSECTL:		/* control mouse arrow */    {	mouse_info_t *mouse = (mouse_info_t*)data;	int fontsize;	switch (scp->font) {	default:	case FONT_8:	    fontsize = 8; break;	case FONT_14:	    fontsize = 14; break;	case FONT_16:	    fontsize = 16; break;	}	switch (mouse->operation) {	case MOUSE_SHOW:	    if (!(scp->status & MOUSE_ENABLED)) {		scp->mouse_oldpos = Crtat + (scp->mouse_pos - scp->scr_buf);		scp->status |= (UPDATE_MOUSE | MOUSE_ENABLED);	    }	    else		return EINVAL;	    break;	case MOUSE_HIDE:	    if (scp->status & MOUSE_ENABLED) {		scp->status &= ~MOUSE_ENABLED;		scp->status |= UPDATE_MOUSE;	    }	    else		return EINVAL;	    break;	case MOUSE_MOVEABS:	    scp->mouse_xpos = mouse->x;	    scp->mouse_ypos = mouse->y;	    goto set_mouse_pos;	case MOUSE_MOVEREL:	    scp->mouse_xpos += mouse->x;	    scp->mouse_ypos += mouse->y;set_mouse_pos:	    if (scp->mouse_xpos < 0)		scp->mouse_xpos = 0;	    if (scp->mouse_ypos < 0)		scp->mouse_ypos = 0;	    if (scp->mouse_xpos >= scp->xsize*8)		scp->mouse_xpos = (scp->xsize*8)-1;	    if (scp->mouse_ypos >= scp->ysize*fontsize)		scp->mouse_ypos = (scp->ysize*fontsize)-1;	    scp->mouse_pos = scp->scr_buf +		(scp->mouse_ypos/fontsize)*scp->xsize + scp->mouse_xpos/8;	    if (scp->status & MOUSE_ENABLED)		scp->status |= UPDATE_MOUSE;	    break;	case MOUSE_GETPOS:	    mouse->x = scp->mouse_xpos;	    mouse->y = scp->mouse_ypos;	    return 0;	default:	    return EINVAL;	}	/* make screensaver happy */	if (scp == cur_console) {	    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;	    }	}	return 0;    }    case CONS_GETINFO:  	/* get current (virtual) console info */    {	vid_info_t *ptr = (vid_info_t*)data;	if (ptr->size == sizeof(struct vid_info)) {	    ptr->m_num = get_scr_num();	    ptr->mv_col = scp->xpos;	    ptr->mv_row = scp->ypos;	    ptr->mv_csz = scp->xsize;	    ptr->mv_rsz = scp->ysize;	    ptr->mv_norm.fore = (scp->term.std_attr & 0x0f00)>>8;	    ptr->mv_norm.back = (scp->term.std_attr & 0xf000)>>12;	    ptr->mv_rev.fore = (scp->term.rev_attr & 0x0f00)>>8;	    ptr->mv_rev.back = (scp->term.rev_attr & 0xf000)>>12;	    ptr->mv_grfc.fore = 0;      /* not supported */	    ptr->mv_grfc.back = 0;      /* not supported */	    ptr->mv_ovscan = scp->border;	    ptr->mk_keylock = scp->status & LOCK_KEY_MASK;	    return 0;	}	return EINVAL;    }    case CONS_GETVERS:  	/* get version number */	*(int*)data = 0x200;    /* version 2.0 */	return 0;    /* VGA TEXT MODES */    case SW_VGA_C40x25:    case SW_VGA_C80x25: case SW_VGA_M80x25:    case SW_VGA_C80x30: case SW_VGA_M80x30:    case SW_VGA_C80x50: case SW_VGA_M80x50:    case SW_VGA_C80x60: case SW_VGA_M80x60:    case SW_B40x25:     case SW_C40x25:    case SW_B80x25:     case SW_C80x25:    case SW_ENH_B40x25: case SW_ENH_C40x25:    case SW_ENH_B80x25: case SW_ENH_C80x25:    case SW_ENH_B80x43: case SW_ENH_C80x43:	if (!crtc_vga || video_mode_ptr == NULL)	    return ENXIO;	switch (cmd & 0xff) {	case M_VGA_C80x60: case M_VGA_M80x60:	    if (!(fonts_loaded & FONT_8))		return EINVAL;	    scp->xsize = 80;	    scp->ysize = 60;	    break;	case M_VGA_C80x50: case M_VGA_M80x50:	    if (!(fonts_loaded & FONT_8))		return EINVAL;	    scp->xsize = 80;	    scp->ysize = 50;	    break;	case M_ENH_B80x43: case M_ENH_C80x43:	    if (!(fonts_loaded & FONT_8))		return EINVAL;	    scp->xsize = 80;	    scp->ysize = 43;	    break;	case M_VGA_C80x30: case M_VGA_M80x30:	    scp->xsize = 80;	    scp->ysize = 30;	    break;	default:	    if ((cmd & 0xff) > M_VGA_CG320)		return EINVAL;	    else		scp->xsize = *(video_mode_ptr+((cmd&0xff)*64));		scp->ysize = *(video_mode_ptr+((cmd&0xff)*64)+1)+1;	    break;	}	scp->mode = cmd & 0xff;	scp->status &= ~UNKNOWN_MODE;   /* text mode */	free(scp->scr_buf, M_DEVBUF);	scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short),					 M_DEVBUF, M_WAITOK);	if (scp == cur_console)	    set_mode(scp);	clear_screen(scp);	if (tp->t_winsize.ws_col != scp->xsize	    || tp->t_winsize.ws_row != scp->ysize) {	    tp->t_winsize.ws_col = scp->xsize;	    tp->t_winsize.ws_row = scp->ysize;	    pgsignal(tp->t_pgrp, SIGWINCH, 1);	}	return 0;    /* GRAPHICS MODES */    case SW_BG320:     case SW_BG640:    case SW_CG320:     case SW_CG320_D:   case SW_CG640_E:    case SW_CG640x350: case SW_ENH_CG640:    case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320:	if (!crtc_vga || video_mode_ptr == NULL)	    return ENXIO;	scp->mode = cmd & 0xFF;	scp->status |= UNKNOWN_MODE;    /* graphics mode */	scp->xsize = (*(video_mode_ptr + (scp->mode*64))) * 8;	scp->ysize = (*(video_mode_ptr + (scp->mode*64) + 1) + 1) *		     (*(video_mode_ptr + (scp->mode*64) + 2));	set_mode(scp);	/* clear_graphics();*/	if (tp->t_winsize.ws_xpixel != scp->xsize	    || tp->t_winsize.ws_ypixel != scp->ysize) {	    tp->t_winsize.ws_xpixel = scp->xsize;	    tp->t_winsize.ws_ypixel = scp->ysize;	    pgsignal(tp->t_pgrp, SIGWINCH, 1);	}	return 0;    case VT_SETMODE:    	/* set screen switcher mode */	bcopy(data, &scp->smode, sizeof(struct vt_mode));	if (scp->smode.mode == VT_PROCESS) {	    scp->proc = p;	    scp->pid = scp->proc->p_pid;	}	return 0;    case VT_GETMODE:    	/* get screen switcher mode */	bcopy(&scp->smode, data, sizeof(struct vt_mode));	return 0;    case VT_RELDISP:    	/* screen switcher ioctl */	switch(*data) {	case VT_FALSE:  	/* user refuses to release screen, abort */	    if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {		old_scp->status &= ~SWITCH_WAIT_REL;		switch_in_progress = FALSE;		return 0;	    }	    return EINVAL;	case VT_TRUE:   	/* user has released screen, go on */	    if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {		scp->status &= ~SWITCH_WAIT_REL;		exchange_scr();		if (new_scp->smode.mode == VT_PROCESS) {		    new_scp->status |= SWITCH_WAIT_ACQ;		    psignal(new_scp->proc, new_scp->smode.acqsig);		}		else		    switch_in_progress = FALSE;		return 0;	    }	    return EINVAL;	case VT_ACKACQ: 	/* acquire acknowledged, switch completed */	    if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) {		scp->status &= ~SWITCH_WAIT_ACQ;		switch_in_progress = FALSE;		return 0;	    }	    return EINVAL;	default:	    return EINVAL;	}	/* NOT REACHED */    case VT_OPENQRY:    	/* return free virtual console */	for (i = 0; i < MAXCONS; i++) {	    tp = VIRTUAL_TTY(i);	    if (!(tp->t_state & TS_ISOPEN)) {		*data = i + 1;		return 0;	    }	}	return EINVAL;    case VT_ACTIVATE:   	/* switch to screen *data */	return switch_scr(scp, (*data) - 1);    case VT_WAITACTIVE: 	/* wait for switch to occur */	if (*data > MAXCONS || *data < 0)	    return EINVAL;	if (minor(dev) == (*data) - 1)	    return 0;	if (*data == 0) {	    if (scp == cur_console)		return 0;	}	else	    scp = console[(*data) - 1];	while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH,			     "waitvt", 0)) == ERESTART) ;	return error;    case VT_GETACTIVE:	*data = get_scr_num()+1;	return 0;#ifndef OSKIT    case KDENABIO:      	/* allow io operations */	error = suser(p->p_ucred, &p->p_acflag);	if (error != 0)	    return error;	if (securelevel > 0)	    return EPERM;	fp = (struct trapframe *)p->p_md.md_regs;	fp->tf_eflags |= PSL_IOPL;	return 0;    case KDDISABIO:     	/* disallow io operations (default) */	fp = (struct trapframe *)p->p_md.md_regs;	fp->tf_eflags &= ~PSL_IOPL;	return 0;#endif /* !OSKIT */    case KDSETMODE:     	/* set current mode of this (virtual) console */	switch (*data) {	case KD_TEXT:   	/* switch to TEXT (known) mode */	    /* restore fonts & palette ! */	    if (crtc_vga) {		if (fonts_loaded & FONT_8)		    copy_font(LOAD, FONT_8, font_8);		if (fonts_loaded & FONT_14)		    copy_font(LOAD, FONT_14, font_14);		if (fonts_loaded & FONT_16)		    copy_font(LOAD, FONT_16, font_16);		if (configuration & CHAR_CURSOR)		    set_destructive_cursor(scp, TRUE);		load_palette();	    }	    /* FALL THROUGH */	case KD_TEXT1:  	/* switch to TEXT (known) mode */	    /* no restore fonts & palette */	    scp->status &= ~UNKNOWN_MODE;	    if (crtc_vga && video_mode_ptr)		set_mode(scp);	    clear_screen(scp);	    return 0;	case KD_GRAPHICS:	/* switch to GRAPHICS (unknown) mode */	    scp->status |= UNKNOWN_MODE;	    return 0;	default:	    return EINVAL;	}	/* NOT REACHED */    case KDGETMODE:     	/* get current mode of this (virtual) console */	*data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT;	return 0;    case KDSBORDER:     	/* set border color of this (virtual) console */	if (!crtc_vga)	    return ENXIO;	scp->border = *data;	if (scp == cur_console)	    set_border(scp->border);	return 0;    case KDSKBSTATE:    	/* set keyboard state (locks) */	if (*data >= 0 && *data <= LOCK_KEY_MASK) {	    scp->status &= ~LOCK_KEY_MASK;	    scp->status |= *data;	    if (scp == cur_console)		update_leds(scp->status);	    return 0;	}	return EINVAL;    case KDGKBSTATE:    	/* get keyboard state (locks) */	*data = scp->status & LOCK_KEY_MASK;	return 0;    case KDSETRAD:      	/* set keyboard repeat & delay rates */	if (*data & 0x80)	    return EINVAL;	i = spltty();	kbd_cmd(KB_SETRAD);	kbd_cmd(*data);	splx(i);	return 0;    case KDSKBMODE:     	/* set keyboard mode */	switch (*data) {	case K_RAW: 		/* switch to RAW scancode mode */	    scp->status |= KBD_RAW_MODE;	    return 0;	case K_XLATE:   	/* switch to XLT ascii mode */	    if (scp == cur_console && scp->status == KBD_RAW_MODE)		shfts = ctls = alts = agrs = metas = 0;	    scp->status &= ~KBD_RAW_MODE;	    return 0;	default:	    return EINVAL;	}	/* NOT REACHED */    case KDGKBMODE:     	/* get keyboard mode */	*data = (scp->status & KBD_RAW_MODE) ? K_RAW : K_XLATE;	return 0;    case KDMKTONE:      	/* sound the bell */	if (*(int*)data)	    do_bell(scp, (*(int*)data)&0xffff,		    (((*(int*)data)>>16)&0xffff)*hz/1000);	else	    do_bell(scp, scp->bell_pitch, scp->bell_duration);	return 0;    case KIOCSOUND:     	/* make tone (*data) hz */	if (scp == cur_console) {	    if (*(int*)data) {		int pitch = TIMER_FREQ/(*(int*)data);		/* set command for counter 2, 2 byte write */		if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE))		    return EBUSY;		/* set pitch */		outb(TIMER_CNTR2, pitch);		outb(TIMER_CNTR2, (pitch>>8));		/* enable counter 2 output to speaker */		outb(IO_PPI, inb(IO_PPI) | 3);	    }	    else {		/* disable counter 2 output to speaker */		outb(IO_PPI, inb(IO_PPI) & 0xFC);		release_timer2();	    }	}	return 0;    case KDGKBTYPE:     	/* get keyboard type */	*data = 0;  		/* type not known (yet) */	return 0;

⌨️ 快捷键说明

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