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

📄 tty_io.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
 * Split this up, as gcc can choke on it otherwise.. */int tty_ioctl(struct inode * inode, struct file * file,	      unsigned int cmd, unsigned long arg){	struct tty_struct *tty, *real_tty;	int retval;		tty = (struct tty_struct *)file->private_data;	if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))		return -EINVAL;	real_tty = tty;	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&	    tty->driver.subtype == PTY_TYPE_MASTER)		real_tty = tty->link;	/*	 * Break handling by driver	 */	if (!tty->driver.break_ctl) {		switch(cmd) {		case TIOCSBRK:		case TIOCCBRK:			if (tty->driver.ioctl)				return tty->driver.ioctl(tty, file, cmd, arg);			return -EINVAL;					/* These two ioctl's always return success; even if */		/* the driver doesn't support them. */		case TCSBRK:		case TCSBRKP:			if (!tty->driver.ioctl)				return 0;			retval = tty->driver.ioctl(tty, file, cmd, arg);			if (retval == -ENOIOCTLCMD)				retval = 0;			return retval;		}	}	/*	 * Factor out some common prep work	 */	switch (cmd) {	case TIOCSETD:	case TIOCSBRK:	case TIOCCBRK:	case TCSBRK:	case TCSBRKP:					retval = tty_check_change(tty);		if (retval)			return retval;		if (cmd != TIOCCBRK) {			tty_wait_until_sent(tty, 0);			if (signal_pending(current))				return -EINTR;		}		break;	}	switch (cmd) {		case TIOCSTI:			return tiocsti(tty, (char *)arg);		case TIOCGWINSZ:			return tiocgwinsz(tty, (struct winsize *) arg);		case TIOCSWINSZ:			return tiocswinsz(tty, real_tty, (struct winsize *) arg);		case TIOCCONS:			return tioccons(tty, real_tty);		case FIONBIO:			return fionbio(file, (int *) arg);		case TIOCEXCL:			set_bit(TTY_EXCLUSIVE, &tty->flags);			return 0;		case TIOCNXCL:			clear_bit(TTY_EXCLUSIVE, &tty->flags);			return 0;		case TIOCNOTTY:			if (current->tty != tty)				return -ENOTTY;			if (current->leader)				disassociate_ctty(0);			current->tty = NULL;			return 0;		case TIOCSCTTY:			return tiocsctty(tty, arg);		case TIOCGPGRP:			return tiocgpgrp(tty, real_tty, (pid_t *) arg);		case TIOCSPGRP:			return tiocspgrp(tty, real_tty, (pid_t *) arg);		case TIOCGSID:			return tiocgsid(tty, real_tty, (pid_t *) arg);		case TIOCGETD:			return put_user(tty->ldisc.num, (int *) arg);		case TIOCSETD:			return tiocsetd(tty, (int *) arg);#ifdef CONFIG_VT		case TIOCLINUX:			return tioclinux(tty, arg);#endif		case TIOCTTYGSTRUCT:			return tiocttygstruct(tty, (struct tty_struct *) arg);		/*		 * Break handling		 */		case TIOCSBRK:	/* Turn break on, unconditionally */			tty->driver.break_ctl(tty, -1);			return 0;					case TIOCCBRK:	/* Turn break off, unconditionally */			tty->driver.break_ctl(tty, 0);			return 0;		case TCSBRK:   /* SVID version: non-zero arg --> no break */			/*			 * XXX is the above comment correct, or the			 * code below correct?  Is this ioctl used at			 * all by anyone?			 */			if (!arg)				return send_break(tty, HZ/4);			return 0;		case TCSBRKP:	/* support for POSIX tcsendbreak() */				return send_break(tty, arg ? arg*(HZ/10) : HZ/4);	}	if (tty->driver.ioctl) {		int retval = (tty->driver.ioctl)(tty, file, cmd, arg);		if (retval != -ENOIOCTLCMD)			return retval;	}	if (tty->ldisc.ioctl) {		int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg);		if (retval != -ENOIOCTLCMD)			return retval;	}	return -EINVAL;}/* * This implements the "Secure Attention Key" ---  the idea is to * prevent trojan horses by killing all processes associated with this * tty when the user hits the "Secure Attention Key".  Required for * super-paranoid applications --- see the Orange Book for more details. *  * This code could be nicer; ideally it should send a HUP, wait a few * seconds, then send a INT, and then a KILL signal.  But you then * have to coordinate with the init process, since all processes associated * with the current tty must be dead before the new getty is allowed * to spawn. */void do_SAK( struct tty_struct *tty){#ifdef TTY_SOFT_SAK	tty_hangup(tty);#else	struct task_struct *p;	int session;	int		i;	struct file	*filp;		if (!tty)		return;	session  = tty->session;	if (tty->ldisc.flush_buffer)		tty->ldisc.flush_buffer(tty);	if (tty->driver.flush_buffer)		tty->driver.flush_buffer(tty);	read_lock(&tasklist_lock);	for_each_task(p) {		if ((p->tty == tty) ||		    ((session > 0) && (p->session == session)))			send_sig(SIGKILL, p, 1);		else if (p->files) {			for (i=0; i < p->files->max_fds; i++) {				filp = fcheck_task(p, i);				if (filp && (filp->f_op == &tty_fops) &&				    (filp->private_data == tty)) {					send_sig(SIGKILL, p, 1);					break;				}			}		}	}	read_unlock(&tasklist_lock);#endif}/* * This routine is called out of the software interrupt to flush data * from the flip buffer to the line discipline. */static void flush_to_ldisc(void *private_){	struct tty_struct *tty = (struct tty_struct *) private_;	unsigned char	*cp;	char		*fp;	int		count;	unsigned long flags;	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {		queue_task(&tty->flip.tqueue, &tq_timer);		return;	}	if (tty->flip.buf_num) {		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;		fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;		tty->flip.buf_num = 0;		save_flags(flags); cli();		tty->flip.char_buf_ptr = tty->flip.char_buf;		tty->flip.flag_buf_ptr = tty->flip.flag_buf;	} else {		cp = tty->flip.char_buf;		fp = tty->flip.flag_buf;		tty->flip.buf_num = 1;		save_flags(flags); cli();		tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;		tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;	}	count = tty->flip.count;	tty->flip.count = 0;	restore_flags(flags);		tty->ldisc.receive_buf(tty, cp, fp, count);}/* * Routine which returns the baud rate of the tty * * Note that the baud_table needs to be kept in sync with the * include/asm/termbits.h file. */static int baud_table[] = {	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,	9600, 19200, 38400, 57600, 115200, 230400, 460800,#ifdef __sparc__	76800, 153600, 307200, 614400, 921600#else	500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,	2500000, 3000000, 3500000, 4000000#endif};static int n_baud_table = sizeof(baud_table)/sizeof(int);int tty_get_baud_rate(struct tty_struct *tty){	unsigned int cflag, i;	cflag = tty->termios->c_cflag;	i = cflag & CBAUD;	if (i & CBAUDEX) {		i &= ~CBAUDEX;		if (i < 1 || i+15 >= n_baud_table) 			tty->termios->c_cflag &= ~CBAUDEX;		else			i += 15;	}	if (i==15 && tty->alt_speed) {		if (!tty->warned) {			printk("Use of setserial/setrocket to set SPD_* flags is deprecated\n");			tty->warned = 1;		}		return(tty->alt_speed);	}		return baud_table[i];}void tty_flip_buffer_push(struct tty_struct *tty){	if (tty->low_latency)		flush_to_ldisc((void *) tty);	else		queue_task(&tty->flip.tqueue, &tq_timer);}/* * This subroutine initializes a tty structure. */static void initialize_tty_struct(struct tty_struct *tty){	memset(tty, 0, sizeof(struct tty_struct));	tty->magic = TTY_MAGIC;	tty->ldisc = ldiscs[N_TTY];	tty->pgrp = -1;	tty->flip.char_buf_ptr = tty->flip.char_buf;	tty->flip.flag_buf_ptr = tty->flip.flag_buf;	tty->flip.tqueue.routine = flush_to_ldisc;	tty->flip.tqueue.data = tty;	tty->flip.pty_sem = MUTEX;	tty->tq_hangup.routine = do_tty_hangup;	tty->tq_hangup.data = tty;	sema_init(&tty->atomic_read, 1);}/* * The default put_char routine if the driver did not define one. */void tty_default_put_char(struct tty_struct *tty, unsigned char ch){	tty->driver.write(tty, 0, &ch, 1);}/* * Called by a tty driver to register itself. */int tty_register_driver(struct tty_driver *driver){	int error;	if (driver->flags & TTY_DRIVER_INSTALLED)		return 0;	error = register_chrdev(driver->major, driver->name, &tty_fops);	if (error < 0)		return error;	else if(driver->major == 0)		driver->major = error;	if (!driver->put_char)		driver->put_char = tty_default_put_char;		driver->prev = 0;	driver->next = tty_drivers;	if (tty_drivers) tty_drivers->prev = driver;	tty_drivers = driver;		proc_tty_register_driver(driver);	return error;}/* * Called by a tty driver to unregister itself. */int tty_unregister_driver(struct tty_driver *driver){	int	retval;	struct tty_driver *p;	int	found = 0;	const char *othername = NULL;		if (*driver->refcount)		return -EBUSY;	for (p = tty_drivers; p; p = p->next) {		if (p == driver)			found++;		else if (p->major == driver->major)			othername = p->name;	}		if (!found)		return -ENOENT;	if (othername == NULL) {		retval = unregister_chrdev(driver->major, driver->name);		if (retval)			return retval;	} else		register_chrdev(driver->major, othername, &tty_fops);	if (driver->prev)		driver->prev->next = driver->next;	else		tty_drivers = driver->next;		if (driver->next)		driver->next->prev = driver->prev;	proc_tty_unregister_driver(driver);	return 0;}/* * Initialize the console device. This is called *early*, so * we can't necessarily depend on lots of kernel help here. * Just do some early initializations, and do the complex setup * later. */long __init console_init(long kmem_start, long kmem_end){	/* Setup the default TTY line discipline. */	memset(ldiscs, 0, sizeof(ldiscs));	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);	/*	 * Set up the standard termios.  Individual tty drivers may 	 * deviate from this; this is used as a template.	 */	memset(&tty_std_termios, 0, sizeof(struct termios));	memcpy(tty_std_termios.c_cc, INIT_C_CC, NCCS);	tty_std_termios.c_iflag = ICRNL | IXON;	tty_std_termios.c_oflag = OPOST | ONLCR;	tty_std_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL;	tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |		ECHOCTL | ECHOKE | IEXTEN;	/*	 * set up the console device so that later boot sequences can 	 * inform about problems etc..	 */#ifdef CONFIG_VT	kmem_start = con_init(kmem_start);#endif#ifdef CONFIG_SERIAL_CONSOLE#ifdef CONFIG_8xx	kmem_start = console_8xx_init(kmem_start, kmem_end);#else 		kmem_start = serial_console_init(kmem_start, kmem_end);#endif /* CONFIG_8xx */#endif	return kmem_start;}static struct tty_driver dev_tty_driver, dev_syscons_driver;#ifdef CONFIG_UNIX98_PTYSstatic struct tty_driver dev_ptmx_driver;#endif#ifdef CONFIG_VTstatic struct tty_driver dev_console_driver;#endif/* * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */__initfunc(int tty_init(void)){	if (sizeof(struct tty_struct) > PAGE_SIZE)		panic("size of tty structure > PAGE_SIZE!");	/*	 * dev_tty_driver and dev_console_driver are actually magic	 * devices which get redirected at open time.  Nevertheless,	 * we register them so that register_chrdev is called	 * appropriately.	 */	memset(&dev_tty_driver, 0, sizeof(struct tty_driver));	dev_tty_driver.magic = TTY_DRIVER_MAGIC;	dev_tty_driver.driver_name = "/dev/tty";	dev_tty_driver.name = dev_tty_driver.driver_name + 5;	dev_tty_driver.name_base = 0;	dev_tty_driver.major = TTYAUX_MAJOR;	dev_tty_driver.minor_start = 0;	dev_tty_driver.num = 1;	dev_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;	dev_tty_driver.subtype = SYSTEM_TYPE_TTY;		if (tty_register_driver(&dev_tty_driver))		panic("Couldn't register /dev/tty driver\n");	dev_syscons_driver = dev_tty_driver;	dev_syscons_driver.driver_name = "/dev/console";	dev_syscons_driver.name = dev_syscons_driver.driver_name + 5;	dev_syscons_driver.major = TTYAUX_MAJOR;	dev_syscons_driver.minor_start = 1;	dev_syscons_driver.type = TTY_DRIVER_TYPE_SYSTEM;	dev_syscons_driver.subtype = SYSTEM_TYPE_SYSCONS;	if (tty_register_driver(&dev_syscons_driver))		panic("Couldn't register /dev/console driver\n");#ifdef CONFIG_UNIX98_PTYS	dev_ptmx_driver = dev_tty_driver;	dev_ptmx_driver.driver_name = "/dev/ptmx";	dev_ptmx_driver.name = dev_ptmx_driver.driver_name + 5;	dev_ptmx_driver.major= MAJOR(PTMX_DEV);	dev_ptmx_driver.minor_start = MINOR(PTMX_DEV);	dev_ptmx_driver.type = TTY_DRIVER_TYPE_SYSTEM;	dev_ptmx_driver.subtype = SYSTEM_TYPE_SYSPTMX;	if (tty_register_driver(&dev_ptmx_driver))		panic("Couldn't register /dev/ptmx driver\n");#endif	#ifdef CONFIG_VT	dev_console_driver = dev_tty_driver;	dev_console_driver.driver_name = "/dev/tty0";	dev_console_driver.name = dev_console_driver.driver_name + 5;	dev_console_driver.major = TTY_MAJOR;	dev_console_driver.type = TTY_DRIVER_TYPE_SYSTEM;	dev_console_driver.subtype = SYSTEM_TYPE_CONSOLE;	if (tty_register_driver(&dev_console_driver))		panic("Couldn't register /dev/tty0 driver\n");#if !defined(CONFIG_STANDALONE) /* ebony */	kbd_init();#endif#endif#ifdef CONFIG_ESPSERIAL  /* init ESP before rs, so rs doesn't see the port */	espserial_init();#endif#ifdef CONFIG_SERIAL	rs_init();#endif#ifdef CONFIG_MAC_SERIAL	macserial_init();#endif#ifdef CONFIG_ROCKETPORT	rp_init();#endif#ifdef CONFIG_MVME16x	serial167_init();#endif#ifdef CONFIG_CYCLADES	cy_init();#endif#ifdef CONFIG_STALLION	stl_init();#endif#ifdef CONFIG_ISTALLION	stli_init();#endif#ifdef CONFIG_DIGI	pcxe_init();#endif#ifdef CONFIG_DIGIEPCA	pc_init();#endif#ifdef CONFIG_RISCOM8	riscom8_init();#endif#ifdef CONFIG_SPECIALIX	specialix_init();#endif#ifdef CONFIG_8xx        rs_8xx_init();#endif /* CONFIG_8xx */	pty_init();#ifdef CONFIG_VT	vcs_init();#endif	return 0;}

⌨️ 快捷键说明

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