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

📄 8250.c

📁 IXP425 平台下嵌入式LINUX的串口的驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
			 */			serial_outp(port, UART_LCR, 0xBF);			serial_outp(port, UART_EFR, 0);			/*			 * For a XR16C850, we need to set the trigger levels			 */			if (port->type == PORT_16850) {				unsigned char fctr;				fctr = serial_inp(port, UART_FCTR) &					 ~(UART_FCTR_RX | UART_FCTR_TX);				serial_outp(port, UART_FCTR, fctr |						UART_FCTR_TRGD |						UART_FCTR_RX);				serial_outp(port, UART_TRG, UART_TRG_96);				serial_outp(port, UART_FCTR, fctr |						UART_FCTR_TRGD |						UART_FCTR_TX);				serial_outp(port, UART_TRG, UART_TRG_96);			}			serial_outp(port, UART_LCR, 0);		}		if (port->type == PORT_16750) {			/* Wake up UART */			serial_outp(port, UART_IER, 0);		}	}}/* * Resource handling.  This is complicated by the fact that resources * depend on the port type.  Maybe we should be claiming the standard * 8250 ports, and then trying to get other resources as necessary? */static intserial8250_request_std_resource(struct uart_port *port, struct resource **res){	unsigned int size = 8 << port->regshift;	int ret = 0;	switch (port->iotype) {	case SERIAL_IO_MEM:		if (port->mapbase) {			*res = request_mem_region(port->mapbase, size, "serial");			if (!*res)				ret = -EBUSY;		}		break;	case SERIAL_IO_HUB6:	case SERIAL_IO_PORT:		*res = request_region(port->iobase, size, "serial");		if (!*res)			ret = -EBUSY;		break;	}	return ret;}static intserial8250_request_rsa_resource(struct uart_port *port, struct resource **res){	unsigned long start, size = 8 << port->regshift;	int ret = 0;	switch (port->iotype) {	case SERIAL_IO_MEM:		if (port->mapbase) {			start = port->mapbase;			start += UART_RSA_BASE << port->regshift;			*res = request_mem_region(start, size, "serial-rsa");			if (!*res)				ret = -EBUSY;		}		break;	case SERIAL_IO_HUB6:	case SERIAL_IO_PORT:		start = port->iobase;		start += UART_RSA_BASE << 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){	unsigned long start, offset = 0, size = 0;	if (port->type == PORT_RSA) {		offset = UART_RSA_BASE << port->regshift;		size = 8;	}	offset <<= port->regshift;	size <<= port->regshift;	switch (port->iotype) {	case SERIAL_IO_MEM:		if (port->mapbase) {			/*			 * Unmap the area.			 */			iounmap(port->membase);			port->membase = NULL;			start = port->mapbase;			if (size)				release_mem_region(start + offset, size);			release_mem_region(start, 8 << port->regshift);		}		break;	case SERIAL_IO_HUB6:	case SERIAL_IO_PORT:		start = port->iobase;		if (size)			release_region(start + offset, size);		release_region(start + offset, 8 << port->regshift);		break;	default:		break;	}}static int serial8250_request_port(struct uart_port *port){	struct resource *res = NULL, *res_rsa = NULL;	int ret = -EBUSY;	if (port->type == PORT_RSA) {		ret = serial8250_request_rsa_resource(port, &res_rsa);		if (ret)			return ret;	}	ret = serial8250_request_std_resource(port, &res);	/*	 * If we have a mapbase, then request that as well.	 */	if (res != NULL && port->iotype == SERIAL_IO_MEM &&	    port->mapbase) {		int size = res->end - res->start + 1;		port->membase = ioremap(port->mapbase, size);		if (!port->membase)			ret = -ENOMEM;	}	if (ret) {		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 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 (port->flags & ASYNC_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(port, &res_std);	if (ret)		return;	ret = serial8250_request_rsa_resource(port, &res_rsa);	if (ret)		probeflags &= ~PROBE_RSA;	if (flags & UART_CONFIG_TYPE)		autoconfig(port, probeflags);	if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)		autoconfig_irq(port);	/*	 * If the port wasn't an RSA port, release the resource.	 */	if (port->type != PORT_RSA && res_rsa)		release_resource(res_rsa);	if (port->type == PORT_UNKNOWN)		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 >= PORT_MAX_8250)		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,	change_speed:	serial8250_change_speed,	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_port serial8250_ports[UART_NR];static void __init serial8250_isa_init_ports(void){	static int first = 1;	int i;	if (!first)		return;	first = 0;	for (i = 0; i < ARRAY_SIZE(old_serial_port); i++) {		serial8250_ports[i].iobase  = old_serial_port[i].port;		serial8250_ports[i].irq     = irq_cannonicalize(old_serial_port[i].irq);		serial8250_ports[i].uartclk = old_serial_port[i].base_baud * 16;		serial8250_ports[i].flags   = old_serial_port[i].flags;		serial8250_ports[i].ops     = &serial8250_pops;	}}#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_port *port){	unsigned int status, tmout = 1000000;	do {		status = serial_in(port, UART_LSR);		if (status & UART_LSR_BI)			lsr_break_flag = UART_LSR_BI;		if (--tmout == 0)			break;	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);	/* Wait for flow control if necessary */	if (port->flags & ASYNC_CONS_FLOW) {		tmout = 1000000;		while (--tmout &&		       ((serial_in(port, UART_MSR) & UART_MSR_CTS) == 0));	}}/* *	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 void serial8250_console_write(struct console *co, const char *s, u_int count){	struct uart_port *port = serial8250_ports + co->index;	unsigned int ier;	int i;	/*	 *	First save the UER then disable the interrupts	 */	ier = serial_in(port, UART_IER);	serial_out(port, UART_IER, 0);	/*	 *	Now, do each character	 */	for (i = 0; i < count; i++, s++) {		wait_for_xmitr(port);		/*		 *	Send the character out.		 *	If a LF, also do CR...		 */		serial_out(port, UART_TX, *s);		if (*s == 10) {			wait_for_xmitr(port);			serial_out(port, UART_TX, 13);		}	}	/*	 *	Finally, wait for transmitter to become empty	 *	and restore the IER	 */	wait_for_xmitr(port);	serial_out(port, UART_IER, ier);}static kdev_t serial8250_console_device(struct console *co){	return MKDEV(TTY_MAJOR, 64 + co->index);}static int __init 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.	 */	port = uart_get_console(serial8250_ports, UART_NR, co);	if (options)		uart_parse_options(options, &baud, &parity, &bits, &flow);	return uart_set_options(port, co, baud, parity, bits, flow);}static struct console serial8250_console = {	name:		"ttyS",	write:		serial8250_console_write,	device:		serial8250_console_device,	setup:		serial8250_console_setup,	flags:		CON_PRINTBUFFER,	index:		-1,};void __init serial8250_console_init(void){	serial8250_isa_init_ports();	register_console(&serial8250_console);}#define SERIAL8250_CONSOLE	&serial8250_console#else#define SERIAL8250_CONSOLE	NULL#endifstatic struct uart_driver serial8250_reg = {	owner:			THIS_MODULE,#ifdef CONFIG_DEVFS_FS	normal_name:		"tts/%d",	callout_name:		"cua/%d",#else	normal_name:		"ttyS",	callout_name:		"cua",#endif	normal_major:		TTY_MAJOR,	callout_major:		TTYAUX_MAJOR,	normal_driver:		&normal,	callout_driver:		&callout,	table:			serial8250_table,	termios:		serial8250_termios,	termios_locked:		serial8250_termios_locked,	minor:			64,	nr:			ARRAY_SIZE(old_serial_port),	port:			serial8250_ports,	cons:			SERIAL8250_CONSOLE,};/* * register_serial and unregister_serial allows for 16x50 serial ports to be * configured at run-time, to support PCMCIA modems. */ /** *	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 neccessary 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){	struct uart_port port;	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 | ASYNC_BOOT_AUTOCONF;	if (HIGH_BITS_OFFSET)		port.iobase |= 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);}void unregister_serial(int line){	uart_unregister_port(&serial8250_reg, line);}static int __init serial8250_init(void){	serial8250_isa_init_ports();	return uart_register_driver(&serial8250_reg);}static void __exit serial8250_exit(void){	uart_unregister_driver(&serial8250_reg);}module_init(serial8250_init);module_exit(serial8250_exit);EXPORT_SYMBOL(register_serial);EXPORT_SYMBOL(unregister_serial);MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");

⌨️ 快捷键说明

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