ia64/xen-unstable

changeset 5776:64f26eed8d47

Allow arch-specific defaults to be specified for ns16550
uart configuration. Based on a patch from Hollis Blanchard
at IBM.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Jul 14 09:05:22 2005 +0000 (2005-07-14)
parents 9b77ba29108d
children 1fb47826d767
files xen/arch/ia64/pcdp.c xen/arch/ia64/xensetup.c xen/arch/x86/setup.c xen/drivers/char/ns16550.c xen/include/xen/serial.h
line diff
     1.1 --- a/xen/arch/ia64/pcdp.c	Thu Jul 14 08:00:55 2005 +0000
     1.2 +++ b/xen/arch/ia64/pcdp.c	Thu Jul 14 09:05:22 2005 +0000
     1.3 @@ -24,11 +24,11 @@ static int __init
     1.4  setup_serial_console(struct pcdp_uart *uart)
     1.5  {
     1.6  #ifdef XEN
     1.7 -	extern char opt_com1[1];
     1.8 -	if (opt_com1[0]) return 0;
     1.9 -	sprintf(&opt_com1[0], "%lu,%dn1,0x%lx,9",
    1.10 -		uart->baud, uart->bits ? uart->bits : 8,
    1.11 -		uart->addr.address);
    1.12 +	extern struct ns16550_defaults ns16550_com1;
    1.13 +	ns16550_com1.baud = uart->baud;
    1.14 +	ns16550_com1.io_base = uart->addr.address;
    1.15 +	if (uart->bits)
    1.16 +		ns16550_com1.data_bits = uart->bits;
    1.17  	return 0;
    1.18  #else
    1.19  #ifdef CONFIG_SERIAL_8250_CONSOLE
     2.1 --- a/xen/arch/ia64/xensetup.c	Thu Jul 14 08:00:55 2005 +0000
     2.2 +++ b/xen/arch/ia64/xensetup.c	Thu Jul 14 09:05:22 2005 +0000
     2.3 @@ -131,6 +131,12 @@ void early_cmdline_parse(char **cmdline_
     2.4      return;
     2.5  }
     2.6  
     2.7 +struct ns16550_defaults ns16550_com1 = {
     2.8 +    .data_bits = 8,
     2.9 +    .parity    = 'n',
    2.10 +    .stop_bits = 1
    2.11 +};
    2.12 +
    2.13  void start_kernel(void)
    2.14  {
    2.15      unsigned char *cmdline;
    2.16 @@ -153,7 +159,7 @@ void start_kernel(void)
    2.17  
    2.18      /* We initialise the serial devices very early so we can get debugging. */
    2.19      if (running_on_sim) hpsim_serial_init();
    2.20 -    else ns16550_init();
    2.21 +    else ns16550_init(0, &ns16550_com1);
    2.22      serial_init_preirq();
    2.23  
    2.24      init_console();
     3.1 --- a/xen/arch/x86/setup.c	Thu Jul 14 08:00:55 2005 +0000
     3.2 +++ b/xen/arch/x86/setup.c	Thu Jul 14 09:05:22 2005 +0000
     3.3 @@ -247,6 +247,11 @@ void __init __start_xen(multiboot_info_t
     3.4      unsigned long initial_images_start, initial_images_end;
     3.5      struct e820entry e820_raw[E820MAX];
     3.6      int i, e820_raw_nr = 0, bytes = 0;
     3.7 +    struct ns16550_defaults ns16550 = {
     3.8 +        .data_bits = 8,
     3.9 +        .parity    = 'n',
    3.10 +        .stop_bits = 1
    3.11 +    };
    3.12  
    3.13      /* Parse the command-line options. */
    3.14      if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) )
    3.15 @@ -259,7 +264,12 @@ void __init __start_xen(multiboot_info_t
    3.16      smp_prepare_boot_cpu();
    3.17  
    3.18      /* We initialise the serial devices very early so we can get debugging. */
    3.19 -    ns16550_init();
    3.20 +    ns16550.io_base = 0x3f8;
    3.21 +    ns16550.irq     = 4;
    3.22 +    ns16550_init(0, &ns16550);
    3.23 +    ns16550.io_base = 0x2f8;
    3.24 +    ns16550.irq     = 3;
    3.25 +    ns16550_init(1, &ns16550);
    3.26      serial_init_preirq();
    3.27  
    3.28      init_console();
     4.1 --- a/xen/drivers/char/ns16550.c	Thu Jul 14 08:00:55 2005 +0000
     4.2 +++ b/xen/drivers/char/ns16550.c	Thu Jul 14 09:05:22 2005 +0000
     4.3 @@ -16,7 +16,7 @@
     4.4  #include <asm/io.h>
     4.5  
     4.6  /* Config serial port with a string <baud>,DPS,<io-base>,<irq>. */
     4.7 -char opt_com1[30] = "", opt_com2[30] = "";
     4.8 +static char opt_com1[30] = "", opt_com2[30] = "";
     4.9  string_param("com1", opt_com1);
    4.10  string_param("com2", opt_com2);
    4.11  
    4.12 @@ -25,10 +25,7 @@ static struct ns16550 {
    4.13      unsigned long io_base;   /* I/O port or memory-mapped I/O address. */
    4.14      char *remapped_io_base;  /* Remapped virtual address of mmap I/O.  */ 
    4.15      struct irqaction irqaction;
    4.16 -} ns16550_com[2] = {
    4.17 -    { 0, 0, 0, 0, 4, 0x3f8 },
    4.18 -    { 0, 0, 0, 0, 3, 0x2f8 }
    4.19 -};
    4.20 +} ns16550_com[2] = { { 0 } };
    4.21  
    4.22  /* Register offsets */
    4.23  #define RBR             0x00    /* receive buffer       */
    4.24 @@ -157,9 +154,12 @@ static void ns16550_init_preirq(struct s
    4.25      ns_write_reg(uart, IER, 0);
    4.26  
    4.27      /* Line control and baud-rate generator. */
    4.28 -    ns_write_reg(uart, LCR, lcr | LCR_DLAB);
    4.29 -    ns_write_reg(uart, DLL, 115200/uart->baud); /* baud lo */
    4.30 -    ns_write_reg(uart, DLM, 0);                 /* baud hi */
    4.31 +    if ( uart->baud != 0 )
    4.32 +    {
    4.33 +        ns_write_reg(uart, LCR, lcr | LCR_DLAB);
    4.34 +        ns_write_reg(uart, DLL, 115200/uart->baud); /* baud lo */
    4.35 +        ns_write_reg(uart, DLM, 0);                 /* baud hi */
    4.36 +    }
    4.37      ns_write_reg(uart, LCR, lcr);               /* parity, data, stop */
    4.38  
    4.39      /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */
    4.40 @@ -178,6 +178,9 @@ static void ns16550_init_postirq(struct 
    4.41      struct ns16550 *uart = port->uart;
    4.42      int rc;
    4.43  
    4.44 +    if ( uart->irq <= 0 )
    4.45 +        return;
    4.46 +
    4.47      serial_async_transmit(port);
    4.48  
    4.49      uart->irqaction.handler = ns16550_interrupt;
    4.50 @@ -213,6 +216,24 @@ static struct uart_driver ns16550_driver
    4.51      .getc         = ns16550_getc
    4.52  };
    4.53  
    4.54 +static int parse_parity_char(int c)
    4.55 +{
    4.56 +    switch ( c )
    4.57 +    {
    4.58 +    case 'n':
    4.59 +        return PARITY_NONE;
    4.60 +    case 'o': 
    4.61 +        return PARITY_ODD;
    4.62 +    case 'e': 
    4.63 +        return PARITY_EVEN;
    4.64 +    case 'm': 
    4.65 +        return PARITY_MARK;
    4.66 +    case 's': 
    4.67 +        return PARITY_SPACE;
    4.68 +    }
    4.69 +    return 0;
    4.70 +}
    4.71 +
    4.72  #define PARSE_ERR(_f, _a...)                 \
    4.73      do {                                     \
    4.74          printk( "ERROR: " _f "\n" , ## _a ); \
    4.75 @@ -221,49 +242,24 @@ static struct uart_driver ns16550_driver
    4.76  
    4.77  static void ns16550_parse_port_config(struct ns16550 *uart, char *conf)
    4.78  {
    4.79 -    if ( *conf == '\0' )
    4.80 -        return;
    4.81 +    int baud;
    4.82  
    4.83 -    uart->baud = simple_strtol(conf, &conf, 10);
    4.84 -    if ( (uart->baud < 1200) || (uart->baud > 115200) )
    4.85 -        PARSE_ERR("Baud rate %d outside supported range.", uart->baud);
    4.86 +    if ( (conf == NULL) || (*conf == '\0') )
    4.87 +        goto config_parsed;
    4.88 +
    4.89 +    if ( (baud = simple_strtol(conf, &conf, 10)) != 0 )
    4.90 +        uart->baud = baud;
    4.91  
    4.92      if ( *conf != ',' )
    4.93 -        PARSE_ERR("Missing data/parity/stop specifiers.");
    4.94 -
    4.95 +        goto config_parsed;
    4.96      conf++;
    4.97  
    4.98      uart->data_bits = simple_strtol(conf, &conf, 10);
    4.99 -    if ( (uart->data_bits < 5) || (uart->data_bits > 8) )
   4.100 -        PARSE_ERR("%d data bits are unsupported.", uart->data_bits);
   4.101  
   4.102 -    switch ( *conf )
   4.103 -    {
   4.104 -    case 'n':
   4.105 -        uart->parity = PARITY_NONE;
   4.106 -        break;
   4.107 -    case 'o': 
   4.108 -        uart->parity =  PARITY_ODD;
   4.109 -        break;
   4.110 -    case 'e': 
   4.111 -        uart->parity =  PARITY_EVEN;
   4.112 -        break;
   4.113 -    case 'm': 
   4.114 -        uart->parity =  PARITY_MARK;
   4.115 -        break;
   4.116 -    case 's': 
   4.117 -        uart->parity =  PARITY_SPACE;
   4.118 -        break;
   4.119 -
   4.120 -    default:
   4.121 -        PARSE_ERR("Invalid parity specifier '%c'.", *conf);
   4.122 -    }
   4.123 -
   4.124 +    uart->parity = parse_parity_char(*conf);
   4.125      conf++;
   4.126  
   4.127      uart->stop_bits = simple_strtol(conf, &conf, 10);
   4.128 -    if ( (uart->stop_bits < 1) || (uart->stop_bits > 2) )
   4.129 -        PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits);
   4.130  
   4.131      if ( *conf == ',' )
   4.132      {
   4.133 @@ -277,13 +273,39 @@ static void ns16550_parse_port_config(st
   4.134          }
   4.135      }
   4.136  
   4.137 + config_parsed:
   4.138 +    /* Sanity checks. */
   4.139 +    if ( (uart->baud != 0) && ((uart->baud < 1200) || (uart->baud > 115200)) )
   4.140 +        PARSE_ERR("Baud rate %d outside supported range.", uart->baud);
   4.141 +    if ( (uart->data_bits < 5) || (uart->data_bits > 8) )
   4.142 +        PARSE_ERR("%d data bits are unsupported.", uart->data_bits);
   4.143 +    if ( (uart->stop_bits < 1) || (uart->stop_bits > 2) )
   4.144 +        PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits);
   4.145 +    if ( uart->io_base == 0 )
   4.146 +        PARSE_ERR("I/O base address must be specified.");
   4.147 +
   4.148 +    /* Register with generic serial driver. */
   4.149      serial_register_uart(uart - ns16550_com, &ns16550_driver, uart);
   4.150  }
   4.151  
   4.152 -void ns16550_init(void)
   4.153 +void ns16550_init(int index, struct ns16550_defaults *defaults)
   4.154  {
   4.155 -    ns16550_parse_port_config(&ns16550_com[0], opt_com1);
   4.156 -    ns16550_parse_port_config(&ns16550_com[1], opt_com2);
   4.157 +    struct ns16550 *uart = &ns16550_com[index];
   4.158 +
   4.159 +    if ( (index < 0) || (index > 1) )
   4.160 +        return;
   4.161 +
   4.162 +    if ( defaults != NULL )
   4.163 +    {
   4.164 +        uart->baud      = defaults->baud;
   4.165 +        uart->data_bits = defaults->data_bits;
   4.166 +        uart->parity    = parse_parity_char(defaults->parity);
   4.167 +        uart->stop_bits = defaults->stop_bits;
   4.168 +        uart->irq       = defaults->irq;
   4.169 +        uart->io_base   = defaults->io_base;
   4.170 +    }
   4.171 +
   4.172 +    ns16550_parse_port_config(uart, (index == 0) ? opt_com1 : opt_com2);
   4.173  }
   4.174  
   4.175  /*
     5.1 --- a/xen/include/xen/serial.h	Thu Jul 14 08:00:55 2005 +0000
     5.2 +++ b/xen/include/xen/serial.h	Thu Jul 14 09:05:22 2005 +0000
     5.3 @@ -113,7 +113,15 @@ void serial_tx_interrupt(struct serial_p
     5.4  /*
     5.5   * Initialisers for individual uart drivers.
     5.6   */
     5.7 -void ns16550_init(void);
     5.8 +struct ns16550_defaults {
     5.9 +    int baud;      /* default baud rate; 0 == pre-configured */
    5.10 +    int data_bits; /* default data bits (5, 6, 7 or 8) */
    5.11 +    int parity;    /* default parity (n, o, e, m or s) */
    5.12 +    int stop_bits; /* default stop bits (1 or 2) */
    5.13 +    int irq;       /* default irq */
    5.14 +    unsigned long io_base; /* default io_base address */
    5.15 +};
    5.16 +void ns16550_init(int index, struct ns16550_defaults *defaults);
    5.17  
    5.18  #endif /* __XEN_SERIAL_H__ */
    5.19