--- zzzz-none-000/linux-2.6.13.1/drivers/serial/8250.c 2005-09-10 02:42:58.000000000 +0000 +++ ohio-7170-487/linux-2.6.13.1/drivers/serial/8250.c 2007-01-17 17:06:05.000000000 +0000 @@ -46,6 +46,8 @@ #include "8250.h" +#define PRINTK printk +/*--- #define PRINTK prom_printf ---*/ /* * Configuration: * share_irqs - whether we pass SA_SHIRQ to request_irq(). This option @@ -174,6 +176,27 @@ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .flags = UART_CAP_FIFO, }, + [PORT_OHIO] = { + .name = "OHIO_UART", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, + .flags = UART_CAP_FIFO, + }, + [PORT_UR8] = { + .name = "UR8_UART", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, + .flags = UART_CAP_FIFO, + }, + [PORT_DAVINCI] = { + .name = "DAVINCI_UART", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00 | UART_FCR_DMA_SELECT, + .flags = UART_CAP_FIFO, + }, [PORT_CIRRUS] = { .name = "Cirrus", .fifo_size = 1, @@ -332,8 +355,8 @@ static inline void serial8250_clear_fifos(struct uart_8250_port *p) { if (p->capabilities & UART_CAP_FIFO) { - serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO | + serial_outp(p, UART_FCR, uart_config[p->port.type].fcr); + serial_outp(p, UART_FCR, uart_config[p->port.type].fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); serial_outp(p, UART_FCR, 0); } @@ -1210,10 +1233,16 @@ { unsigned int status = serial_inp(up, UART_LSR); + /*--- printk("status = %x...", status); ---*/ DEBUG_INTR("status = %x...", status); if (status & UART_LSR_DR) receive_chars(up, &status, regs); +#if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) + if (status & UART_LSR_BI) + receive_chars(up, &status, regs); +#endif /*--- #if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) ---*/ + check_modem_status(up); if (status & UART_LSR_THRE) transmit_chars(up); @@ -1240,6 +1269,7 @@ int pass_counter = 0, handled = 0; DEBUG_INTR("serial8250_interrupt(%d)...", irq); + /*--- printk("serial8250_interrupt(%d)...", irq); ---*/ spin_lock(&i->lock); @@ -1249,14 +1279,15 @@ unsigned int iir; up = list_entry(l, struct uart_8250_port, list); + /*--- printk("serial8250: base = 0x%x\n", up->port.membase); ---*/ + iir = serial_in(up, UART_IIR); - iir = serial_in(up, UART_IIR); if (!(iir & UART_IIR_NO_INT)) { spin_lock(&up->port.lock); serial8250_handle_port(up, regs); spin_unlock(&up->port.lock); - handled = 1; + handled = IRQ_HANDLED; end = NULL; } else if (end == NULL) @@ -1274,9 +1305,14 @@ spin_unlock(&i->lock); + /*--- printk("end.\n"); ---*/ DEBUG_INTR("end.\n"); +#ifdef CONFIG_ARCH_DAVINCI + return IRQ_RETVAL(1); /*--- der UART generiert beim Schreiben auf das IER einen Interrupt ---*/ +#else return IRQ_RETVAL(handled); +#endif } /* @@ -1309,23 +1345,29 @@ spin_lock_irq(&i->lock); - if (i->head) { - list_add(&up->list, i->head); + /*--- printk("[serial_link_irq_chain] start\n"); ---*/ + + if (i->head) { + /*--- printk("[serial_link_irq_chain] we are not head of irq list \n"); ---*/ + list_add(&up->list, i->head); spin_unlock_irq(&i->lock); ret = 0; } else { INIT_LIST_HEAD(&up->list); - i->head = &up->list; + /*--- printk("[serial_link_irq_chain] we are the head of irq list, request irq\n"); ---*/ + i->head = &up->list; spin_unlock_irq(&i->lock); - ret = request_irq(up->port.irq, serial8250_interrupt, - irq_flags, "serial", i); - if (ret < 0) + ret = request_irq(up->port.irq, serial8250_interrupt, irq_flags, "serial", i); + if (ret < 0) { + printk("\n",ret); serial_do_unlink(i, up); + } } - return ret; + /*--- printk("[serial_link_irq_chain] done ret=%d\n", ret); ---*/ + return ret; } static void serial_unlink_irq_chain(struct uart_8250_port *up) @@ -1380,10 +1422,13 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long flags; unsigned char status; unsigned int ret; + spin_lock_irqsave(&up->port.lock, flags); status = serial_in(up, UART_MSR); + spin_unlock_irqrestore(&up->port.lock, flags); ret = 0; if (status & UART_MSR_DCD) @@ -1414,7 +1459,6 @@ mcr |= UART_MCR_LOOP; mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; - serial_out(up, UART_MCR, mcr); } @@ -1436,9 +1480,8 @@ { struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned long flags; - unsigned char lsr, iir; - int retval; - + unsigned char lsr, iir; + int retval; up->capabilities = uart_config[up->port.type].flags; up->mcr = 0; @@ -1517,10 +1560,13 @@ up->timer.data = (unsigned long)up; mod_timer(&up->timer, jiffies + timeout); + /*--- printk("[serial8250_startup] virtual irq by timer\n"); ---*/ } else { + /*--- printk("[serial8250_startup] real irq %u\n", up->port.irq); ---*/ retval = serial_link_irq_chain(up); - if (retval) + if (retval) { return retval; + } } /* @@ -1532,12 +1578,13 @@ if (up->port.flags & UPF_FOURPORT) { if (!is_real_interrupt(up->port.irq)) up->port.mctrl |= TIOCM_OUT1; - } else + } else { /* * Most PC uarts need OUT2 raised to enable interrupts. */ - if (is_real_interrupt(up->port.irq)) + if (is_real_interrupt(up->port.irq)) up->port.mctrl |= TIOCM_OUT2; + } serial8250_set_mctrl(&up->port, up->port.mctrl); @@ -1685,15 +1732,20 @@ if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; - if (termios->c_cflag & PARENB) + if (termios->c_cflag & PARENB) { cval |= UART_LCR_PARITY; - if (!(termios->c_cflag & PARODD)) - cval |= UART_LCR_EPAR; + if (!(termios->c_cflag & PARODD)) + cval |= UART_LCR_EPAR; + } #ifdef CMSPAR if (termios->c_cflag & CMSPAR) cval |= UART_LCR_SPAR; #endif +#if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) + /*--- es wird kein autoconfig verwendet! ---*/ + up->capabilities = uart_config[up->port.type].flags; +#endif/*--- #if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) ---*/ /* * Ask the core to calculate the divisor for us. */ @@ -1706,7 +1758,7 @@ if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0) quot ++; - if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) { + if ((up->capabilities & UART_CAP_FIFO) && up->port.fifosize > 1) { if (baud < 2400) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; else @@ -1809,14 +1861,18 @@ serial_outp(up, UART_FCR, fcr); serial_outp(up, UART_LCR, cval); /* reset DLAB */ + up->lcr = cval; /* Save LCR */ if (up->port.type != PORT_16750) { if (fcr & UART_FCR_ENABLE_FIFO) { /* emulated UARTs (Lucent Venus 167x) need two steps */ - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + /*--- NOTE: Always clear FIFOs when enabling! ---*/ + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); } serial_outp(up, UART_FCR, fcr); /* set fcr */ } + + serial8250_set_mctrl(&up->port, up->port.mctrl); spin_unlock_irqrestore(&up->port.lock, flags); } @@ -2033,16 +2089,24 @@ static struct uart_8250_port serial8250_ports[UART_NR]; +/*------------------------------------------------------------------------------------------*\ + * call-tree bei ohio: + * + * static void __init ohio_serial_init(void); + * int __init early_serial_setup(struct uart_port *port); + * static void __init serial8250_isa_init_ports(void); + * +\*------------------------------------------------------------------------------------------*/ static void __init serial8250_isa_init_ports(void) { struct uart_8250_port *up; static int first = 1; int i; - if (!first) + if (!first) { return; + } first = 0; - for (i = 0; i < UART_NR; i++) { struct uart_8250_port *up = &serial8250_ports[i]; @@ -2087,6 +2151,7 @@ for (i = 0; i < UART_NR; i++) { struct uart_8250_port *up = &serial8250_ports[i]; + up->port.dev = dev; uart_add_one_port(drv, &up->port); } @@ -2179,7 +2244,7 @@ int bits = 8; int parity = 'n'; int flow = 'n'; - + int ret; /* * Check whether an invalid uart number has been specified, and * if so, search for the first available port that does have @@ -2188,13 +2253,15 @@ if (co->index >= UART_NR) co->index = 0; port = &serial8250_ports[co->index].port; - if (!port->iobase && !port->membase) + if (!port->iobase && !port->membase) { return -ENODEV; - - if (options) + } + if (options) { uart_parse_options(options, &baud, &parity, &bits, &flow); + } - return uart_set_options(port, co, baud, parity, bits, flow); + ret = uart_set_options(port, co, baud, parity, bits, flow); + return ret; } static struct uart_driver serial8250_reg; @@ -2210,8 +2277,8 @@ static int __init serial8250_console_init(void) { - serial8250_isa_init_ports(); - register_console(&serial8250_console); + serial8250_isa_init_ports(); + register_console(&serial8250_console); return 0; } console_initcall(serial8250_console_init); @@ -2236,8 +2303,9 @@ int line; line = find_port(port); - if (line < 0) + if (line < 0) { return -ENODEV; + } add_preferred_console("ttyS", line, options); printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n", @@ -2258,23 +2326,27 @@ static struct uart_driver serial8250_reg = { .owner = THIS_MODULE, - .driver_name = "serial", + .driver_name = "serial", .devfs_name = "tts/", .dev_name = "ttyS", .major = TTY_MAJOR, .minor = 64, - .nr = UART_NR, + .nr = UART_NR, .cons = SERIAL8250_CONSOLE, }; +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ int __init early_serial_setup(struct uart_port *port) { - if (port->line >= ARRAY_SIZE(serial8250_ports)) + 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; } @@ -2460,13 +2532,17 @@ struct uart_8250_port *uart; int ret = -ENOSPC; - if (port->uartclk == 0) + + if (port->uartclk == 0) { return -EINVAL; + } down(&serial_sem); + printk("[serial8250_register_port]\n"); uart = serial8250_find_match_or_unused(port); if (uart) { + printk("[serial8250_register_port] set port fifosize %x\n", port->fifosize); uart_remove_one_port(&serial8250_reg, &uart->port); uart->port.iobase = port->iobase; @@ -2487,6 +2563,7 @@ } up(&serial_sem); + return ret; } EXPORT_SYMBOL(serial8250_register_port); @@ -2516,13 +2593,15 @@ } EXPORT_SYMBOL(serial8250_unregister_port); -static int __init serial8250_init(void) +#if !defined(CONFIG_MIPS_OHIO) && !defined(CONFIG_MIPS_AR7) && !defined(CONFIG_ARCH_DAVINCI) && !defined(CONFIG_MIPS_UR8) +static +#endif /*--- #if !defined(CONFIG_MIPS_OHIO) && !defined(CONFIG_MIPS_AR7) && !defined(CONFIG_ARCH_DAVINCI) && !defined(CONFIG_MIPS_UR8) ---*/ +int __init serial8250_init(void) { int ret, i; - printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ " - "%d ports, IRQ sharing %sabled\n", (int) UART_NR, - share_irqs ? "en" : "dis"); + PRINTK(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ " "%d ports, IRQ sharing %sabled\n", + (int) UART_NR, share_irqs ? "en" : "dis"); for (i = 0; i < NR_IRQS; i++) spin_lock_init(&irq_lists[i].lock); @@ -2531,8 +2610,7 @@ if (ret) goto out; - serial8250_isa_devs = platform_device_register_simple("serial8250", - -1, NULL, 0); + serial8250_isa_devs = platform_device_register_simple("serial8250", -1, NULL, 0); if (IS_ERR(serial8250_isa_devs)) { ret = PTR_ERR(serial8250_isa_devs); goto unreg; @@ -2541,8 +2619,9 @@ serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev); ret = driver_register(&serial8250_isa_driver); - if (ret == 0) + if (ret == 0) { goto out; + } platform_device_unregister(serial8250_isa_devs); unreg: @@ -2587,81 +2666,3 @@ #endif MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); -/** - * 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 necessary 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. - * - * Note: this function is deprecated - use serial8250_register_port - * instead. - */ -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 | UPF_BOOT_AUTOCONF; - port.mapbase = req->iomap_base; - port.dev = NULL; - - if (share_irqs) - port.flags |= UPF_SHARE_IRQ; - - if (HIGH_BITS_OFFSET) - port.iobase |= (long) 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. This should be 115200 (*16) - * and should not depend on the architecture's BASE_BAUD definition. - * However, since this API will be deprecated, it's probably a - * better idea to convert the drivers to use the new API - * (serial8250_register_port and serial8250_unregister_port). - */ - if (port.uartclk == 0) { - printk(KERN_WARNING - "Serial: registering port at [%08x,%08lx,%p] irq %d with zero baud_base\n", - port.iobase, port.mapbase, port.membase, port.irq); - printk(KERN_WARNING "Serial: see %s:%d for more information\n", - __FILE__, __LINE__); - dump_stack(); - - /* - * Fix it up for now, but this is only a temporary measure. - */ - port.uartclk = BASE_BAUD * 16; - } - - return serial8250_register_port(&port); -} -EXPORT_SYMBOL(register_serial); - -/** - * unregister_serial - remove a 16x50 serial port at runtime - * @line: serial line number - * - * Remove one serial port. This may not be called from interrupt - * context. We hand the port back to our local PM control. - * - * Note: this function is deprecated - use serial8250_unregister_port - * instead. - */ -void unregister_serial(int line) -{ - serial8250_unregister_port(line); -} -EXPORT_SYMBOL(unregister_serial);