CTC++ Coverage Report - Execution Profile    #616/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/serial/8250_early.c
Instrumentation mode: function-decision-multicondition
TER: 7 % ( 6/ 81)

Start/ End/    
True False - Line Source

  1 /*
  2  * Early serial console for 8250/16550 devices
  3  *
  4  * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
  5  *   Bjorn Helgaas <bjorn.helgaas@hp.com>
  6  *
  7  * This program is free software; you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License version 2 as
  9  * published by the Free Software Foundation.
  10  *
  11  * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King,
  12  * and on early_printk.c by Andi Kleen.
  13  *
  14  * This is for use before the serial driver has initialized, in
  15  * particular, before the UARTs have been discovered and named.
  16  * Instead of specifying the console device as, e.g., "ttyS0",
  17  * we locate the device directly by its MMIO or I/O port address.
  18  *
  19  * The user can specify the device directly, e.g.,
  20  *   console=uart,io,0x3f8,9600n8
  21  *   console=uart,mmio,0xff5e0000,115200n8
  22  * or platform code can call early_uart_console_init() to set
  23  * the early UART device.
  24  *
  25  * After the normal serial driver starts, we try to locate the
  26  * matching ttyS device and start a console there.
  27  */
  28 
  29 #include <linux/tty.h>
  30 #include <linux/init.h>
  31 #include <linux/console.h>
  32 #include <linux/serial_core.h>
  33 #include <linux/serial_reg.h>
  34 #include <linux/serial.h>
  35 #include <asm/io.h>
  36 #include <asm/serial.h>
  37 
  38 struct early_uart_device {
  39    struct uart_port port;
  40    char options[16];      /* e.g., 115200n8 */
  41    unsigned int baud;
  42 };
  43 
  44 static struct early_uart_device early_device __initdata;
  45 static int early_uart_registered __initdata;
  46 
 
- 47 static unsigned int __init serial_in(struct uart_port *port, int offset)
  48 {
- 49    if (port->iotype == UPIO_MEM)
 - 50       return readb(port->membase + offset);
    51    else
 - 52       return inb(port->iobase + offset);
  53 }
  54 
 
- 55 static void __init serial_out(struct uart_port *port, int offset, int value)
  56 {
- 57    if (port->iotype == UPIO_MEM)
  58       writeb(value, port->membase + offset);
    59    else
  60       outb(value, port->iobase + offset);
  61 }
  62 
  63 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
  64 
 
- 65 static void __init wait_for_xmitr(struct uart_port *port)
  66 {
  67    unsigned int status;
  68 
- 69    for (;;) {
  70       status = serial_in(port, UART_LSR);
- 71       if ((status & BOTH_EMPTY) == BOTH_EMPTY)
 - 72          return;
  73       cpu_relax();
  74    }
  75 }
  76 
 
- 77 static void __init putc(struct uart_port *port, unsigned char c)
  78 {
  79    wait_for_xmitr(port);
  80    serial_out(port, UART_TX, c);
  81 }
  82 
 
- 83 static void __init early_uart_write(struct console *console, const char *s, unsigned int count)
  84 {
  85    struct uart_port *port = &early_device.port;
  86    unsigned int ier;
  87 
  88    /* Save the IER and disable interrupts */
  89    ier = serial_in(port, UART_IER);
  90    serial_out(port, UART_IER, 0);
  91 
- 92    while (*s && count-- > 0) {
 - 92   T && T
 - 92   T && F
 - 92   F && _
  93       putc(port, *s);
- 94       if (*s == '\n')
  95          putc(port, '\r');
  96       s++;
  97    }
  98 
  99    /* Wait for transmitter to become empty and restore the IER */
  100    wait_for_xmitr(port);
  101    serial_out(port, UART_IER, ier);
  102 }
  103 
 
- 104 static unsigned int __init probe_baud(struct uart_port *port)
  105 {
  106    unsigned char lcr, dll, dlm;
  107    unsigned int quot;
  108 
  109    lcr = serial_in(port, UART_LCR);
  110    serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
  111    dll = serial_in(port, UART_DLL);
  112    dlm = serial_in(port, UART_DLM);
  113    serial_out(port, UART_LCR, lcr);
  114 
  115    quot = (dlm << 8) | dll;
 - 116    return (port->uartclk / 16) / quot;
  117 }
  118 
 
- 119 static void __init init_port(struct early_uart_device *device)
  120 {
  121    struct uart_port *port = &device->port;
  122    unsigned int divisor;
  123    unsigned char c;
  124 
  125    serial_out(port, UART_LCR, 0x3);   /* 8n1 */
  126    serial_out(port, UART_IER, 0);      /* no interrupt */
  127    serial_out(port, UART_FCR, 0);      /* no fifo */
  128    serial_out(port, UART_MCR, 0x3);   /* DTR + RTS */
  129 
  130    divisor = port->uartclk / (16 * device->baud);
  131    c = serial_in(port, UART_LCR);
  132    serial_out(port, UART_LCR, c | UART_LCR_DLAB);
  133    serial_out(port, UART_DLL, divisor & 0xff);
  134    serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
  135    serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
  136 }
  137 
 
- 138 static int __init parse_options(struct early_uart_device *device, char *options)
  139 {
  140    struct uart_port *port = &device->port;
  141    int mapsize = 64;
  142    int mmio, length;
  143 
- 144    if (!options)
 - 145       return -ENODEV;
  146 
  147    port->uartclk = BASE_BAUD * 16;
- 148    if (!strncmp(options, "mmio,", 5)) {
  149       port->iotype = UPIO_MEM;
  150       port->mapbase = simple_strtoul(options + 5, &options, 0);
  151       port->membase = ioremap(port->mapbase, mapsize);
- 152       if (!port->membase) {
  153          printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
  154             __FUNCTION__, port->mapbase);
 - 155          return -ENOMEM;
  156       }
  157       mmio = 1;
- 158    } else if (!strncmp(options, "io,", 3)) {
  159       port->iotype = UPIO_PORT;
  160       port->iobase = simple_strtoul(options + 3, &options, 0);
  161       mmio = 0;
    162    } else
 - 163       return -EINVAL;
  164 
- 165    if ((options = strchr(options, ','))) {
  166       options++;
  167       device->baud = simple_strtoul(options, NULL, 0);
  168       length = min(strcspn(options, " "), sizeof(device->options));
  169       strncpy(device->options, options, length);
    170    } else {
  171       device->baud = probe_baud(port);
  172       snprintf(device->options, sizeof(device->options), "%u",
  173          device->baud);
  174    }
  175 
  176    printk(KERN_INFO "Early serial console at %s 0x%lx (options '%s')\n",
    177       mmio ? "MMIO" : "I/O port",
- 177 ternary-?: mmio
    178       mmio ? port->mapbase : (unsigned long) port->iobase,
- 178 ternary-?: mmio
  179       device->options);
 - 180    return 0;
  181 }
  182 
 
- 183 static int __init early_uart_setup(struct console *console, char *options)
  184 {
  185    struct early_uart_device *device = &early_device;
  186    int err;
  187 
- 188    if (device->port.membase || device->port.iobase)
 - 188   T || _
 - 188   F || T
 - 188   F || F
 - 189       return 0;
  190 
- 191    if ((err = parse_options(device, options)) < 0)
 - 192       return err;
  193 
  194    init_port(device);
 - 195    return 0;
  196 }
  197 
  198 static struct console early_uart_console __initdata = {
  199    .name   = "uart",
  200    .write   = early_uart_write,
  201    .setup   = early_uart_setup,
  202    .flags   = CON_PRINTBUFFER,
  203    .index   = -1,
  204 };
  205 
 
  206 static int __init early_uart_console_init(void)
  207 {
- 208    if (!early_uart_registered) {
  209       register_console(&early_uart_console);
  210       early_uart_registered = 1;
  211    }
   212    return 0;
  213 }
  214 console_initcall(early_uart_console_init);
  215 
 
- 216 int __init early_serial_console_init(char *cmdline)
  217 {
  218    char *options;
  219    int err;
  220 
  221    options = strstr(cmdline, "console=uart,");
- 222    if (!options)
 - 223       return -ENODEV;
  224 
  225    options = strchr(cmdline, ',') + 1;
- 226    if ((err = early_uart_setup(NULL, options)) < 0)
 - 227       return err;
 - 228    return early_uart_console_init();
  229 }
  230 
 
  231 static int __init early_uart_console_switch(void)
  232 {
  233    struct early_uart_device *device = &early_device;
  234    struct uart_port *port = &device->port;
  235    int mmio, line;
  236 
- 237    if (!(early_uart_console.flags & CON_ENABLED))
   238       return 0;
  239 
  240    /* Try to start the normal driver on a matching line.  */
  241    mmio = (port->iotype == UPIO_MEM);
  242    line = serial8250_start_console(port, device->options);
- 243    if (line < 0)
  244       printk("No ttyS device at %s 0x%lx for console\n",
    245          mmio ? "MMIO" : "I/O port",
- 245   ternary-?: mmio
    246          mmio ? port->mapbase :
- 246   ternary-?: mmio
  247              (unsigned long) port->iobase);
  248 
  249    unregister_console(&early_uart_console);
- 250    if (mmio)
  251       iounmap(port->membase);
  252 
 - 253    return 0;
  254 }
  255 late_initcall(early_uart_console_switch);
***TER 7% (6/81) of SOURCE FILE 8250_early.c

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last | Top