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

📄 vacserial.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif	if (retval)		return retval;	info->flags |= ASYNC_NORMAL_ACTIVE;	return 0;}static int get_async_struct(int line, struct async_struct **ret_info){	struct async_struct *info;	struct serial_state *sstate;	sstate = rs_table + line;	sstate->count++;	if (sstate->info) {		*ret_info = sstate->info;		return 0;	}	info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);	if (!info) {		sstate->count--;		return -ENOMEM;	}	memset(info, 0, sizeof(struct async_struct));	init_waitqueue_head(&info->open_wait);	init_waitqueue_head(&info->close_wait);	init_waitqueue_head(&info->delta_msr_wait);	info->magic = SERIAL_MAGIC;	info->port = sstate->port;	info->flags = sstate->flags;	info->xmit_fifo_size = sstate->xmit_fifo_size;	info->line = line;	info->tqueue.routine = do_softint;	info->tqueue.data = info;	info->state = sstate;	if (sstate->info) {		kfree(info);		*ret_info = sstate->info;		return 0;	}	*ret_info = sstate->info = info;	return 0;}/* * This routine is called whenever a serial port is opened.  It * enables interrupts for a serial port, linking in its async structure into * the IRQ chain.   It also performs the serial-specific * initialization for the tty structure. */static int rs_open(struct tty_struct *tty, struct file * filp){	struct async_struct	*info;	int 			retval, line;	unsigned long		page;	MOD_INC_USE_COUNT; 	line = MINOR(tty->device) - tty->driver.minor_start;	if ((line < 0) || (line >= NR_PORTS)) {		MOD_DEC_USE_COUNT; 		return -ENODEV;	}	retval = get_async_struct(line, &info);	if (retval) {		MOD_DEC_USE_COUNT;		return retval;	}        tty->driver_data = info;        info->tty = tty;	if (serial_paranoia_check(info, tty->device, "rs_open")) {	        /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ 		return -ENODEV;	}#ifdef SERIAL_DEBUG_OPEN	baget_printk("rs_open %s%d, count = %d\n", 		     tty->driver.name, info->line,		     info->state->count);#endif	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;	if (!tmp_buf) {		page = get_free_page(GFP_KERNEL);		if (!page) {			/* MOD_DEC_USE_COUNT; "info->tty" will cause this */			return -ENOMEM;		}		if (tmp_buf)			free_page(page);		else			tmp_buf = (unsigned char *) page;	}	/*	 * If the port is the middle of closing, bail out now	 */	if (tty_hung_up_p(filp) ||	    (info->flags & ASYNC_CLOSING)) {		if (info->flags & ASYNC_CLOSING)			interruptible_sleep_on(&info->close_wait);		/* MOD_DEC_USE_COUNT; "info->tty" will cause this */#ifdef SERIAL_DO_RESTART		return ((info->flags & ASYNC_HUP_NOTIFY) ?			-EAGAIN : -ERESTARTSYS);#else		return -EAGAIN;#endif	}	/*	 * Start up serial port	 */	retval = startup(info);	if (retval) {		/* MOD_DEC_USE_COUNT; "info->tty" will cause this */		return retval;	}	retval = block_til_ready(tty, filp, info);	if (retval) {		 /* MOD_DEC_USE_COUNT; "info->tty" will cause this */#ifdef SERIAL_DEBUG_OPEN		 baget_printk("rs_open returning after block_til_ready "			      "with %d\n",			      retval);#endif		 return retval;	}	if ((info->state->count == 1) &&	    (info->flags & ASYNC_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = info->state->normal_termios;		else 			*tty->termios = info->state->callout_termios;		change_speed(info);	}#ifdef CONFIG_SERIAL_CONSOLE	if (sercons.cflag && sercons.index == line) {		tty->termios->c_cflag = sercons.cflag;		sercons.cflag = 0;		change_speed(info);	}#endif	info->session = current->session;	info->pgrp = current->pgrp;#ifdef SERIAL_DEBUG_OPEN	baget_printk("rs_open ttys%d successful...", info->line);#endif	return 0;}/* * /proc fs routines.... */static inline int line_info(char *buf, struct serial_state *state){	struct async_struct *info = state->info, scr_info;	int	ret;	ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",		      state->line, uart_config[state->type].name, 		      state->port, state->irq);	if (!state->port || (state->type == PORT_UNKNOWN)) {		ret += sprintf(buf+ret, "\n");		return ret;	}	/*	 * Figure out the current RS-232 lines	 */	if (!info) {		info = &scr_info;	/* This is just for serial_{in,out} */		info->magic = SERIAL_MAGIC;		info->port = state->port;		info->flags = state->flags;		info->quot = 0;		info->tty = 0;	}		if (info->quot) {		ret += sprintf(buf+ret, " baud:%d",			       state->baud_base / info->quot);	}	ret += sprintf(buf+ret, " tx:%d rx:%d",		      state->icount.tx, state->icount.rx);	if (state->icount.frame)		ret += sprintf(buf+ret, " fe:%d", state->icount.frame);		if (state->icount.parity)		ret += sprintf(buf+ret, " pe:%d", state->icount.parity);		if (state->icount.brk)		ret += sprintf(buf+ret, " brk:%d", state->icount.brk);		if (state->icount.overrun)		ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);	return ret;}int rs_read_proc(char *page, char **start, off_t off, int count,		 int *eof, void *data){	int i, len = 0, l;	off_t	begin = 0;	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);	for (i = 0; i < NR_PORTS && len < 4000; i++) {                l = line_info(page + len, &rs_table[i]);                len += l; 		if (len+begin > off+count)			goto done;		if (len+begin < off) {			begin += len;			len = 0;		}	}	*eof = 1;done:	if (off >= len+begin)		return 0;	*start = page + (off-begin);	return ((count < begin+len-off) ? count : begin+len-off);}/* * --------------------------------------------------------------------- * rs_init() and friends * * rs_init() is called at boot-time to initialize the serial driver. * --------------------------------------------------------------------- *//* * This routine prints out the appropriate serial driver version * number, and identifies which options were configured into this * driver. */static _INLINE_ void show_serial_version(void){ 	printk(KERN_INFO "%s version %s with", serial_name, serial_version);#ifdef CONFIG_SERIAL_SHARE_IRQ	printk(" SHARE_IRQ");#endif#define SERIAL_OPT#ifdef CONFIG_SERIAL_DETECT_IRQ	printk(" DETECT_IRQ");#endif#ifdef SERIAL_OPT	printk(" enabled\n");#else	printk(" no serial options enabled\n");#endif#undef SERIAL_OPT}/* * This routine is called by rs_init() to initialize a specific serial * port.  It determines what type of UART chip this serial port is * using: 8250, 16450, 16550, 16550A.  The important question is * whether or not this UART is a 16550A or not, since this will * determine whether or not we can use its FIFO features or not. *//* *  Functionality of this function is reduced: we already know we have a VAC, *  but still need to perform some important actions (see code :-). */static void autoconfig(struct serial_state * state){	struct async_struct *info, scr_info; 	unsigned long flags;	/* Setting up important parameters */	state->type = VAC_UART_TYPE;	state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size;	info = &scr_info;       /* This is just for serial_{in,out} */   	info->magic = SERIAL_MAGIC;        info->port  = state->port;        info->flags = state->flags;        save_flags(flags); cli();	/* + Flush VAC input fifo */         (void)serial_in(info, VAC_UART_RX);        (void)serial_in(info, VAC_UART_RX);        (void)serial_in(info, VAC_UART_RX);        (void)serial_in(info, VAC_UART_RX);	/* Disable interrupts */        serial_outp(info, VAC_UART_INT_MASK, 0);        restore_flags(flags);}int register_serial(struct serial_struct *req);void unregister_serial(int line);EXPORT_SYMBOL(register_serial);EXPORT_SYMBOL(unregister_serial);/* *  Important function for VAC UART check and reanimation. */static void rs_timer(unsigned long dummy){        static unsigned long last_strobe = 0;        struct async_struct *info;        unsigned int    i;        unsigned long flags;        if ((jiffies - last_strobe) >= RS_STROBE_TIME) {                for (i=1; i < NR_IRQS; i++) {                        info = IRQ_ports[i];                        if (!info)                                continue;                        save_flags(flags); cli();#ifdef CONFIG_SERIAL_SHARE_IRQ                        if (info->next_port) {                                do {                                        serial_out(info, VAC_UART_INT_MASK, 0);                                        info->IER |= VAC_UART_INT_TX_EMPTY;                                        serial_out(info, VAC_UART_INT_MASK, 						   info->IER);                                        info = info->next_port;                                } while (info);				rs_interrupt(i, NULL, NULL);                        } else#endif /* CONFIG_SERIAL_SHARE_IRQ */                                rs_interrupt_single(i, NULL, NULL);                        restore_flags(flags);                }        }        last_strobe = jiffies;        mod_timer(&vacs_timer, jiffies + RS_STROBE_TIME);	/*	 *  It looks this code for case we share IRQ with console...	 */        if (IRQ_ports[0]) {                save_flags(flags); cli();#ifdef CONFIG_SERIAL_SHARE_IRQ                rs_interrupt(0, NULL, NULL);#else                rs_interrupt_single(0, NULL, NULL);#endif                restore_flags(flags);                mod_timer(&vacs_timer, jiffies + IRQ_timeout[0] - 2);        }} /* * The serial driver boot-time initialization code! */int __init rs_init(void){	int i;	struct serial_state * state;	extern void atomwide_serial_init (void);	extern void dualsp_serial_init (void);#ifdef CONFIG_ATOMWIDE_SERIAL	atomwide_serial_init ();#endif#ifdef CONFIG_DUALSP_SERIAL	dualsp_serial_init ();#endif	init_bh(SERIAL_BH, do_serial_bh);	init_timer(&vacs_timer);	vacs_timer.function = rs_timer;	vacs_timer.expires = 0;	for (i = 0; i < NR_IRQS; i++) {		IRQ_ports[i] = 0;		IRQ_timeout[i] = 0;	}/* *  It is not a good idea to share interrupts with console, *  but it looks we cannot avoid it. */#if 0 #ifdef CONFIG_SERIAL_CONSOLE	/*	 *	The interrupt of the serial console port	 *	can't be shared.	 */	if (sercons.flags & CON_CONSDEV) {		for(i = 0; i < NR_PORTS; i++)			if (i != sercons.index &&			    rs_table[i].irq == rs_table[sercons.index].irq)				rs_table[i].irq = 0;	}#endif#endif	show_serial_version();	/* Initialize the tty_driver structure */		memset(&serial_driver, 0, sizeof(struct tty_driver));	serial_driver.magic = TTY_DRIVER_MAGIC;	serial_driver.driver_name = "serial";	serial_driver.name = "ttyS";	serial_driver.major = TTY_MAJOR;	serial_driver.minor_start = 64;	serial_driver.num = NR_PORTS;	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;	serial_driver.subtype = SERIAL_TYPE_NORMAL;	serial_driver.init_termios = tty_std_termios;	serial_driver.init_termios.c_cflag =		B9600 | CS8 | CREAD | HUPCL | CLOCAL;	serial_driver.flags = TTY_DRIVER_REAL_RAW;	serial_driver.refcount = &serial_refcount;	serial_driver.table = serial_table;	serial_driver.termios = serial_termios;	serial_driver.termios_locked = serial_termios_locked;	serial_driver.open = rs_open;	serial_driver.close = rs_close;	serial_driver.write = rs_write;	serial_driver.put_char = rs_put_char;	serial_driver.flush_chars = rs_flush_chars;	serial_driver.write_room = rs_write_room;	serial_driver.chars_in_buffer = rs_chars_in_buffer;	serial_driver.flush_buffer = rs_flush_buffer;	serial_driver.ioctl = rs_ioctl;	serial_driver.throttle = rs_throttle;	serial_driver.unthrottle = rs_unthrottle;	serial_driver.send_xchar = rs_send_xchar;	serial_driver.set_termios = rs_set_termios;	serial_driver.stop = rs_stop;	serial_driver.start = rs_start;	serial_driver.hangup = rs_hangup;	serial_driver.break_ctl = rs_break;	serial_driver.wait_until_sent = rs_wait_until_sent;	serial_driver.read_proc = rs_read_proc;		/*	 * The callout device is just like normal device except for	 * major number and the subtype code.	 */	callout_driver = serial_driver;	callout_driver.name = "cua";	callout_driver.major = TTYAUX_MAJOR;	callout_driver.subtype = SERIAL_TYPE_CALLOUT;	callout_driver.read_proc = 0;	callout_driver.proc_entry = 0;	if (tty_register_driver(&serial_driver))		panic("Couldn't register serial driver\n");	if (tty_register_driver(&callout_driver))		panic("Couldn't register callout driver\n");		for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {		state->magic = SSTATE_MAGIC;		state->line = i;		state->type = PORT_UNKNOWN;		state->custom_divisor = 0;		state->close_delay = 5*HZ/10;		state->closing_wait = 30*HZ;		state->callout_termios = callout_driver.init_termios;		state->normal_termios = serial_driver.init_termios;		state->icount.cts = state->icount.dsr = 			state->icount.rng = state->icount.dcd = 0;		state->icount.rx = state->icount.tx = 0;		state->icount.frame = state->icount.parity = 0;		state->icount.overrun = state->icount.brk = 0;		state->irq = irq_cannonicalize(state->irq);

⌨️ 快捷键说明

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