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

📄 serial_core.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 4 页
字号:
	return ports + idx;}/** *	uart_parse_options - Parse serial port baud/parity/bits/flow contro. *	@options: pointer to option string *	@baud: pointer to an 'int' variable for the baud rate. *	@parity: pointer to an 'int' variable for the parity. *	@bits: pointer to an 'int' variable for the number of data bits. *	@flow: pointer to an 'int' variable for the flow control character. * *	uart_parse_options decodes a string containing the serial console *	options.  The format of the string is <baud><parity><bits><flow>, *	eg: 115200n8r */void __inituart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow){	char *s = options;	*baud = simple_strtoul(s, NULL, 10);	while (*s >= '0' && *s <= '9')		s++;	if (*s)		*parity = *s++;	if (*s)		*bits = *s++ - '0';	if (*s)		*flow = *s;}/** *	uart_set_options - setup the serial console parameters *	@port: pointer to the serial ports uart_port structure *	@co: console pointer *	@baud: baud rate *	@parity: parity character - 'n' (none), 'o' (odd), 'e' (even) *	@bits: number of data bits *	@flow: flow control character - 'r' (rts) */int __inituart_set_options(struct uart_port *port, struct console *co,		 int baud, int parity, int bits, int flow){	u_int cflag = CREAD | HUPCL | CLOCAL;	u_int quot;	/*	 * Construct a cflag setting.	 */	switch (baud) {	case 1200:	cflag |= B1200;			break;	case 2400:	cflag |= B2400;			break;	case 4800:	cflag |= B4800;			break;	case 9600:	cflag |= B9600;			break;	case 19200:	cflag |= B19200;		break;	default:	cflag |= B38400;  baud = 38400;	break;	case 57600:	cflag |= B57600;		break;	case 115200:	cflag |= B115200;		break;	case 230400:	cflag |= B230400;		break;	case 460800:	cflag |= B460800;		break;	}	if (bits == 7)		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;}#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(struct pm_dev *dev, pm_request_t rqst, void *data){	if (rqst == PM_SUSPEND || rqst == PM_RESUME) {		struct uart_state *state = dev->data;		struct uart_port *port = state->port;		struct uart_ops *ops = port->ops;		int pm_state = (int)data;		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, dev->state);			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, dev->state);		} 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, dev->state);		}	}	return 0;}#endifstatic 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);	}#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 + 1;	*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_CON, 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);	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);

⌨️ 快捷键说明

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