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 + -
显示快捷键?