mux.c

来自「linux 内核源代码」· C语言 代码 · 共 635 行 · 第 1/2 页

C
635
字号
 * Return a pointer to a string constant describing the * specified port. */static const char *mux_type(struct uart_port *port){	return "Mux";}/** * mux_release_port - Release memory and IO regions. * @port: Ptr to the uart_port. *  * Release any memory and IO region resources currently in use by * the port. */static void mux_release_port(struct uart_port *port){}/** * mux_request_port - Request memory and IO regions. * @port: Ptr to the uart_port. * * Request any memory and IO region resources required by the port. * If any fail, no resources should be registered when this function * returns, and it should return -EBUSY on failure. */static int mux_request_port(struct uart_port *port){	return 0;}/** * mux_config_port - Perform port autoconfiguration. * @port: Ptr to the uart_port. * @type: Bitmask of required configurations. * * Perform any autoconfiguration steps for the port.  This function is * called if the UPF_BOOT_AUTOCONF flag is specified for the port. * [Note: This is required for now because of a bug in the Serial core. *  rmk has already submitted a patch to linus, should be available for *  2.5.47.] */static void mux_config_port(struct uart_port *port, int type){	port->type = PORT_MUX;}/** * mux_verify_port - Verify the port information. * @port: Ptr to the uart_port. * @ser: Ptr to the serial information. * * Verify the new serial port information contained within serinfo is * suitable for this port type. */static int mux_verify_port(struct uart_port *port, struct serial_struct *ser){	if(port->membase == NULL)		return -EINVAL;	return 0;}/** * mux_drv_poll - Mux poll function. * @unused: Unused variable * * This function periodically polls the Serial MUX to check for new data. */static void mux_poll(unsigned long unused){  	int i;	for(i = 0; i < port_cnt; ++i) {		if(!mux_ports[i].enabled)			continue;		mux_read(&mux_ports[i].port);		mux_write(&mux_ports[i].port);	}	mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);}#ifdef CONFIG_SERIAL_MUX_CONSOLEstatic void mux_console_write(struct console *co, const char *s, unsigned count){	/* Wait until the FIFO drains. */	while(UART_GET_FIFO_CNT(&mux_ports[0].port))		udelay(1);	while(count--) {		if(*s == '\n') {			UART_PUT_CHAR(&mux_ports[0].port, '\r');		}		UART_PUT_CHAR(&mux_ports[0].port, *s++);	}}static int mux_console_setup(struct console *co, char *options){        return 0;}struct tty_driver *mux_console_device(struct console *co, int *index){        *index = co->index;	return mux_driver.tty_driver;}static struct console mux_console = {	.name =		"ttyB",	.write =	mux_console_write,	.device =	mux_console_device,	.setup =	mux_console_setup,	.flags =	CON_ENABLED | CON_PRINTBUFFER,	.index =	0,};#define MUX_CONSOLE	&mux_console#else#define MUX_CONSOLE	NULL#endifstatic struct uart_ops mux_pops = {	.tx_empty =		mux_tx_empty,	.set_mctrl =		mux_set_mctrl,	.get_mctrl =		mux_get_mctrl,	.stop_tx =		mux_stop_tx,	.start_tx =		mux_start_tx,	.stop_rx =		mux_stop_rx,	.enable_ms =		mux_enable_ms,	.break_ctl =		mux_break_ctl,	.startup =		mux_startup,	.shutdown =		mux_shutdown,	.set_termios =		mux_set_termios,	.type =			mux_type,	.release_port =		mux_release_port,	.request_port =		mux_request_port,	.config_port =		mux_config_port,	.verify_port =		mux_verify_port,};/** * mux_probe - Determine if the Serial Mux should claim this device. * @dev: The parisc device. * * Deterimine if the Serial Mux should claim this chip (return 0) * or not (return 1). */static int __init mux_probe(struct parisc_device *dev){	int i, status;	int port_count = get_mux_port_count(dev);	printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.6\n", port_count);	dev_set_drvdata(&dev->dev, (void *)(long)port_count);	request_mem_region(dev->hpa.start + MUX_OFFSET,                           port_count * MUX_LINE_OFFSET, "Mux");	if(!port_cnt) {		mux_driver.cons = MUX_CONSOLE;		status = uart_register_driver(&mux_driver);		if(status) {			printk(KERN_ERR "Serial mux: Unable to register driver.\n");			return 1;		}	}	for(i = 0; i < port_count; ++i, ++port_cnt) {		struct uart_port *port = &mux_ports[port_cnt].port;		port->iobase	= 0;		port->mapbase	= dev->hpa.start + MUX_OFFSET +						(i * MUX_LINE_OFFSET);		port->membase	= ioremap_nocache(port->mapbase, MUX_LINE_OFFSET);		port->iotype	= UPIO_MEM;		port->type	= PORT_MUX;		port->irq	= NO_IRQ;		port->uartclk	= 0;		port->fifosize	= MUX_FIFO_SIZE;		port->ops	= &mux_pops;		port->flags	= UPF_BOOT_AUTOCONF;		port->line	= port_cnt;		/* The port->timeout needs to match what is present in		 * uart_wait_until_sent in serial_core.c.  Otherwise		 * the time spent in msleep_interruptable will be very		 * long, causing the appearance of a console hang.		 */		port->timeout   = HZ / 50;		spin_lock_init(&port->lock);		status = uart_add_one_port(&mux_driver, port);		BUG_ON(status);	}	return 0;}static int __devexit mux_remove(struct parisc_device *dev){	int i, j;	int port_count = (long)dev_get_drvdata(&dev->dev);	/* Find Port 0 for this card in the mux_ports list. */	for(i = 0; i < port_cnt; ++i) {		if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET)			break;	}	BUG_ON(i + port_count > port_cnt);	/* Release the resources associated with each port on the device. */	for(j = 0; j < port_count; ++j, ++i) {		struct uart_port *port = &mux_ports[i].port;		uart_remove_one_port(&mux_driver, port);		if(port->membase)			iounmap(port->membase);	}	release_mem_region(dev->hpa.start + MUX_OFFSET, port_count * MUX_LINE_OFFSET);	return 0;}/* Hack.  This idea was taken from the 8250_gsc.c on how to properly order * the serial port detection in the proper order.   The idea is we always * want the builtin mux to be detected before addin mux cards, so we * specifically probe for the builtin mux cards first. * * This table only contains the parisc_device_id of known builtin mux * devices.  All other mux cards will be detected by the generic mux_tbl. */static struct parisc_device_id builtin_mux_tbl[] = {	{ HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x15, 0x0000D }, /* All K-class */	{ HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x44, 0x0000D }, /* E35, E45, and E55 */	{ 0, }};static struct parisc_device_id mux_tbl[] = {	{ HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D },	{ 0, }};MODULE_DEVICE_TABLE(parisc, builtin_mux_tbl);MODULE_DEVICE_TABLE(parisc, mux_tbl);static struct parisc_driver builtin_serial_mux_driver = {	.name =		"builtin_serial_mux",	.id_table =	builtin_mux_tbl,	.probe =	mux_probe,	.remove =       __devexit_p(mux_remove),};static struct parisc_driver serial_mux_driver = {	.name =		"serial_mux",	.id_table =	mux_tbl,	.probe =	mux_probe,	.remove =       __devexit_p(mux_remove),};/** * mux_init - Serial MUX initalization procedure. * * Register the Serial MUX driver. */static int __init mux_init(void){	register_parisc_driver(&builtin_serial_mux_driver);	register_parisc_driver(&serial_mux_driver);	if(port_cnt > 0) {		/* Start the Mux timer */		init_timer(&mux_timer);		mux_timer.function = mux_poll;		mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);#ifdef CONFIG_SERIAL_MUX_CONSOLE	        register_console(&mux_console);#endif	}	return 0;}/** * mux_exit - Serial MUX cleanup procedure. * * Unregister the Serial MUX driver from the tty layer. */static void __exit mux_exit(void){	/* Delete the Mux timer. */	if(port_cnt > 0) {		del_timer(&mux_timer);#ifdef CONFIG_SERIAL_MUX_CONSOLE		unregister_console(&mux_console);#endif	}	unregister_parisc_driver(&builtin_serial_mux_driver);	unregister_parisc_driver(&serial_mux_driver);	uart_unregister_driver(&mux_driver);}module_init(mux_init);module_exit(mux_exit);MODULE_AUTHOR("Ryan Bradetich");MODULE_DESCRIPTION("Serial MUX driver");MODULE_LICENSE("GPL");MODULE_ALIAS_CHARDEV_MAJOR(MUX_MAJOR);

⌨️ 快捷键说明

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