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

📄 8250.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
{	unsigned int size = 8 << up->port.regshift;	unsigned long start;	int ret = 0;	switch (up->port.iotype) {	case UPIO_MEM:		if (up->port.mapbase) {			start = up->port.mapbase;			start += UART_RSA_BASE << up->port.regshift;			*res = request_mem_region(start, size, "serial-rsa");			if (!*res)				ret = -EBUSY;		}		break;	case UPIO_HUB6:	case UPIO_PORT:		start = up->port.iobase;		start += UART_RSA_BASE << up->port.regshift;		*res = request_region(start, size, "serial-rsa");		if (!*res)			ret = -EBUSY;		break;	}	return ret;}static void serial8250_release_port(struct uart_port *port){	struct uart_8250_port *up = (struct uart_8250_port *)port;	unsigned long start, offset = 0, size = 0;	if (up->port.type == PORT_RSA) {		offset = UART_RSA_BASE << up->port.regshift;		size = 8;	}	size <<= up->port.regshift;	switch (up->port.iotype) {	case UPIO_MEM:		if (up->port.mapbase) {			/*			 * Unmap the area.			 */			iounmap(up->port.membase);			up->port.membase = NULL;			start = up->port.mapbase;			if (size)				release_mem_region(start + offset, size);			release_mem_region(start, 8 << up->port.regshift);		}		break;	case UPIO_HUB6:	case UPIO_PORT:		start = up->port.iobase;		if (size)			release_region(start + offset, size);		release_region(start + offset, 8 << up->port.regshift);		break;	default:		break;	}}static int serial8250_request_port(struct uart_port *port){	struct uart_8250_port *up = (struct uart_8250_port *)port;	struct resource *res = NULL, *res_rsa = NULL;	int ret = 0;	if (up->port.type == PORT_RSA) {		ret = serial8250_request_rsa_resource(up, &res_rsa);		if (ret < 0)			return ret;	}	ret = serial8250_request_std_resource(up, &res);	/*	 * If we have a mapbase, then request that as well.	 */	if (ret == 0 && up->port.flags & UPF_IOREMAP) {		int size = res->end - res->start + 1;		up->port.membase = ioremap(up->port.mapbase, size);		if (!up->port.membase)			ret = -ENOMEM;	}	if (ret < 0) {		if (res_rsa)			release_resource(res_rsa);		if (res)			release_resource(res);	}	return ret;}static void serial8250_config_port(struct uart_port *port, int flags){	struct uart_8250_port *up = (struct uart_8250_port *)port;	struct resource *res_std = NULL, *res_rsa = NULL;	int probeflags = PROBE_ANY;	int ret;#ifdef CONFIG_MCA	/*	 * Don't probe for MCA ports on non-MCA machines.	 */	if (up->port.flags & UPF_BOOT_ONLYMCA && !MCA_bus)		return;#endif	/*	 * Find the region that we can probe for.  This in turn	 * tells us whether we can probe for the type of port.	 */	ret = serial8250_request_std_resource(up, &res_std);	if (ret < 0)		return;	ret = serial8250_request_rsa_resource(up, &res_rsa);	if (ret < 0)		probeflags &= ~PROBE_RSA;	if (flags & UART_CONFIG_TYPE)		autoconfig(up, probeflags);	if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)		autoconfig_irq(up);	/*	 * If the port wasn't an RSA port, release the resource.	 */	if (up->port.type != PORT_RSA && res_rsa)		release_resource(res_rsa);	if (up->port.type == PORT_UNKNOWN && res_std)		release_resource(res_std);}static intserial8250_verify_port(struct uart_port *port, struct serial_struct *ser){	if (ser->irq >= NR_IRQS || ser->irq < 0 ||	    ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||	    ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS ||	    ser->type == PORT_STARTECH)		return -EINVAL;	return 0;}static const char *serial8250_type(struct uart_port *port){	int type = port->type;	if (type >= ARRAY_SIZE(uart_config))		type = 0;	return uart_config[type].name;}static struct uart_ops serial8250_pops = {	.tx_empty	= serial8250_tx_empty,	.set_mctrl	= serial8250_set_mctrl,	.get_mctrl	= serial8250_get_mctrl,	.stop_tx	= serial8250_stop_tx,	.start_tx	= serial8250_start_tx,	.stop_rx	= serial8250_stop_rx,	.enable_ms	= serial8250_enable_ms,	.break_ctl	= serial8250_break_ctl,	.startup	= serial8250_startup,	.shutdown	= serial8250_shutdown,	.set_termios	= serial8250_set_termios,	.pm		= serial8250_pm,	.type		= serial8250_type,	.release_port	= serial8250_release_port,	.request_port	= serial8250_request_port,	.config_port	= serial8250_config_port,	.verify_port	= serial8250_verify_port,};static struct uart_8250_port serial8250_ports[UART_NR];static void __init serial8250_isa_init_ports(void){	struct uart_8250_port *up;	static int first = 1;	int i;	if (!first)		return;	first = 0;	for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);	     i++, up++) {		up->port.iobase   = old_serial_port[i].port;		up->port.irq      = irq_canonicalize(old_serial_port[i].irq);		up->port.uartclk  = old_serial_port[i].baud_base * 16;		up->port.flags    = old_serial_port[i].flags;		up->port.hub6     = old_serial_port[i].hub6;		up->port.membase  = old_serial_port[i].iomem_base;		up->port.iotype   = old_serial_port[i].io_type;		up->port.regshift = old_serial_port[i].iomem_reg_shift;		up->port.ops      = &serial8250_pops;		if (share_irqs)			up->port.flags |= UPF_SHARE_IRQ;	}}static void __init serial8250_register_ports(struct uart_driver *drv){	int i;	serial8250_isa_init_ports();	for (i = 0; i < UART_NR; i++) {		struct uart_8250_port *up = &serial8250_ports[i];		up->port.line = i;		up->port.ops = &serial8250_pops;		init_timer(&up->timer);		up->timer.function = serial8250_timeout;		/*		 * ALPHA_KLUDGE_MCR needs to be killed.		 */		up->mcr_mask = ~ALPHA_KLUDGE_MCR;		up->mcr_force = ALPHA_KLUDGE_MCR;		uart_add_one_port(drv, &up->port);	}}#ifdef CONFIG_SERIAL_8250_CONSOLE#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)/* *	Wait for transmitter & holding register to empty */static inline void wait_for_xmitr(struct uart_8250_port *up){	unsigned int status, tmout = 10000;	/* Wait up to 10ms for the character(s) to be sent. */	do {		status = serial_in(up, UART_LSR);		if (status & UART_LSR_BI)			up->lsr_break_flag = UART_LSR_BI;		if (--tmout == 0)			break;		udelay(1);	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);	/* Wait up to 1s for flow control if necessary */	if (up->port.flags & UPF_CONS_FLOW) {		tmout = 1000000;		while (--tmout &&		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))			udelay(1);	}}/* *	Print a string to the serial port trying not to disturb *	any possible real use of the port... * *	The console_lock must be held when we get here. */static voidserial8250_console_write(struct console *co, const char *s, unsigned int count){	struct uart_8250_port *up = &serial8250_ports[co->index];	unsigned int ier;	int i;	/*	 *	First save the UER then disable the interrupts	 */	ier = serial_in(up, UART_IER);	if (up->port.type == PORT_XSCALE)		serial_out(up, UART_IER, UART_IER_UUE);	else		serial_out(up, UART_IER, 0);	/*	 *	Now, do each character	 */	for (i = 0; i < count; i++, s++) {		wait_for_xmitr(up);		/*		 *	Send the character out.		 *	If a LF, also do CR...		 */		serial_out(up, UART_TX, *s);		if (*s == 10) {			wait_for_xmitr(up);			serial_out(up, UART_TX, 13);		}	}	/*	 *	Finally, wait for transmitter to become empty	 *	and restore the IER	 */	wait_for_xmitr(up);	serial_out(up, UART_IER, ier);}static int __init serial8250_console_setup(struct console *co, char *options){	struct uart_port *port;	int baud = 115200;	int bits = 8;	int parity = 'n';	int flow = 'n';	/*	 * Check whether an invalid uart number has been specified, and	 * if so, search for the first available port that does have	 * console support.	 */	if (co->index >= UART_NR)		co->index = 0;	port = &serial8250_ports[co->index].port;	if (!port->ops)		return -ENODEV;	/*	 * Temporary fix.	 */	spin_lock_init(&port->lock);	if (options)		uart_parse_options(options, &baud, &parity, &bits, &flow);	return uart_set_options(port, co, baud, parity, bits, flow);}static struct uart_driver serial8250_reg;static struct console serial8250_console = {	.name		= "ttyS",	.write		= serial8250_console_write,	.device		= uart_console_device,	.setup		= serial8250_console_setup,	.flags		= CON_PRINTBUFFER,	.index		= -1,	.data		= &serial8250_reg,};static int __init serial8250_console_init(void){	serial8250_isa_init_ports();	register_console(&serial8250_console);	return 0;}console_initcall(serial8250_console_init);static int __init serial8250_late_console_init(void){	if (!(serial8250_console.flags & CON_ENABLED))		register_console(&serial8250_console);	return 0;}late_initcall(serial8250_late_console_init);#define SERIAL8250_CONSOLE	&serial8250_console#else#define SERIAL8250_CONSOLE	NULL#endifstatic struct uart_driver serial8250_reg = {	.owner			= THIS_MODULE,	.driver_name		= "serial",	.devfs_name		= "tts/",	.dev_name		= "ttyS",	.major			= TTY_MAJOR,	.minor			= 64,	.nr			= UART_NR,	.cons			= SERIAL8250_CONSOLE,};/* * register_serial and unregister_serial allows for 16x50 serial ports to be * configured at run-time, to support PCMCIA modems. */static int __register_serial(struct serial_struct *req, int line){	struct uart_port port;	port.type     = req->type;	port.iobase   = req->port;	port.membase  = req->iomem_base;	port.irq      = req->irq;	port.uartclk  = req->baud_base * 16;	port.fifosize = req->xmit_fifo_size;	port.regshift = req->iomem_reg_shift;	port.iotype   = req->io_type;	port.flags    = req->flags;	port.mapbase  = req->iomap_base;	port.line     = line;	if (req->type != PORT_OMAP)		req->flags |= UPF_BOOT_AUTOCONF;	if (share_irqs)		port.flags |= UPF_SHARE_IRQ;	if (HIGH_BITS_OFFSET)		port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET;	/*	 * If a clock rate wasn't specified by the low level	 * driver, then default to the standard clock rate.	 */	if (port.uartclk == 0)		port.uartclk = BASE_BAUD * 16;	return uart_register_port(&serial8250_reg, &port);}/** *	register_serial - configure a 16x50 serial port at runtime *	@req: request structure * *	Configure the serial port specified by the request. If the *	port exists and is in use an error is returned. If the port *	is not currently in the table it is added. * *	The port is then probed and if necessary the IRQ is autodetected *	If this fails an error is returned. * *	On success the port is ready to use and the line number is returned. */int register_serial(struct serial_struct *req){	return __register_serial(req, -1);}int __init early_serial_setup(struct uart_port *port){	if (port->line >= ARRAY_SIZE(serial8250_ports))		return -ENODEV;	serial8250_isa_init_ports();	serial8250_ports[port->line].port	= *port;	serial8250_ports[port->line].port.ops	= &serial8250_pops;	return 0;}/** *	unregister_serial - remove a 16x50 serial port at runtime *	@line: serial line number * *	Remove one serial port.  This may be called from interrupt *	context. */void unregister_serial(int line){	uart_unregister_port(&serial8250_reg, line);}/* * This is for ISAPNP only. */void serial8250_get_irq_map(unsigned int *map){	int i;	for (i = 0; i < UART_NR; i++) {		if (serial8250_ports[i].port.type != PORT_UNKNOWN &&		    serial8250_ports[i].port.irq < 16)			*map |= 1 << serial8250_ports[i].port.irq;	}}/** *	serial8250_suspend_port - suspend one serial port *	@line:  serial line number *      @level: the level of port suspension, as per uart_suspend_port * *	Suspend one serial port. */void serial8250_suspend_port(int line){	uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port);}/** *	serial8250_resume_port - resume one serial port *	@line:  serial line number *      @level: the level of port resumption, as per uart_resume_port * *	Resume one serial port. */void serial8250_resume_port(int line){	uart_resume_port(&serial8250_reg, &serial8250_ports[line].port);}static int __init serial8250_init(void){	int ret, i;	printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ "		"%d ports, IRQ sharing %sabled\n", (int) UART_NR,		share_irqs ? "en" : "dis");	for (i = 0; i < NR_IRQS; i++)		spin_lock_init(&irq_lists[i].lock);	ret = uart_register_driver(&serial8250_reg);	if (ret >= 0)		serial8250_register_ports(&serial8250_reg);	return ret;}static void __exit serial8250_exit(void){	int i;	for (i = 0; i < UART_NR; i++)		uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port);	uart_unregister_driver(&serial8250_reg);}module_init(serial8250_init);module_exit(serial8250_exit);EXPORT_SYMBOL(register_serial);EXPORT_SYMBOL(unregister_serial);EXPORT_SYMBOL(serial8250_get_irq_map);EXPORT_SYMBOL(serial8250_suspend_port);EXPORT_SYMBOL(serial8250_resume_port);MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.90 $");module_param(share_irqs, uint, 0644);MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"	" (unsafe)");#ifdef CONFIG_SERIAL_8250_RSAmodule_param_array(probe_rsa, ulong, probe_rsa_count, 0444);MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");#endifMODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);

⌨️ 快捷键说明

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