📄 8250.c
字号:
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 + -