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

📄 core.c

📁 IXP425 平台下嵌入式LINUX的串口的驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		cflag |= CS7;	else		cflag |= CS8;	switch (parity) {	case 'o': case 'O':		cflag |= PARODD;		/*fall through*/	case 'e': case 'E':		cflag |= PARENB;		break;	}	co->cflag = cflag;	quot = (port->uartclk / (16 * baud));	port->ops->change_speed(port, cflag, 0, quot);	return 0;}extern void ambauart_console_init(void);extern void anakin_console_init(void);extern void clps711xuart_console_init(void);extern void rs285_console_init(void);extern void sa1100_rs_console_init(void);extern void serial8250_console_init(void);extern void ixp1200_console_init(void);/* * Central "initialise all serial consoles" container.  Needs to be killed. */void __init uart_console_init(void){#ifdef CONFIG_SERIAL_AMBA_CONSOLE	ambauart_console_init();#endif#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE	anakin_console_init();#endif#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE	clps711xuart_console_init();#endif#ifdef CONFIG_SERIAL_21285_CONSOLE	rs285_console_init();#endif#ifdef CONFIG_SERIAL_SA1100_CONSOLE	sa1100_rs_console_init();#endif#ifdef CONFIG_SERIAL_8250_CONSOLE	serial8250_console_init();#endif#ifdef CONFIG_SERIAL_UART00_CONSOLE	uart00_console_init();#endif#ifdef CONFIG_SERIAL_IXP1200_CONSOLE	ixp1200_console_init();#endif}#endif /* CONFIG_SERIAL_CORE_CONSOLE */#ifdef CONFIG_PM/* *  Serial port power management. * * This is pretty coarse at the moment - either all on or all off.  We * should probably some day do finer power management here some day. * * We don't actually save any state; the serial driver has enough * state held internally to re-setup the port when we come out of D3. */static int uart_pm_set_state(struct uart_state *state, int pm_state, int oldstate){	struct uart_port *port = state->port;	struct uart_ops *ops = port->ops;	int running = state->info &&		      state->info->flags & ASYNC_INITIALIZED;	if (port->type == PORT_UNKNOWN)		return 0;//printk("pm: %08x: %d -> %d, %srunning\n", port->iobase, dev->state, pm_state, running ? "" : "not ");	if (pm_state == 0) {		if (ops->pm)			ops->pm(port, pm_state, oldstate);		if (running) {			ops->set_mctrl(port, 0);			ops->startup(port, state->info);			uart_change_speed(state->info, NULL);			ops->set_mctrl(port, state->info->mctrl);			ops->start_tx(port, 1, 0);		}		/*		 * Re-enable the console device after suspending.		 */		if (state->cons && state->cons->index == port->line)			state->cons->flags |= CON_ENABLED;	} else if (pm_state == 1) {		if (ops->pm)			ops->pm(port, pm_state, oldstate);	} else {		/*		 * Disable the console device before suspending.		 */		if (state->cons && state->cons->index == port->line)			state->cons->flags &= ~CON_ENABLED;		if (running) {			ops->stop_tx(port, 0);			ops->set_mctrl(port, 0);			ops->stop_rx(port);			ops->shutdown(port, state->info);		}		if (ops->pm)			ops->pm(port, pm_state, oldstate);	}	return 0;}/* *  Wakeup support. */static int uart_pm_set_wakeup(struct uart_state *state, int data){	int err = 0;	if (state->port->ops->set_wake)		err = state->port->ops->set_wake(state->port, data);	return err;}static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data){	struct uart_state *state = dev->data;	int err = 0;	switch (rqst) {	case PM_SUSPEND:	case PM_RESUME:		err = uart_pm_set_state(state, (int)data, dev->state);		break;	case PM_SET_WAKEUP:		err = uart_pm_set_wakeup(state, (int)data);		break;	}	return err;}#endifstatic inline voiduart_report_port(struct uart_driver *drv, struct uart_port *port){	printk("%s%d at ", drv->normal_name, port->line);	switch (port->iotype) {	case SERIAL_IO_PORT:		printk("I/O 0x%x", port->iobase);		break;	case SERIAL_IO_HUB6:		printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);		break;	case SERIAL_IO_MEM:		printk("MEM 0x%lx", port->mapbase);		break;	}	printk(" (irq = %d) is a %s\n", port->irq, uart_type(port));}static voiduart_setup_port(struct uart_driver *drv, struct uart_state *state){	struct uart_port *port = state->port;	int flags = UART_CONFIG_TYPE;	init_MUTEX(&state->count_sem);	state->close_delay	= 5 * HZ / 10;	state->closing_wait	= 30 * HZ;	port->type = PORT_UNKNOWN;#ifdef CONFIG_PM	state->cons = drv->cons;	state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);	if (state->pm)		state->pm->data = state;#endif	/*	 * If there isn't a port here, don't do anything further.	 */	if (!port->iobase && !port->mapbase)		return;	/*	 * Now do the auto configuration stuff.  Note that config_port	 * is expected to claim the resources and map the port for us.	 */	if (port->flags & ASYNC_AUTO_IRQ)		flags |= UART_CONFIG_IRQ;	if (port->flags & ASYNC_BOOT_AUTOCONF)		port->ops->config_port(port, flags);	/*	 * Only register this port if it is detected.	 */	if (port->type != PORT_UNKNOWN) {		tty_register_devfs(drv->normal_driver, 0, drv->minor +					state->port->line);		tty_register_devfs(drv->callout_driver, 0, drv->minor +					state->port->line);		uart_report_port(drv, port);	}#ifdef CONFIG_PM	/*	 * Power down all ports by default, except the console if we have one.	 */	if (state->pm && (!drv->cons || port->line != drv->cons->index))		pm_send(state->pm, PM_SUSPEND, (void *)3);#endif}/* * Register a set of ports with the core driver.  Note that we don't * printk any information about the ports; that is up to the low level * driver to do if they so wish. */int uart_register_driver(struct uart_driver *drv){	struct tty_driver *normal, *callout;	int i, retval;	if (drv->state)		panic("drv->state already allocated\n");	/*	 * Maybe we should be using a slab cache for this, especially if	 * we have a large number of ports to handle.  Note that we also	 * allocate space for an integer for reference counting.	 */	drv->state = kmalloc(sizeof(struct uart_state) * drv->nr +			     sizeof(int), GFP_KERNEL);	retval = -ENOMEM;	if (!drv->state)		goto out;	memset(drv->state, 0, sizeof(struct uart_state) * drv->nr +			sizeof(int));	normal  = drv->normal_driver;	callout = drv->callout_driver;	normal->magic		= TTY_DRIVER_MAGIC;	normal->driver_name	= drv->normal_name;	normal->name		= drv->normal_name;	normal->major		= drv->normal_major;	normal->minor_start	= drv->minor;	normal->num		= drv->nr;	normal->type		= TTY_DRIVER_TYPE_SERIAL;	normal->subtype		= SERIAL_TYPE_NORMAL;	normal->init_termios	= tty_std_termios;	normal->init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;	normal->flags		= TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;	normal->refcount	= (int *)(drv->state + drv->nr);	normal->table		= drv->table;	normal->termios		= drv->termios;	normal->termios_locked	= drv->termios_locked;	normal->driver_state    = drv;	normal->open		= uart_open;	normal->close		= uart_close;	normal->write		= uart_write;	normal->put_char	= uart_put_char;	normal->flush_chars	= uart_flush_chars;	normal->write_room	= uart_write_room;	normal->chars_in_buffer	= uart_chars_in_buffer;	normal->flush_buffer	= uart_flush_buffer;	normal->ioctl		= uart_ioctl;	normal->throttle	= uart_throttle;	normal->unthrottle	= uart_unthrottle;	normal->send_xchar	= uart_send_xchar;	normal->set_termios	= uart_set_termios;	normal->stop		= uart_stop;	normal->start		= uart_start;	normal->hangup		= uart_hangup;	normal->break_ctl	= uart_break_ctl;	normal->wait_until_sent	= uart_wait_until_sent;#ifdef CONFIG_PROC_FS	normal->read_proc	= uart_read_proc;#endif	/*	 * The callout device is just like the normal device except for	 * the major number and the subtype code.	 */	*callout		= *normal;	callout->name		= drv->callout_name;	callout->major		= drv->callout_major;	callout->subtype	= SERIAL_TYPE_CALLOUT;	callout->read_proc	= NULL;	callout->proc_entry	= NULL;	for (i = 0; i < drv->nr; i++) {		struct uart_state *state = drv->state + i;		state->callout_termios	= callout->init_termios;		state->normal_termios	= normal->init_termios;		state->port		= drv->port + i;		state->port->line	= i;		uart_setup_port(drv, state);	}	retval = tty_register_driver(normal);	if (retval)		goto out;	retval = tty_register_driver(callout);	if (retval)		tty_unregister_driver(normal);out:	if (retval && drv->state)		kfree(drv->state);	return retval;}void uart_unregister_driver(struct uart_driver *drv){	int i;	for (i = 0; i < drv->nr; i++) {		struct uart_state *state = drv->state + i;		if (state->info && state->info->tty)			tty_hangup(state->info->tty);		pm_unregister(state->pm);		if (state->port->type != PORT_UNKNOWN)			state->port->ops->release_port(state->port);		if (state->info) {			tasklet_kill(&state->info->tlet);			kfree(state->info);		}	}	tty_unregister_driver(drv->normal_driver);	tty_unregister_driver(drv->callout_driver);	kfree(drv->state);}static int uart_match_port(struct uart_port *port1, struct uart_port *port2){	if (port1->iotype != port2->iotype)		return 0;	switch (port1->iotype) {	case SERIAL_IO_PORT:	return (port1->iobase == port2->iobase);	case SERIAL_IO_MEM:	return (port1->membase == port2->membase);	}	return 0;}/** *	uart_register_port: register a port with the generic uart driver *	@reg: pointer to the uart low level driver structure for this port *	@port: uart port structure describing the port * *	Register a UART with the specified low level driver.  Detect the *	type of the port if ASYNC_BOOT_AUTOCONF is set, and detect the IRQ *	if ASYNC_AUTO_IRQ is set. * *	Returns negative error, or positive line number. */int uart_register_port(struct uart_driver *drv, struct uart_port *port){	struct uart_state *state = NULL;	int i, flags = UART_CONFIG_TYPE;	/*	 * 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.	 */	down(&port_sem);	for (i = 0; i < drv->nr; i++) {		if (uart_match_port(drv->state[i].port, port)) {			down(&drv->state[i].count_sem);			state = &drv->state[i];			break;		}	}	/*	 * If we didn't find a matching entry, look for the first	 * free entry.  We look for one which hasn't been previously	 * used (indicated by zero iobase).	 */	if (!state) {		for (i = 0; i < drv->nr; i++) {			if (drv->state[i].port->type == PORT_UNKNOWN &&			    drv->state[i].port->iobase == 0) {				down(&drv->state[i].count_sem);				if (drv->state[i].count == 0) {					state = &drv->state[i];					break;				}			}		}	}	/*	 * Ok, that also failed.  Find the first unused entry, which	 * may be previously in use.	 */	if (!state) {		for (i = 0; i < drv->nr; i++) {			if (drv->state[i].port->type == PORT_UNKNOWN) {				down(&drv->state[i].count_sem);				if (drv->state[i].count == 0) {					state = &drv->state[i];					break;				}			}		}	}	up(&port_sem);	if (!state)		return -ENOSPC;	/*	 * 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 (state->count != 0 ||	    (state->info && state->info->blocked_open != 0)) {		up(&state->count_sem);		return -EBUSY;	}	/*	 * We're holding the lock for this port.  Copy the relevant data	 * into the port structure.	 */	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;#if 0 //def CONFIG_PM	/* we have already registered the power management handlers */	state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);	if (state->pm) {		state->pm->data = state;		/*		 * Power down all ports by default, except		 * the console if we have one.		 */		if (!drv->cons || state->port->line != drv->cons->index)			pm_send(state->pm, PM_SUSPEND, (void *)3);	}#endif	if (state->port->flags & ASYNC_AUTO_IRQ)		flags |= UART_CONFIG_IRQ;	if (state->port->flags & ASYNC_BOOT_AUTOCONF)		state->port->ops->config_port(state->port, flags);	tty_register_devfs(drv->normal_driver, 0, drv->minor +					state->port->line);	tty_register_devfs(drv->callout_driver, 0, drv->minor +					state->port->line);	uart_report_port(drv, state->port);	up(&state->count_sem);	return i;}/* * Unregister the specified port index on the specified driver. */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 %s%d\n",			drv->normal_name, line);		return;	}	state = drv->state + line;	down(&state->count_sem);	/*	 * The port has already gone.  We have to hang up the line	 * to kill all usage of this port.	 */	if (state->info && state->info->tty)		tty_hangup(state->info->tty);	/*	 * Free the ports resources, if any.	 */	state->port->ops->release_port(state->port);	/*	 * Indicate that there isn't a port here anymore.	 */	state->port->type = PORT_UNKNOWN;#if 0 // not yet	/*	 * No point in doing power management for hardware that	 * isn't present.	 */	pm_unregister(state->pm);#endif	/*	 * Remove the devices from devfs	 */	tty_unregister_devfs(drv->normal_driver, drv->minor + line);	tty_unregister_devfs(drv->callout_driver, drv->minor + line);	up(&state->count_sem);}EXPORT_SYMBOL(uart_event);EXPORT_SYMBOL(uart_register_driver);EXPORT_SYMBOL(uart_unregister_driver);EXPORT_SYMBOL(uart_register_port);EXPORT_SYMBOL(uart_unregister_port);static int __init uart_init(void){	return 0;}static void __exit uart_exit(void){	free_page((unsigned long)tmp_buf);	tmp_buf = NULL;}module_init(uart_init);module_exit(uart_exit);MODULE_DESCRIPTION("Serial driver core");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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