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

📄 8250.c

📁 the attached file is the driver of Uart
💻 C
📖 第 1 页 / 共 5 页
字号:
		serial8250_release_std_resource(up);}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 >= ARRAY_SIZE(uart_config) || 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; i < UART_NR; i++) {		struct uart_8250_port *up = &serial8250_ports[i];		up->port.line = i;		spin_lock_init(&up->port.lock);		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;		up->port.ops = &serial8250_pops;	}	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;		if (share_irqs)			up->port.flags |= UPF_SHARE_IRQ;	}}static void __initserial8250_register_ports(struct uart_driver *drv, struct device *dev){	int i;	serial8250_isa_init_ports();	for (i = 0; i < UART_NR; i++) {		struct uart_8250_port *up = &serial8250_ports[i];		if (up->port.line == kgdb8250_ttyS)			continue;		up->port.dev = dev;		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 serial8250_console_setup(struct console *co, char *options){	struct uart_port *port;	int baud = 9600;	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->iobase && !port->membase)		return -ENODEV;	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);static int __init find_port(struct uart_port *p){	int line;	struct uart_port *port;	for (line = 0; line < UART_NR; line++) {		port = &serial8250_ports[line].port;		if (p->iotype == port->iotype &&		    p->iobase == port->iobase &&		    p->membase == port->membase)			return line;	}	return -ENODEV;}int __init serial8250_start_console(struct uart_port *port, char *options){	int line;	line = find_port(port);	if (line < 0)		return -ENODEV;	add_preferred_console("ttyS", line, options);	printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n",		line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port",		port->iotype == UPIO_MEM ? (unsigned long) port->mapbase :		    (unsigned long) port->iobase, options);	if (!(serial8250_console.flags & CON_ENABLED)) {		serial8250_console.flags &= ~CON_PRINTBUFFER;		register_console(&serial8250_console);	}	return line;}#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,};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;	spin_lock_init(&serial8250_ports[port->line].port.lock);	return 0;}/** *	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 struct uart_8250_port *uart_8250_register_port(struct uart_port *port, int *line);/* * Register a set of serial devices attached to a platform device.  The * list is terminated with a zero flags entry, which means we expect * all entries to have at least UPF_BOOT_AUTOCONF set. */static int __devinit serial8250_probe(struct device *dev){	struct plat_serial8250_port *p = dev->platform_data;	struct uart_port port;	struct uart_8250_port *uart;	int line;	memset(&port, 0, sizeof(struct uart_port));	for (; p && p->flags != 0; p++) {		port.iobase	= p->iobase;		port.membase	= p->membase;		port.irq	= p->irq;		port.uartclk	= p->uartclk;		port.regshift	= p->regshift;		port.iotype	= p->iotype;		port.flags	= p->flags;		port.mapbase	= p->mapbase;		port.line	= p->line;		port.dev	= dev;		if (share_irqs)			port.flags |= UPF_SHARE_IRQ;		uart = uart_8250_register_port(&port, &line);		if (!IS_ERR(uart))			uart->pm = p->pm;	}	return 0;}/* * Remove serial ports registered against a platform device. */static int __devexit serial8250_remove(struct device *dev){	int i;	for (i = 0; i < UART_NR; i++) {		struct uart_8250_port *up = &serial8250_ports[i];		if (up->port.dev == dev)			serial8250_unregister_port(i);	}	return 0;}static int serial8250_suspend(struct device *dev, u32 state, u32 level){	int i;	if (level != SUSPEND_DISABLE)		return 0;	for (i = 0; i < UART_NR; i++) {		struct uart_8250_port *up = &serial8250_ports[i];		if (up->port.type != PORT_UNKNOWN && up->port.dev == dev)			uart_suspend_port(&serial8250_reg, &up->port);	}	return 0;}static int serial8250_resume(struct device *dev, u32 level){	int i;	if (level != RESUME_ENABLE)		return 0;	for (i = 0; i < UART_NR; i++) {		struct uart_8250_port *up = &serial8250_ports[i];		if (up->port.type != PORT_UNKNOWN && up->port.dev == dev)			uart_resume_port(&serial8250_reg, &up->port);	}	return 0;}static struct device_driver serial8250_isa_driver = {	.name		= "serial8250",	.bus		= &platform_bus_type,	.probe		= serial8250_probe,	.remove		= __devexit_p(serial8250_remove),	.suspend	= serial8250_suspend,	.resume		= serial8250_resume,};/* * This "device" covers _all_ ISA 8250-compatible serial devices listed * in the table in include/asm/serial.h */static struct platform_device *serial8250_isa_devs;/* * serial8250_register_port and serial8250_unregister_port allows for * 16x50 serial ports to be configured at run-time, to support PCMCIA * modems and PCI multiport cards. */static DECLARE_MUTEX(serial_sem);/* *	Are the two ports equivalent? */static 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;}static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port){	int i;	/*	 * First, find a port entry which matches.	 */	for (i = 0; i < UART_NR; i++)		if (uart_match_port(&serial8250_ports[i].port, port))			return &serial8250_ports[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 < UART_NR; i++)		if (serial8250_ports[i].port.type == PORT_UNKNOWN &&		    serial8250_ports[i].port.iobase == 0)			return &serial8250_ports[i];	/*	 * That also failed.  Last resort is to find any entry which	 * doesn't have a real port associated with it.	 */	for (i = 0; i < UART_NR; i++)		if (serial8250_ports[i].port.type == PORT_UNKNOWN)			return &serial8250_ports[i];	return NULL;}/** *	uart_8250_register_port - register a serial port *	@port: serial port template *	@line: returned (on success) value of the line number * *	Configure the serial port specified by the request. If the *	port exists and is in use, it is hung up and unregistered *	first. * *	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 pointer to the  *	corresponding struct uart_8250_port is returned. */static struct uart_8250_port *uart_8250_register_port(struct uart_port *port, int *line){	struct uart_8250_port *uart;	int ret = -ENOSPC;	if (port->uartclk == 0)		return ERR_PTR(-EINVAL);	/* Avoid re-registering platform based ports if KGDB active */	if (port->line

⌨️ 快捷键说明

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