⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vt.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/arch/arm/drivers/char/vt.c * * VT routines * * Changelog: *  05-Sep-1996	RMK	Fixed race condition between VT switch & initialisation *  08-Sep-1996	RMK	Adapted Brad Pepers (ramparts@agt.net) console buffering code *			(vt_put_char & vt_flush_chars). *  02-Sep-1997 RMK	Added in VT switch disable */#include <linux/config.h>#include <linux/sched.h>#include <linux/tty.h>#include <linux/kd.h>#include <linux/errno.h>#include <linux/malloc.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/major.h>#include <asm/segment.h>#include <asm/hardware.h>#include "kbd_kern.h"#include "vt_kern.h"#define CON_XMIT_SIZE	2048#ifndef MIN#define MIN(a,b)        ((a) < (b) ? (a) : (b))#endif/* * VCD functions */extern void		vcd_blankscreen (int nopowersave);extern void		vcd_disallocate (struct vt *);extern int		vcd_init (struct vt *, int kmallocok, unsigned long *kmem);extern int		vcd_ioctl (struct vt *, int cmd, unsigned long arg);extern unsigned long	vcd_pre_init (unsigned long kmem, struct vt *);extern int		vcd_resize (int rows, int columns);extern void		vcd_restorestate (const struct vt *);extern void		vcd_savestate (const struct vt *, int blanked);extern void		vcd_unblankscreen (void);extern int		vcd_write (const struct vt *, int from_user, const unsigned char *buf, int count);extern void		vcd_setup_graphics (const struct vt *);/* * Console functions */extern void con_reset_palette (const struct vt *vt);extern void con_set_palette (const struct vt *vt);extern int con_init (void);static int vt_refcount;int do_poke_blanked_console;static struct tty_driver vt_driver;static struct tty_struct *vt_table[MAX_NR_CONSOLES];static struct termios *vt_termios[MAX_NR_CONSOLES];static struct termios *vt_termios_locked[MAX_NR_CONSOLES];struct vt_data vtdata;struct vt vt_con_data[MAX_NR_CONSOLES];extern void vt_do_blankscreen (int nopowersave);extern void vt_do_unblankscreen (void);/* set this to the sound driver's wave output trigger */void (*mksound_hook)(unsigned int freq, unsigned int vol, unsigned int duration);/* * last_console is the last used console */struct vt *last_console;struct vt *want_console;static char vt_dont_switch = 0;/* * Sometimes we want to wait until a particular VT has been activated. We * do it in a very simple manner. Everybody waits on a single queue and * get woken up at once. Those that are satisfied go on with their business, * while those not ready go back to sleep. Seems overkill to add a wait * to each vt just for this - usually this does nothing! */static struct wait_queue *vt_activate_queue = NULL;/* * Sleeps until a vt is activated, or the task is interrupted. Returns * 0 if activation, -1 if interrupted. */static int vt_waitonactivate (void){    interruptible_sleep_on (&vt_activate_queue);    return (current->signal & ~current->blocked) ? -1 : 0;}#define vt_wake_waitactive() wake_up(&vt_activate_queue)void vt_reset (const struct vt *vt){    vt->kbd->kbdmode		= VC_XLATE;    vt->vtd->vc_mode		= KD_TEXT;    vt->vtd->vt_mode.mode	= VT_AUTO;    vt->vtd->vt_mode.waitv	= 0;    vt->vtd->vt_mode.relsig	= 0;    vt->vtd->vt_mode.acqsig	= 0;    vt->vtd->vt_mode.frsig	= 0;    vt->vtd->vt_pid		= -1;    vt->vtd->vt_newvt		= NULL;    con_reset_palette (vt);}static int vt_allocate (struct vt *vt){    if (!vt_allocated(vt)) {	void *data, *p;	int r;	data = kmalloc (sizeof (*vt->vcd) +			sizeof (*vt->kbd) +			sizeof (*vt->vtd) + CON_XMIT_SIZE, GFP_KERNEL);	if (!data)	    return -ENOMEM;	vt->vcd = data;  p = ((struct con_struct *)data + 1);	vt->kbd = p;     p = ((struct kbd_struct *)p + 1);	vt->vtd = p;	 p = ((struct vt_struct *)p + 1);	vt->vtd->xmit_buf = p;	if ((r = kbd_struct_init (vt, 1)) < 0) {	    vt->vcd = NULL;	    vt->kbd = NULL;	    vt->vtd = NULL;	    kfree (data);	    return r;	}	if ((r = vcd_init (vt, 1, NULL)) < 0) {	    vt->vcd = NULL;	    vt->kbd = NULL;	    vt->vtd = NULL;	    kfree (data);	    return r;	}	vt_reset (vt);	vt->vtd->xmitting = vt->vtd->xmit_cnt =	vt->vtd->xmit_out = vt->vtd->xmit_in = 0;	vt->allocinit = 1;    }    return 0;}static int vt_disallocate (struct vt *vt){    if (vt_allocated (vt)) {	void *data = vt->vcd;	vt->allocinit = 0;	vcd_disallocate (vt);	vt->vcd = NULL;	vt->kbd = NULL;	vt->vtd = NULL;	kfree (data);    }    return 0;}void vt_updatescreen (const struct vt *newvt){    static int lock = 0;    if (newvt == vtdata.fgconsole || lock)	return;    if (!vt_allocated (newvt)) {	printk ("updatescreen: tty %d not allocated ??\n", newvt->num);	return;    }    lock = 1;    vcd_savestate (vtdata.fgconsole, vtdata.blanked != NULL);    vtdata.fgconsole = (struct vt *)newvt;    vcd_restorestate (vtdata.fgconsole);    compute_shiftstate ();    lock = 0;}/* * Performs the back end of a vt switch */void vt_completechangeconsole (const struct vt *new_console){    unsigned char old_vt_mode;    struct vt *old_vt = vtdata.fgconsole;    if (new_console == old_vt || (vt_dont_switch))	return;    if (!vt_allocated (new_console))	return;    last_console = old_vt;    /*     * If we're switching, we could be going from KD_GRAPHICS to     * KD_TEXT mode or vice versa, which means we need to blank or     * unblank the screen later.     */    old_vt_mode = old_vt->vtd->vc_mode;    vt_updatescreen (new_console);    /*     * If this new console is under process control, send it a signal     * telling it that it has acquired. Also check if it has died and     * clean up (similar to logic employed in vt_changeconsole())     */    if (new_console->vtd->vt_mode.mode == VT_PROCESS) {	/*	 * Send the signal as privileged - kill_proc() will	 * tell us if the process has gone or something else	 * is awry	 */	if (kill_proc(new_console->vtd->vt_pid,			      new_console->vtd->vt_mode.acqsig,			      1) != 0) {	    /*	     * The controlling process has died, so we revert back to	     * normal operation. In this case, we'll also change back	     * to KD_TEXT mode. I'm not sure if this is strictly correct	     * but it saves the agony when the X server dies and the screen	     * remains blanked due to KD_GRAPHICS! It would be nice to do	     * this outside of VT_PROCESS but there is no single process	     * to account for and tracking tty count may be undesirable.	     */	    vt_reset (new_console);	}    }    /*     * We do this here because the controlling process above may have     * gone, and so there is now a new vc_mode     */    if (old_vt_mode != new_console->vtd->vc_mode) {	if (new_console->vtd->vc_mode == KD_TEXT)	    vt_do_unblankscreen ();	else {	    vt_do_blankscreen (1);	    vcd_setup_graphics (new_console);	}    }    /* Set the colour palette for this VT */    if (new_console->vtd->vc_mode == KD_TEXT)	con_set_palette (new_console);	    /*     * Wake anyone waiting for their VT to activate     */    vt_wake_waitactive();    return;}/* * Performs the front-end of a vt switch */void vt_changeconsole (struct vt *new_console){    struct vt *old_vt = vtdata.fgconsole;    if (new_console == old_vt || (vt_dont_switch))	return;    if (!vt_allocated (new_console))	return;    /*     * If this vt is in process mode, then we need to handshake with     * that process before switching. Essentially, we store where that     * vt wants to switch to and wait for it to tell us when it's done     * (via VT_RELDISP ioctl).     *     * We also check to see if the controlling process still exists.     * If it doesn't, we reset this vt to auto mode and continue.     * This is a cheap way to track process control. The worst thing     * that can happen is: we send a signal to a process, it dies, and     * the switch gets "lost" waiting for a response; hopefully, the     * user will try again, we'll detect the process is gone (unless     * the user waits just the right amount of time :-) and revert the     * vt to auto control.     */    if (old_vt->vtd->vt_mode.mode == VT_PROCESS) {	/*	 * Send the signal as privileged - kill_proc() will	 * tell us if the process has gone or something else	 * is awry	 */	if (kill_proc(old_vt->vtd->vt_pid, old_vt->vtd->vt_mode.relsig, 1) == 0) {	    /*	     * It worked. Mark the vt to switch to and	     * return. The process needs to send us a	     * VT_RELDISP ioctl to complete the switch.	     */	    old_vt->vtd->vt_newvt = new_console;	    return;	}	/*	 * The controlling process has died, so we revert back to	 * normal operation. In this case, we'll also change back	 * to KD_TEXT mode. I'm not sure if this is strictly correct	 * but it saves the agony when the X server dies and the screen	 * remains blanked due to KD_GRAPHICS! It would be nice to do	 * this outside of VT_PROCESS but there is no single process	 * to account for and tracking tty count may be undesirable.	 */	vt_reset (old_vt);	/*	 * Fall through to normal (VT_AUTO) handling of the switch...	 */    }    /*     * Ignore all switches in KD_GRAPHICS+VT_AUTO mode     */    if (old_vt->vtd->vc_mode == KD_GRAPHICS)	return;    vt_completechangeconsole (new_console);}/* * If a vt is under process control, the kernel will not switch to it * immediately, but postpone the operation until the process calls this * ioctl, allowing the switch to complete. * * According to the X sources this is the behavior: *      0:      pending switch-from not OK *      1:      pending switch-from OK *      2:      completed switch-to OK */static inline int vt_reldisp (const struct vt *old_vt, int arg){    int i;    if (old_vt->vtd->vt_mode.mode != VT_PROCESS)	return -EINVAL;    if (old_vt->vtd->vt_newvt) {	/*	 * Switching-from response	 */	if (arg == 0)	    /*	     * Switch disallowed, so forget we were trying	     * to do it.	     */	    old_vt->vtd->vt_newvt = NULL;	else {	    /*	     * The current vt has been released, so complete the	     * switch.	     */	    struct vt *new_vt = old_vt->vtd->vt_newvt;	    old_vt->vtd->vt_newvt = NULL;	    i = vt_allocate (new_vt);	    if (i)		return i;	    vt_completechangeconsole (new_vt);	}    } else {	/*	 * Switched-to response	 */	if (arg != VT_ACKACQ)	    return -EINVAL;    }    return 0;}/* * Set the mode of a VT. */static inline int vt_kdsetmode (const struct vt *vt, int mode){    /*     * Currently, setting the mode from KD_TEXT to KD_GRAPHICS     * doesn't do a whole lot. I'm not sure if it should do any     * restoration of modes or what...     */    switch (mode) {    case KD_TEXT0:    case KD_TEXT1:	mode = KD_TEXT;    case KD_GRAPHICS:    case KD_TEXT:	break;    default:	return -EINVAL;    }    if (vt->vtd->vc_mode == mode)	return 0;    vt->vtd->vc_mode = mode;    if (vt != vtdata.fgconsole)	return 0;    /*     * explicitly blank/unblank the screen if switching modes     */    if (mode == KD_TEXT) {	vt_do_unblankscreen ();        vcd_restorestate (vt);    } else {	vt_do_blankscreen (1);	vcd_setup_graphics (vt);    }    return 0;}static inline int vt_setmode (const struct vt *vt, struct vt_mode *vtmode){    if (vtmode->mode != VT_AUTO && vtmode->mode != VT_PROCESS)	return -EINVAL;    vt->vtd->vt_mode = *vtmode;    vt->vtd->vt_mode.frsig = 0;    vt->vtd->vt_pid = current->pid;    vt->vtd->vt_newvt = NULL;    return 0;}void vt_mksound (unsigned int freq, unsigned int vol, unsigned int ticks){    if (mksound_hook)        mksound_hook (freq, vol, ticks);}/* * Deallocate memory associated to VT (but leave VT1) */int vt_deallocate (int arg){    int i;    if (arg == 0) {	/*	 * deallocate all unused consoles, but leave 0	 */	for (i = 1; i < MAX_NR_CONSOLES; i++)	    if (!VT_BUSY (i))		vt_disallocate (vt_con_data + i);    } else {	arg -= 1;	if (VT_BUSY (arg))	    return -EBUSY;	if (arg)	    vt_disallocate (vt_con_data + arg);    }    return 0;}int vt_resize (int columns, int rows){    return vcd_resize (rows, columns);}void vt_pokeblankedconsole (void){    timer_active &= ~(1 << BLANK_TIMER);    if (vtdata.fgconsole->vtd->vc_mode == KD_GRAPHICS)	return;    if (vtdata.blanked) {	timer_table[BLANK_TIMER].expires = 0;	timer_active |= 1 << BLANK_TIMER;    } else if (vtdata.screen.blankinterval) {	timer_table[BLANK_TIMER].expires = jiffies + vtdata.screen.blankinterval;	timer_active |= 1 << BLANK_TIMER;    }}static void vt_blankscreen (void);void vt_do_unblankscreen (void){    if (!vtdata.blanked)	return;    if (!vt_allocated (vtdata.fgconsole)) {	/* impossible... */	printk ("unblank_screen: tty %d not allocated ??\n", vtdata.fgconsole->num);	return;    }    timer_table[BLANK_TIMER].fn = vt_blankscreen;    if (vtdata.screen.blankinterval) {	timer_table[BLANK_TIMER].expires = jiffies + vtdata.screen.blankinterval;	timer_active |= 1 << BLANK_TIMER;    }    vtdata.blanked = NULL;    vcd_unblankscreen ();}/* * for panic.c */void do_unblank_screen (void){    vt_do_unblankscreen ();}void vt_do_blankscreen (int nopowersave){    if (vtdata.blanked)	return;    timer_active &= ~(1 << BLANK_TIMER);    timer_table[BLANK_TIMER].fn = do_unblank_screen;    vtdata.blanked = vtdata.fgconsole;    vcd_blankscreen (nopowersave);}static void vt_blankscreen (void){    vt_do_blankscreen (0);}static int vt_open (struct tty_struct *tty, struct file *filp){    struct vt *vt;    unsigned int idx;    int i;    idx = MINOR(tty->device) - tty->driver.minor_start;

⌨️ 快捷键说明

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