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

📄 serial_core.c

📁 ARM9 2440 Serial 应用开发程式软件
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	if (flow == 'r')		termios.c_cflag |= CRTSCTS;	port->ops->set_termios(port, &termios, NULL);	co->cflag = termios.c_cflag;	return 0;}#endif /* CONFIG_SERIAL_CORE_CONSOLE */static void uart_change_pm(struct uart_state *state, int pm_state){	struct uart_port *port = state->port;	if (port->ops->pm)		port->ops->pm(port, pm_state, state->pm_state);	state->pm_state = pm_state;}int uart_suspend_port(struct uart_driver *drv, struct uart_port *port){	struct uart_state *state = drv->state + port->line;	down(&state->sem);	if (state->info && state->info->flags & UIF_INITIALIZED) {		struct uart_ops *ops = port->ops;		spin_lock_irq(&port->lock);		ops->stop_tx(port, 0);		ops->set_mctrl(port, 0);		ops->stop_rx(port);		spin_unlock_irq(&port->lock);		/*		 * Wait for the transmitter to empty.		 */		while (!ops->tx_empty(port)) {			msleep(10);		}		ops->shutdown(port);	}	/*	 * Disable the console device before suspending.	 */	if (uart_console(port))		console_stop(port->cons);	uart_change_pm(state, 3);	up(&state->sem);	return 0;}int uart_resume_port(struct uart_driver *drv, struct uart_port *port){	struct uart_state *state = drv->state + port->line;	down(&state->sem);	uart_change_pm(state, 0);	/*	 * Re-enable the console device after suspending.	 */	if (uart_console(port)) {		struct termios termios;		/*		 * First try to use the console cflag setting.		 */		memset(&termios, 0, sizeof(struct termios));		termios.c_cflag = port->cons->cflag;		/*		 * If that's unset, use the tty termios setting.		 */		if (state->info && state->info->tty && termios.c_cflag == 0)			termios = *state->info->tty->termios;		port->ops->set_termios(port, &termios, NULL);		console_start(port->cons);	}	if (state->info && state->info->flags & UIF_INITIALIZED) {		struct uart_ops *ops = port->ops;		ops->set_mctrl(port, 0);		ops->startup(port);		uart_change_speed(state, NULL);		spin_lock_irq(&port->lock);		ops->set_mctrl(port, port->mctrl);		ops->start_tx(port, 0);		spin_unlock_irq(&port->lock);	}	up(&state->sem);	return 0;}static inline voiduart_report_port(struct uart_driver *drv, struct uart_port *port){	printk(KERN_ERR "enter uart_report_port() line %d passed\n",__LINE__);	printk("%s%d", drv->dev_name, port->line);	printk(" at ");	switch (port->iotype) {	case UPIO_PORT:		printk("I/O 0x%x", port->iobase);		break;	case UPIO_HUB6:		printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);		break;	case UPIO_MEM:	case UPIO_MEM32:		printk("MMIO 0x%lx", port->mapbase);		break;	}	printk(" (irq = %d) is a %s\n", port->irq, uart_type(port));}static voiduart_configure_port(struct uart_driver *drv, struct uart_state *state,		    struct uart_port *port){	unsigned int flags;	/*	 * If there isn't a port here, don't do anything further.	 */	if (!port->iobase && !port->mapbase && !port->membase)		{printk(KERN_ERR "line %d passed\n",__LINE__);	return;}  /*	 * Now do the auto configuration stuff.  Note that config_port	 * is expected to claim the resources and map the port for us.	 */	flags = UART_CONFIG_TYPE;	if (port->flags & UPF_AUTO_IRQ)		flags |= UART_CONFIG_IRQ;	if (port->flags & UPF_BOOT_AUTOCONF) {		port->type = PORT_UNKNOWN;		printk(KERN_ERR "line %d passed\n",__LINE__);		port->ops->config_port(port, flags);		printk(KERN_ERR "line %d passed\n",__LINE__);	}	if (port->type != PORT_UNKNOWN) {		unsigned long flags;printk(KERN_ERR "IN!!line %d passed\n",__LINE__);		uart_report_port(drv, port);		printk(KERN_ERR "line %d passed\n",__LINE__);		/*		 * Ensure that the modem control lines are de-activated.		 * We probably don't need a spinlock around this, but		 */		spin_lock_irqsave(&port->lock, flags);		printk(KERN_ERR "line %d passed\n",__LINE__);		port->ops->set_mctrl(port, 0);		printk(KERN_ERR "line %d passed\n",__LINE__);		spin_unlock_irqrestore(&port->lock, flags);		/*		 * Power down all ports by default, except the		 * console if we have one.		 */		if (!uart_console(port))			{printk(KERN_ERR "line %d passed\n",__LINE__);		uart_change_pm(state, 3);}	}	else printk(KERN_ERR "OUT!!line %d passed\n",__LINE__);}/* * This reverses the effects of uart_configure_port, hanging up the * port before removal. */static voiduart_unconfigure_port(struct uart_driver *drv, struct uart_state *state){	struct uart_port *port = state->port;	struct uart_info *info = state->info;	if (info && info->tty)		tty_vhangup(info->tty);	down(&state->sem);	state->info = NULL;	/*	 * Free the port IO and memory resources, if any.	 */	if (port->type != PORT_UNKNOWN)		port->ops->release_port(port);	/*	 * Indicate that there isn't a port here anymore.	 */	port->type = PORT_UNKNOWN;	/*	 * Kill the tasklet, and free resources.	 */	if (info) {		tasklet_kill(&info->tlet);		kfree(info);	}	up(&state->sem);}static struct tty_operations uart_ops = {	.open		= uart_open,	.close		= uart_close,	.write		= uart_write,	.put_char	= uart_put_char,	.flush_chars	= uart_flush_chars,	.write_room	= uart_write_room,	.chars_in_buffer= uart_chars_in_buffer,	.flush_buffer	= uart_flush_buffer,	.ioctl		= uart_ioctl,	.throttle	= uart_throttle,	.unthrottle	= uart_unthrottle,	.send_xchar	= uart_send_xchar,	.set_termios	= uart_set_termios,	.stop		= uart_stop,	.start		= uart_start,	.hangup		= uart_hangup,	.break_ctl	= uart_break_ctl,	.wait_until_sent= uart_wait_until_sent,#ifdef CONFIG_PROC_FS	.read_proc	= uart_read_proc,#endif	.tiocmget	= uart_tiocmget,	.tiocmset	= uart_tiocmset,};/** *	uart_register_driver - register a driver with the uart core layer *	@drv: low level driver structure * *	Register a uart driver with the core driver.  We in turn register *	with the tty layer, and initialise the core driver per-port state. * *	We have a proc file in /proc/tty/driver which is named after the *	normal driver. * *	drv->port should be NULL, and the per-port structures should be *	registered using uart_add_one_port after this call has succeeded. */int uart_register_driver(struct uart_driver *drv){	struct tty_driver *normal = NULL;	int i, retval;	BUG_ON(drv->state);	/*	 * Maybe we should be using a slab cache for this, especially if	 * we have a large number of ports to handle.	 */	drv->state = kmalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);	retval = -ENOMEM;	if (!drv->state)		goto out;	memset(drv->state, 0, sizeof(struct uart_state) * drv->nr);	normal  = alloc_tty_driver(drv->nr);	if (!normal)		goto out;	drv->tty_driver = normal;	normal->owner		= drv->owner;	normal->driver_name	= drv->driver_name;	normal->devfs_name	= drv->devfs_name;	normal->name		= drv->dev_name;	normal->major		= drv->major;	normal->minor_start	= drv->minor;	normal->type		= TTY_DRIVER_TYPE_SERIAL;	normal->subtype		= SERIAL_TYPE_NORMAL;	normal->init_termios	= tty_std_termios;	normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;	normal->flags		= TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;	normal->driver_state    = drv;	tty_set_operations(normal, &uart_ops);	/*	 * Initialise the UART state(s).	 */	for (i = 0; i < drv->nr; i++) {		struct uart_state *state = drv->state + i;		state->close_delay     = 500;	/* .5 seconds */		state->closing_wait    = 30000;	/* 30 seconds */		init_MUTEX(&state->sem);	}	retval = tty_register_driver(normal); out:	if (retval < 0) {		put_tty_driver(normal);		kfree(drv->state);	}	return retval;}/** *	uart_unregister_driver - remove a driver from the uart core layer *	@drv: low level driver structure * *	Remove all references to a driver from the core driver.  The low *	level driver must have removed all its ports via the *	uart_remove_one_port() if it registered them with uart_add_one_port(). *	(ie, drv->port == NULL) */void uart_unregister_driver(struct uart_driver *drv){	struct tty_driver *p = drv->tty_driver;	tty_unregister_driver(p);	put_tty_driver(p);	kfree(drv->state);	drv->tty_driver = NULL;}struct tty_driver *uart_console_device(struct console *co, int *index){	struct uart_driver *p = co->data;	*index = co->index;	return p->tty_driver;}/** *	uart_add_one_port - attach a driver-defined port structure *	@drv: pointer to the uart low level driver structure for this port *	@port: uart port structure to use for this port. * *	This allows the driver to register its own uart_port structure *	with the core driver.  The main purpose is to allow the low *	level uart drivers to expand uart_port, rather than having yet *	more levels of structures. */int uart_add_one_port(struct uart_driver *drv, struct uart_port *port){	struct uart_state *state;	int ret = 0;printk(KERN_ERR "line %d passed\n",__LINE__);	BUG_ON(in_interrupt());printk(KERN_ERR "line %d passed\n",__LINE__);	if (port->line >= drv->nr)		{printk(KERN_ERR "line %d passed\n",__LINE__);	return -EINVAL;}	state = drv->state + port->line;	down(&port_sem);	if (state->port) {		ret = -EINVAL;		printk(KERN_ERR "line %d passed\n",__LINE__);		goto out;	}	state->port = port;	spin_lock_init(&port->lock);	port->cons = drv->cons;	port->info = state->info;printk(KERN_ERR "before uart_configure_port!\n");	uart_configure_port(drv, state, port);	printk(KERN_ERR "after uart_configure_port!\n");	/*	 * Register the port whether it's detected or not.  This allows	 * setserial to be used to alter this ports parameters.	 */	 printk(KERN_ERR "line %d passed\n",__LINE__);	tty_register_device(drv->tty_driver, port->line, port->dev);printk(KERN_ERR "line %d passed\n",__LINE__);	/*	 * If this driver supports console, and it hasn't been	 * successfully registered yet, try to re-register it.	 * It may be that the port was not available.	 */	if (port->type != PORT_UNKNOWN &&	    port->cons && !(port->cons->flags & CON_ENABLED))		register_console(port->cons); out:	up(&port_sem);	return ret;}/** *	uart_remove_one_port - detach a driver defined port structure *	@drv: pointer to the uart low level driver structure for this port *	@port: uart port structure for this port * *	This unhooks (and hangs up) the specified port structure from the *	core driver.  No further calls will be made to the low-level code *	for this port. */int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port){	struct uart_state *state = drv->state + port->line;	BUG_ON(in_interrupt());	if (state->port != port)		printk(KERN_ALERT "Removing wrong port: %p != %p\n",			state->port, port);	down(&port_sem);	/*	 * Remove the devices from devfs	 */	tty_unregister_device(drv->tty_driver, port->line);	uart_unconfigure_port(drv, state);	state->port = NULL;	up(&port_sem);	return 0;}/* *	Are the two ports equivalent? */int uart_match_port(struct uart_port *port1, struct uart_port *port2){	if (port1->iotype != port2->iotype)		return 0;	switch (port1->iotype) {	case UPIO_PORT:		return (port1->iobase == port2->iobase);	case UPIO_HUB6:		return (port1->iobase == port2->iobase) &&		       (port1->hub6   == port2->hub6);	case UPIO_MEM:		return (port1->membase == port2->membase);	}	return 0;}EXPORT_SYMBOL(uart_match_port);/* *	Try to find an unused uart_state slot for a port. */static struct uart_state *uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port){	int i;	/*	 * First, find a port entry which matches.  Note: if we do	 * find a matching entry, and it has a non-zero use count,	 * then we can't register the port.	 */	for (i = 0; i < drv->nr; i++)		if (uart_match_port(drv->state[i].port, port))			return &drv->state[i];	/*	 * We didn't find a matching entry, so look for the first	 * free entry.  We look for one which hasn't been previously	 * used (indicated by zero iobase).	 */	for (i = 0; i < drv->nr; i++)		if (drv->state[i].port->type == PORT_UNKNOWN &&		    drv->state[i].port->iobase == 0 &&		    drv->state[i].count == 0)			return &drv->state[i];	/*	 * That also failed.  Last resort is to find any currently	 * entry which doesn't have a real port associated with it.	 */	for (i = 0; i < drv->nr; i++)		if (drv->state[i].port->type == PORT_UNKNOWN &&		    drv->state[i].count == 0)			return &drv->state[i];	return NULL;}/** *	uart_register_port: register uart settings with a port *	@drv: pointer to the uart low level driver structure for this port *	@port: uart port structure describing the port * *	Register UART settings with the specified low level driver.  Detect *	the type of the port if UPF_BOOT_AUTOCONF is set, and detect the *	IRQ if UPF_AUTO_IRQ is set. * *	We try to pick the same port for the same IO base address, so that *	when a modem is plugged in, unplugged and plugged back in, it gets *	allocated the same port. * *	Returns negative error, or positive line number. */int uart_register_port(struct uart_driver *drv, struct uart_port *port){	struct uart_state *state;	int ret;	down(&port_sem);	state = uart_find_match_or_unused(drv, port);	if (state) {		/*		 * Ok, we've found a line that we can use.		 *		 * If we find a port that matches this one, and it appears		 * to be in-use (even if it doesn't have a type) we shouldn't		 * alter it underneath itself - the port may be open and		 * trying to do useful work.		 */		if (uart_users(state) != 0) {			ret = -EBUSY;			goto out;		}		/*		 * If the port is already initialised, don't touch it.		 */		if (state->port->type == PORT_UNKNOWN) {			state->port->iobase   = port->iobase;			state->port->membase  = port->membase;			state->port->irq      = port->irq;			state->port->uartclk  = port->uartclk;			state->port->fifosize = port->fifosize;			state->port->regshift = port->regshift;			state->port->iotype   = port->iotype;			state->port->flags    = port->flags;			state->port->line     = state - drv->state;			state->port->mapbase  = port->mapbase;			uart_configure_port(drv, state, state->port);		}		ret = state->port->line;	} else		ret = -ENOSPC; out:	up(&port_sem);	return ret;}/** *	uart_unregister_port - de-allocate a port *	@drv: pointer to the uart low level driver structure for this port *	@line: line index previously returned from uart_register_port() * *	Hang up the specified line associated with the low level driver, *	and mark the port as unused. */void uart_unregister_port(struct uart_driver *drv, int line){	struct uart_state *state;	if (line < 0 || line >= drv->nr) {		printk(KERN_ERR "Attempt to unregister ");		printk("%s%d", drv->dev_name, line);		printk("\n");		return;	}	state = drv->state + line;	down(&port_sem);	uart_unconfigure_port(drv, state);	up(&port_sem);}EXPORT_SYMBOL(uart_write_wakeup);EXPORT_SYMBOL(uart_register_driver);EXPORT_SYMBOL(uart_unregister_driver);EXPORT_SYMBOL(uart_suspend_port);EXPORT_SYMBOL(uart_resume_port);EXPORT_SYMBOL(uart_register_port);EXPORT_SYMBOL(uart_unregister_port);EXPORT_SYMBOL(uart_add_one_port);EXPORT_SYMBOL(uart_remove_one_port);MODULE_DESCRIPTION("Serial driver core");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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