ia64/xen-unstable

changeset 5195:4c63d91b687f

bitkeeper revision 1.1586 (4298e019QH28MgGwaw0jHPWEeEnyoA)

Clean up serial driver in Xen: separate ns16550 driver from generic
serial code.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat May 28 21:18:17 2005 +0000 (2005-05-28)
parents 1e610bdd54fc
children df3e1d0fd811
files .rootkeys xen/arch/ia64/xensetup.c xen/arch/x86/cdb.c xen/arch/x86/setup.c xen/drivers/char/console.c xen/drivers/char/ns16550.c xen/drivers/char/serial.c xen/include/asm-ia64/config.h xen/include/asm-ia64/serial.h xen/include/asm-x86/serial.h xen/include/xen/console.h xen/include/xen/serial.h
line diff
     1.1 --- a/.rootkeys	Sat May 28 15:21:07 2005 +0000
     1.2 +++ b/.rootkeys	Sat May 28 21:18:17 2005 +0000
     1.3 @@ -1232,6 +1232,7 @@ 40715b2bi9gU43-cYzlmPDgreYQchw xen/drive
     1.4  40715b2cNVOegtvyft_AHFKJYRprfA xen/drivers/acpi/tables.c
     1.5  3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile
     1.6  4049e6bfNSIq7s7OV-Bd69QD0RpR2Q xen/drivers/char/console.c
     1.7 +4298e018XQtZkCdufpyFimOGZqqsFA xen/drivers/char/ns16550.c
     1.8  3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/serial.c
     1.9  40715b2cFpte_UNWnBZW0Du7z9AhTQ xen/include/acpi/acconfig.h
    1.10  40715b2ctNvVZ058w8eM8DR9hOat_A xen/include/acpi/acexcep.h
    1.11 @@ -1356,7 +1357,6 @@ 42422fb0FVX-TJkSvAXnbfwMf19XFA xen/inclu
    1.12  3ddb79c2QF5-pZGzuX4QukPCDAl59A xen/include/asm-x86/processor.h
    1.13  40cf1596bim9F9DNdV75klgRSZ6Y2A xen/include/asm-x86/regs.h
    1.14  3ddb79c2plf7ciNgoNjU-RsbUzawsw xen/include/asm-x86/rwlock.h
    1.15 -42136b49h6MkeayfuOaTPcJQWKga2g xen/include/asm-x86/serial.h
    1.16  405b8599BsDsDwKEJLS0XipaiQW3TA xen/include/asm-x86/shadow.h
    1.17  3ddb79c3Hgbb2g8CyWLMCK-6_ZVQSQ xen/include/asm-x86/smp.h
    1.18  3ddb79c3jn8ALV_S9W5aeTYUQRKBpg xen/include/asm-x86/smpboot.h
     2.1 --- a/xen/arch/ia64/xensetup.c	Sat May 28 15:21:07 2005 +0000
     2.2 +++ b/xen/arch/ia64/xensetup.c	Sat May 28 21:18:17 2005 +0000
     2.3 @@ -154,7 +154,8 @@ void start_kernel(void)
     2.4      early_setup_arch(&cmdline);
     2.5  
     2.6      /* We initialise the serial devices very early so we can get debugging. */
     2.7 -    serial_init_stage1();
     2.8 +    ns16550_init();
     2.9 +    serial_init_preirq();
    2.10  
    2.11      init_console();
    2.12      set_printk_prefix("(XEN) ");
     3.1 --- a/xen/arch/x86/cdb.c	Sat May 28 15:21:07 2005 +0000
     3.2 +++ b/xen/arch/x86/cdb.c	Sat May 28 21:18:17 2005 +0000
     3.3 @@ -91,11 +91,11 @@ attempt_receive_packet(char *recv_buf, s
     3.4  	u8 ch;
     3.5  
     3.6  	/* Skip over everything up to the first '$' */
     3.7 -	while ((ch = irq_serial_getc(ctx->serhnd)) != '$')
     3.8 +	while ((ch = serial_getc(ctx->serhnd)) != '$')
     3.9  		;
    3.10  	csum = 0;
    3.11  	for (count = 0; count < 4096; count++) {
    3.12 -		ch = irq_serial_getc(ctx->serhnd);
    3.13 +		ch = serial_getc(ctx->serhnd);
    3.14  		if (ch == '#')
    3.15  			break;
    3.16  		recv_buf[count] = ch;
    3.17 @@ -106,8 +106,8 @@ attempt_receive_packet(char *recv_buf, s
    3.18  		return -1;
    3.19  	}
    3.20  	recv_buf[count] = 0;
    3.21 -	received_csum = hex_char_val(irq_serial_getc(ctx->serhnd)) * 16 +
    3.22 -		hex_char_val(irq_serial_getc(ctx->serhnd));
    3.23 +	received_csum = hex_char_val(serial_getc(ctx->serhnd)) * 16 +
    3.24 +		hex_char_val(serial_getc(ctx->serhnd));
    3.25  	if (received_csum == csum) {
    3.26  		return 0;
    3.27  	} else {
    3.28 @@ -163,7 +163,7 @@ xendbg_finish_reply(struct xendbg_contex
    3.29  	xendbg_put_char('#', ctx);
    3.30  	xendbg_send(buf, 2, ctx);
    3.31  
    3.32 -	ch = irq_serial_getc(ctx->serhnd);
    3.33 +	ch = serial_getc(ctx->serhnd);
    3.34  	if (ch == '+')
    3.35  		return 0;
    3.36  	else
    3.37 @@ -394,7 +394,7 @@ initialize_xendbg(void)
    3.38  {
    3.39  	if (!strcmp(opt_cdb, "none"))
    3.40  		return 0;
    3.41 -	xdb_ctx.serhnd = parse_serial_handle(opt_cdb);
    3.42 +	xdb_ctx.serhnd = serial_parse_handle(opt_cdb);
    3.43  	if (xdb_ctx.serhnd == -1)
    3.44  		panic("Can't parse %s as CDB serial info.\n", opt_cdb);
    3.45  
     4.1 --- a/xen/arch/x86/setup.c	Sat May 28 15:21:07 2005 +0000
     4.2 +++ b/xen/arch/x86/setup.c	Sat May 28 21:18:17 2005 +0000
     4.3 @@ -216,7 +216,7 @@ static void __init start_of_day(void)
     4.4  
     4.5      initialize_keytable();
     4.6  
     4.7 -    serial_init_stage2();
     4.8 +    serial_init_postirq();
     4.9  
    4.10      init_xen_time();
    4.11  
    4.12 @@ -263,7 +263,8 @@ void __init __start_xen(multiboot_info_t
    4.13      smp_prepare_boot_cpu();
    4.14  
    4.15      /* We initialise the serial devices very early so we can get debugging. */
    4.16 -    serial_init_stage1();
    4.17 +    ns16550_init();
    4.18 +    serial_init_preirq();
    4.19  
    4.20      init_console();
    4.21  
     5.1 --- a/xen/drivers/char/console.c	Sat May 28 15:21:07 2005 +0000
     5.2 +++ b/xen/drivers/char/console.c	Sat May 28 21:18:17 2005 +0000
     5.3 @@ -260,7 +260,7 @@ static void switch_serial_input(void)
     5.4      }
     5.5  }
     5.6  
     5.7 -static void __serial_rx(unsigned char c, struct cpu_user_regs *regs)
     5.8 +static void __serial_rx(char c, struct cpu_user_regs *regs)
     5.9  {
    5.10      if ( xen_rx )
    5.11          return handle_keypress(c, regs);
    5.12 @@ -272,7 +272,7 @@ static void __serial_rx(unsigned char c,
    5.13      send_guest_virq(dom0->exec_domain[0], VIRQ_CONSOLE);
    5.14  }
    5.15  
    5.16 -static void serial_rx(unsigned char c, struct cpu_user_regs *regs)
    5.17 +static void serial_rx(char c, struct cpu_user_regs *regs)
    5.18  {
    5.19      static int switch_code_count = 0;
    5.20  
    5.21 @@ -416,7 +416,7 @@ void init_console(void)
    5.22          if ( *p == ',' )
    5.23              p++;
    5.24          if ( strncmp(p, "com", 3) == 0 )
    5.25 -            sercon_handle = parse_serial_handle(p);
    5.26 +            sercon_handle = serial_parse_handle(p);
    5.27          else if ( strncmp(p, "vga", 3) == 0 )
    5.28              vgacon_enabled = 1;
    5.29      }
    5.30 @@ -465,21 +465,6 @@ void console_force_lock(void)
    5.31      spin_lock(&console_lock);
    5.32  }
    5.33  
    5.34 -void console_putc(char c)
    5.35 -{
    5.36 -    serial_putc(sercon_handle, c);
    5.37 -}
    5.38 -
    5.39 -int console_getc(void)
    5.40 -{
    5.41 -    return serial_getc(sercon_handle);
    5.42 -}
    5.43 -
    5.44 -int irq_console_getc(void)
    5.45 -{
    5.46 -    return irq_serial_getc(sercon_handle);
    5.47 -}
    5.48 -
    5.49  
    5.50  /*
    5.51   * **************************************************************
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/drivers/char/ns16550.c	Sat May 28 21:18:17 2005 +0000
     6.3 @@ -0,0 +1,263 @@
     6.4 +/******************************************************************************
     6.5 + * ns16550.c
     6.6 + * 
     6.7 + * Driver for 16550-series UARTs. This driver is to be kept within Xen as
     6.8 + * it permits debugging of seriously-toasted machines (e.g., in situations
     6.9 + * where a device driver within a guest OS would be inaccessible).
    6.10 + * 
    6.11 + * Copyright (c) 2003-2005, K A Fraser
    6.12 + */
    6.13 +
    6.14 +#include <xen/config.h>
    6.15 +#include <xen/init.h>
    6.16 +#include <xen/irq.h>
    6.17 +#include <xen/sched.h>
    6.18 +#include <xen/serial.h>
    6.19 +#include <asm/io.h>
    6.20 +
    6.21 +/* Config serial port with a string <baud>,DPS,<io-base>,<irq>. */
    6.22 +static char opt_com1[30] = "", opt_com2[30] = "";
    6.23 +string_param("com1", opt_com1);
    6.24 +string_param("com2", opt_com2);
    6.25 +
    6.26 +static struct ns16550 {
    6.27 +    int baud, data_bits, parity, stop_bits, io_base, irq;
    6.28 +    struct irqaction irqaction;
    6.29 +} ns16550_com[2] = {
    6.30 +    { 0, 0, 0, 0, 0x3f8, 4 },
    6.31 +    { 0, 0, 0, 0, 0x2f8, 3 }
    6.32 +};
    6.33 +
    6.34 +/* Register offsets */
    6.35 +#define RBR             0x00    /* receive buffer       */
    6.36 +#define THR             0x00    /* transmit holding     */
    6.37 +#define IER             0x01    /* interrupt enable     */
    6.38 +#define IIR             0x02    /* interrupt identity   */
    6.39 +#define FCR             0x02    /* FIFO control         */
    6.40 +#define LCR             0x03    /* line control         */
    6.41 +#define MCR             0x04    /* Modem control        */
    6.42 +#define LSR             0x05    /* line status          */
    6.43 +#define MSR             0x06    /* Modem status         */
    6.44 +#define DLL             0x00    /* divisor latch (ls) (DLAB=1) */
    6.45 +#define DLM             0x01    /* divisor latch (ms) (DLAB=1) */
    6.46 +
    6.47 +/* Interrupt Enable Register */
    6.48 +#define IER_ERDAI       0x01    /* rx data recv'd       */
    6.49 +#define IER_ETHREI      0x02    /* tx reg. empty        */
    6.50 +#define IER_ELSI        0x04    /* rx line status       */
    6.51 +#define IER_EMSI        0x08    /* MODEM status         */
    6.52 +
    6.53 +/* FIFO control register */
    6.54 +#define FCR_ENABLE      0x01    /* enable FIFO          */
    6.55 +#define FCR_CLRX        0x02    /* clear Rx FIFO        */
    6.56 +#define FCR_CLTX        0x04    /* clear Tx FIFO        */
    6.57 +#define FCR_DMA         0x10    /* enter DMA mode       */
    6.58 +#define FCR_TRG1        0x00    /* Rx FIFO trig lev 1   */
    6.59 +#define FCR_TRG4        0x40    /* Rx FIFO trig lev 4   */
    6.60 +#define FCR_TRG8        0x80    /* Rx FIFO trig lev 8   */
    6.61 +#define FCR_TRG14       0xc0    /* Rx FIFO trig lev 14  */
    6.62 +
    6.63 +/* Line control register */
    6.64 +#define LCR_DLAB        0x80    /* Divisor Latch Access */
    6.65 +
    6.66 +/* Modem Control Register */
    6.67 +#define MCR_DTR         0x01    /* Data Terminal Ready  */
    6.68 +#define MCR_RTS         0x02    /* Request to Send      */
    6.69 +#define MCR_OUT2        0x08    /* OUT2: interrupt mask */
    6.70 +
    6.71 +/* Line Status Register */
    6.72 +#define LSR_DR          0x01    /* Data ready           */
    6.73 +#define LSR_OE          0x02    /* Overrun              */
    6.74 +#define LSR_PE          0x04    /* Parity error         */
    6.75 +#define LSR_FE          0x08    /* Framing error        */
    6.76 +#define LSR_BI          0x10    /* Break                */
    6.77 +#define LSR_THRE        0x20    /* Xmit hold reg empty  */
    6.78 +#define LSR_TEMT        0x40    /* Xmitter empty        */
    6.79 +#define LSR_ERR         0x80    /* Error                */
    6.80 +
    6.81 +/* These parity settings can be ORed directly into the LCR. */
    6.82 +#define PARITY_NONE     (0<<3)
    6.83 +#define PARITY_ODD      (1<<3)
    6.84 +#define PARITY_EVEN     (3<<3)
    6.85 +#define PARITY_MARK     (5<<3)
    6.86 +#define PARITY_SPACE    (7<<3)
    6.87 +
    6.88 +static void ns16550_interrupt(
    6.89 +    int irq, void *dev_id, struct cpu_user_regs *regs)
    6.90 +{
    6.91 +    serial_rx_interrupt(dev_id, regs);
    6.92 +}
    6.93 +
    6.94 +static void ns16550_putc(struct serial_port *port, char c)
    6.95 +{
    6.96 +    struct ns16550 *uart = port->uart;
    6.97 +
    6.98 +    while ( !(inb(uart->io_base + LSR) & LSR_THRE) )
    6.99 +        cpu_relax();
   6.100 +
   6.101 +    outb(c, uart->io_base + THR);
   6.102 +}
   6.103 +
   6.104 +static int ns16550_getc(struct serial_port *port, char *pc)
   6.105 +{
   6.106 +    struct ns16550 *uart = port->uart;
   6.107 +
   6.108 +    if ( !(inb(uart->io_base + LSR) & LSR_DR) )
   6.109 +        return 0;
   6.110 +
   6.111 +    *pc = inb(uart->io_base + RBR);
   6.112 +    return 1;
   6.113 +}
   6.114 +
   6.115 +static void ns16550_init_preirq(struct serial_port *port)
   6.116 +{
   6.117 +    struct ns16550 *uart = port->uart;
   6.118 +    unsigned char lcr;
   6.119 +
   6.120 +    lcr = (uart->data_bits - 5) | ((uart->stop_bits - 1) << 2) | uart->parity;
   6.121 +
   6.122 +    /* No interrupts. */
   6.123 +    outb(0, uart->io_base + IER);
   6.124 +
   6.125 +    /* Line control and baud-rate generator. */
   6.126 +    outb(lcr | LCR_DLAB,    uart->io_base + LCR);
   6.127 +    outb(115200/uart->baud, uart->io_base + DLL); /* baud lo */
   6.128 +    outb(0,                 uart->io_base + DLM); /* baud hi */
   6.129 +    outb(lcr,               uart->io_base + LCR); /* parity, data, stop */
   6.130 +
   6.131 +    /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */
   6.132 +    outb(MCR_DTR | MCR_RTS, uart->io_base + MCR);
   6.133 +
   6.134 +    /* Enable and clear the FIFOs. Set a large trigger threshold. */
   6.135 +    outb(FCR_ENABLE | FCR_CLRX | FCR_CLTX | FCR_TRG14, uart->io_base + FCR);
   6.136 +}
   6.137 +
   6.138 +static void ns16550_init_postirq(struct serial_port *port)
   6.139 +{
   6.140 +    struct ns16550 *uart = port->uart;
   6.141 +    int rc;
   6.142 +
   6.143 +    uart->irqaction.handler = ns16550_interrupt;
   6.144 +    uart->irqaction.name    = "ns16550";
   6.145 +    uart->irqaction.dev_id  = port;
   6.146 +    if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
   6.147 +        printk("ERROR: Failed to allocate na16550 IRQ %d\n", uart->irq);
   6.148 +
   6.149 +    /* For sanity, clear the receive FIFO. */
   6.150 +    outb(FCR_ENABLE | FCR_CLRX | FCR_TRG14, uart->io_base + FCR);
   6.151 +
   6.152 +    /* Master interrupt enable; also keep DTR/RTS asserted. */
   6.153 +    outb(MCR_OUT2 | MCR_DTR | MCR_RTS, uart->io_base + MCR);
   6.154 +
   6.155 +    /* Enable receive interrupts. */
   6.156 +    outb(IER_ERDAI, uart->io_base + IER);
   6.157 +}
   6.158 +
   6.159 +#ifdef CONFIG_X86
   6.160 +#include <asm/physdev.h>
   6.161 +static void ns16550_endboot(struct serial_port *port)
   6.162 +{
   6.163 +    struct ns16550 *uart = port->uart;
   6.164 +    physdev_modify_ioport_access_range(dom0, 0, uart->io_base, 8);
   6.165 +}
   6.166 +#else
   6.167 +#define ns16550_endboot NULL
   6.168 +#endif
   6.169 +
   6.170 +static struct uart_driver ns16550_driver = {
   6.171 +    .init_preirq  = ns16550_init_preirq,
   6.172 +    .init_postirq = ns16550_init_postirq,
   6.173 +    .endboot      = ns16550_endboot,
   6.174 +    .putc         = ns16550_putc,
   6.175 +    .getc         = ns16550_getc
   6.176 +};
   6.177 +
   6.178 +#define PARSE_ERR(_f, _a...)                 \
   6.179 +    do {                                     \
   6.180 +        printk( "ERROR: " _f "\n" , ## _a ); \
   6.181 +        return;                              \
   6.182 +    } while ( 0 )
   6.183 +
   6.184 +static void ns16550_parse_port_config(struct ns16550 *uart, char *conf)
   6.185 +{
   6.186 +    if ( *conf == '\0' )
   6.187 +        return;
   6.188 +
   6.189 +    uart->baud = simple_strtol(conf, &conf, 10);
   6.190 +    if ( (uart->baud < 1200) || (uart->baud > 115200) )
   6.191 +        PARSE_ERR("Baud rate %d outside supported range.", uart->baud);
   6.192 +
   6.193 +    if ( *conf != ',' )
   6.194 +        PARSE_ERR("Missing data/parity/stop specifiers.");
   6.195 +
   6.196 +    conf++;
   6.197 +
   6.198 +    uart->data_bits = simple_strtol(conf, &conf, 10);
   6.199 +    if ( (uart->data_bits < 5) || (uart->data_bits > 8) )
   6.200 +        PARSE_ERR("%d data bits are unsupported.", uart->data_bits);
   6.201 +
   6.202 +    switch ( *conf )
   6.203 +    {
   6.204 +    case 'n':
   6.205 +        uart->parity = PARITY_NONE;
   6.206 +        break;
   6.207 +    case 'o': 
   6.208 +        uart->parity =  PARITY_ODD;
   6.209 +        break;
   6.210 +    case 'e': 
   6.211 +        uart->parity =  PARITY_EVEN;
   6.212 +        break;
   6.213 +    case 'm': 
   6.214 +        uart->parity =  PARITY_MARK;
   6.215 +        break;
   6.216 +    case 's': 
   6.217 +        uart->parity =  PARITY_SPACE;
   6.218 +        break;
   6.219 +
   6.220 +    default:
   6.221 +        PARSE_ERR("Invalid parity specifier '%c'.", *conf);
   6.222 +    }
   6.223 +
   6.224 +    conf++;
   6.225 +
   6.226 +    uart->stop_bits = simple_strtol(conf, &conf, 10);
   6.227 +    if ( (uart->stop_bits < 1) || (uart->stop_bits > 2) )
   6.228 +        PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits);
   6.229 +
   6.230 +    if ( *conf == ',' )
   6.231 +    {
   6.232 +        conf++;
   6.233 +
   6.234 +        uart->io_base = simple_strtol(conf, &conf, 0);
   6.235 +        if ( (uart->io_base <= 0x0000) || (uart->io_base > 0xfff0) )
   6.236 +            PARSE_ERR("I/O port base 0x%x is outside the supported range.",
   6.237 +                      uart->io_base);
   6.238 +
   6.239 +        if ( *conf != ',' )
   6.240 +            PARSE_ERR("Missing IRQ specifier.");
   6.241 +            
   6.242 +        conf++;
   6.243 +            
   6.244 +        uart->irq = simple_strtol(conf, &conf, 10);
   6.245 +        if ( (uart->irq <= 0) || (uart->irq >= 32) )
   6.246 +            PARSE_ERR("IRQ %d is outside the supported range.", uart->irq);
   6.247 +    }
   6.248 +
   6.249 +    serial_register_uart(uart - ns16550_com, &ns16550_driver, uart);
   6.250 +}
   6.251 +
   6.252 +void ns16550_init(void)
   6.253 +{
   6.254 +    ns16550_parse_port_config(&ns16550_com[0], opt_com1);
   6.255 +    ns16550_parse_port_config(&ns16550_com[1], opt_com2);
   6.256 +}
   6.257 +
   6.258 +/*
   6.259 + * Local variables:
   6.260 + * mode: C
   6.261 + * c-set-style: "BSD"
   6.262 + * c-basic-offset: 4
   6.263 + * tab-width: 4
   6.264 + * indent-tabs-mode: nil
   6.265 + * End:
   6.266 + */
     7.1 --- a/xen/drivers/char/serial.c	Sat May 28 15:21:07 2005 +0000
     7.2 +++ b/xen/drivers/char/serial.c	Sat May 28 21:18:17 2005 +0000
     7.3 @@ -1,9 +1,7 @@
     7.4  /******************************************************************************
     7.5   * serial.c
     7.6   * 
     7.7 - * Driver for 16550-series UARTs. This driver is to be kept within Xen as
     7.8 - * it permits debugging of seriously-toasted machines (e.g., in situations
     7.9 - * where a device driver within a guest OS would be inaccessible).
    7.10 + * Framework for serial device drivers.
    7.11   * 
    7.12   * Copyright (c) 2003-2005, K A Fraser
    7.13   */
    7.14 @@ -15,230 +13,119 @@
    7.15  #include <xen/reboot.h>
    7.16  #include <xen/sched.h>
    7.17  #include <xen/serial.h>
    7.18 -#include <asm/io.h>
    7.19  
    7.20 -#ifdef CONFIG_X86
    7.21 -#include <asm/physdev.h>
    7.22 -#endif
    7.23 -
    7.24 -/* Config serial port with a string <baud>,DPS,<io-base>,<irq>. */
    7.25 -static char opt_com1[30] = OPT_COM1_STR, opt_com2[30] = OPT_COM2_STR;
    7.26 -string_param("com1", opt_com1);
    7.27 -string_param("com2", opt_com2);
    7.28 -
    7.29 -static struct uart com[2] = {
    7.30 -    { 0, 0, 0, 0, 0x3f8, 4,
    7.31 -      NULL, NULL, NULL,
    7.32 -      SPIN_LOCK_UNLOCKED },
    7.33 -    { 0, 0, 0, 0, 0x2f8, 3,
    7.34 -      NULL, NULL, NULL,
    7.35 -      SPIN_LOCK_UNLOCKED }
    7.36 +static struct serial_port com[2] = {
    7.37 +    { .lock = SPIN_LOCK_UNLOCKED }, 
    7.38 +    { .lock = SPIN_LOCK_UNLOCKED }
    7.39  };
    7.40  
    7.41 -#define UART_ENABLED(_u) ((_u)->baud != 0)
    7.42 -#define DISABLE_UART(_u) ((_u)->baud = 0)
    7.43 +void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
    7.44 +{
    7.45 +    char c;
    7.46 +    serial_rx_fn fn;
    7.47 +    unsigned long flags;
    7.48  
    7.49 +    BUG_ON(!port->driver);
    7.50 +    BUG_ON(!port->driver->getc);
    7.51 +
    7.52 +    spin_lock_irqsave(&port->lock, flags);
    7.53 +
    7.54 +    while ( port->driver->getc(port, &c) )
    7.55 +    {
    7.56 +        fn = NULL;
    7.57  
    7.58 -/***********************
    7.59 - * PRIVATE FUNCTIONS
    7.60 - */
    7.61 +        if ( port->rx != NULL )
    7.62 +            fn = port->rx;
    7.63 +        else if ( (c & 0x80) && (port->rx_hi != NULL) )
    7.64 +            fn = port->rx_hi;
    7.65 +        else if ( !(c & 0x80) && (port->rx_lo != NULL) )
    7.66 +            fn = port->rx_lo;
    7.67 +        else if ( (port->rxbufp - port->rxbufc) != RXBUFSZ )
    7.68 +            port->rxbuf[MASK_RXBUF_IDX(port->rxbufp++)] = c;            
    7.69  
    7.70 -static void uart_rx(struct uart *uart, struct cpu_user_regs *regs)
    7.71 +        if ( fn != NULL )
    7.72 +        {
    7.73 +            spin_unlock_irqrestore(&port->lock, flags);
    7.74 +            (*fn)(c & 0x7f, regs);
    7.75 +            spin_lock_irqsave(&port->lock, flags);
    7.76 +        }
    7.77 +    }
    7.78 +
    7.79 +    spin_unlock_irqrestore(&port->lock, flags);
    7.80 +}
    7.81 +
    7.82 +void serial_putc(int handle, char c)
    7.83  {
    7.84 -    unsigned char c;
    7.85 +    struct serial_port *port = &com[handle & SERHND_IDX];
    7.86 +    unsigned long flags;
    7.87  
    7.88 -    if ( !UART_ENABLED(uart) )
    7.89 +    if ( (handle == -1) || !port->driver || !port->driver->putc )
    7.90          return;
    7.91  
    7.92 -    /*
    7.93 -     * No need for the uart spinlock here. Only the uart's own interrupt
    7.94 -     * handler will read from the RBR and the handler isn't reentrant.
    7.95 -     * Calls to serial_getc() will disable this handler before proceeding.
    7.96 -     */
    7.97 -    while ( inb(uart->io_base + LSR) & LSR_DR )
    7.98 -    {
    7.99 -        c = inb(uart->io_base + RBR);
   7.100 -        if ( uart->rx != NULL )
   7.101 -            uart->rx(c, regs);
   7.102 -        else if ( (c & 0x80) && (uart->rx_hi != NULL) )
   7.103 -            uart->rx_hi(c&0x7f, regs);
   7.104 -        else if ( !(c & 0x80) && (uart->rx_lo != NULL) )
   7.105 -            uart->rx_lo(c&0x7f, regs);
   7.106 -        else if ( (uart->rxbufp - uart->rxbufc) != RXBUFSZ )
   7.107 -            uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufp++)] = c;            
   7.108 -    }
   7.109 -}
   7.110 -
   7.111 -static void serial_interrupt(
   7.112 -    int irq, void *dev_id, struct cpu_user_regs *regs)
   7.113 -{
   7.114 -    uart_rx((struct uart *)dev_id, regs);
   7.115 -}
   7.116 -
   7.117 -static inline void __serial_putc(
   7.118 -    struct uart *uart, int handle, unsigned char c)
   7.119 -{
   7.120 -    unsigned long flags;
   7.121 -    int space;
   7.122 +    spin_lock_irqsave(&port->lock, flags);
   7.123  
   7.124      if ( (c == '\n') && (handle & SERHND_COOKED) )
   7.125 -        __serial_putc(uart, handle, '\r');
   7.126 +        port->driver->putc(port, '\r');
   7.127  
   7.128      if ( handle & SERHND_HI )
   7.129          c |= 0x80;
   7.130      else if ( handle & SERHND_LO )
   7.131          c &= 0x7f;
   7.132  
   7.133 -    do { 
   7.134 -        spin_lock_irqsave(&uart->lock, flags);
   7.135 -        space = arch_serial_putc(uart, c);
   7.136 -        spin_unlock_irqrestore(&uart->lock, flags);
   7.137 +    port->driver->putc(port, c);
   7.138 +
   7.139 +    spin_unlock_irqrestore(&port->lock, flags);
   7.140 +}
   7.141 +
   7.142 +void serial_puts(int handle, const char *s)
   7.143 +{
   7.144 +    while ( *s != '\0' )
   7.145 +        serial_putc(handle, *s++);
   7.146 +}
   7.147 +
   7.148 +/* Returns TRUE if given character (*pc) matches the serial handle. */
   7.149 +static int byte_matches(int handle, unsigned char *pc)
   7.150 +{
   7.151 +    if ( !(handle & SERHND_HI) )
   7.152 +    {
   7.153 +        if ( !(handle & SERHND_LO) || !(*pc & 0x80) )
   7.154 +            return 1;
   7.155      }
   7.156 -    while ( !space );
   7.157 +    else if ( *pc & 0x80 )
   7.158 +    {
   7.159 +        *pc &= 0x7f;
   7.160 +        return 1;
   7.161 +    }
   7.162 +    return 0;
   7.163  }
   7.164  
   7.165 -#define PARSE_ERR(_f, _a...)                 \
   7.166 -    do {                                     \
   7.167 -        printk( "ERROR: " _f "\n" , ## _a ); \
   7.168 -        DISABLE_UART(uart);                  \
   7.169 -        return;                              \
   7.170 -} while ( 0 )
   7.171 -        
   7.172 -static void parse_port_config(char *conf, struct uart *uart)
   7.173 +char serial_getc(int handle)
   7.174  {
   7.175 -    if ( *conf == '\0' )
   7.176 -        return;
   7.177 +    struct serial_port *port = &com[handle & SERHND_IDX];
   7.178 +    unsigned char c;
   7.179 +    unsigned long flags;
   7.180  
   7.181 -    uart->baud = simple_strtol(conf, &conf, 10);
   7.182 -    if ( (uart->baud < 1200) || (uart->baud > 115200) )
   7.183 -        PARSE_ERR("Baud rate %d outside supported range.", uart->baud);
   7.184 -
   7.185 -    if ( *conf != ',' )
   7.186 -        PARSE_ERR("Missing data/parity/stop specifiers.");
   7.187 +    if ( (handle == -1) || !port->driver || !port->driver->getc )
   7.188 +        return '\0';
   7.189  
   7.190 -    conf++;
   7.191 +    spin_lock_irqsave(&port->lock, flags);
   7.192  
   7.193 -    uart->data_bits = simple_strtol(conf, &conf, 10);
   7.194 -    if ( (uart->data_bits < 5) || (uart->data_bits > 8) )
   7.195 -        PARSE_ERR("%d data bits are unsupported.", uart->data_bits);
   7.196 -
   7.197 -    switch ( *conf )
   7.198 +    while ( port->rxbufp != port->rxbufc )
   7.199      {
   7.200 -    case 'n':
   7.201 -        uart->parity = PARITY_NONE;
   7.202 -        break;
   7.203 -    case 'o': 
   7.204 -        uart->parity =  PARITY_ODD;
   7.205 -        break;
   7.206 -    case 'e': 
   7.207 -        uart->parity =  PARITY_EVEN;
   7.208 -        break;
   7.209 -    case 'm': 
   7.210 -        uart->parity =  PARITY_MARK;
   7.211 -        break;
   7.212 -    case 's': 
   7.213 -        uart->parity =  PARITY_SPACE;
   7.214 -        break;
   7.215 -
   7.216 -    default:
   7.217 -        PARSE_ERR("Invalid parity specifier '%c'.", *conf);
   7.218 +        c = port->rxbuf[MASK_RXBUF_IDX(port->rxbufc++)];
   7.219 +        if ( byte_matches(handle, &c) )
   7.220 +            goto out;
   7.221      }
   7.222 -
   7.223 -    conf++;
   7.224 +    
   7.225 +    while ( !port->driver->getc(port, &c) && !byte_matches(handle, &c) )
   7.226 +        continue;
   7.227  
   7.228 -    uart->stop_bits = simple_strtol(conf, &conf, 10);
   7.229 -    if ( (uart->stop_bits < 1) || (uart->stop_bits > 2) )
   7.230 -        PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits);
   7.231 -
   7.232 -    if ( *conf == ',' )
   7.233 -    {
   7.234 -        conf++;
   7.235 -
   7.236 -        uart->io_base = simple_strtol(conf, &conf, 0);
   7.237 -        if ( (uart->io_base <= 0x0000) || (uart->io_base > 0xfff0) )
   7.238 -            PARSE_ERR("I/O port base 0x%x is outside the supported range.",
   7.239 -                      uart->io_base);
   7.240 -
   7.241 -        if ( *conf != ',' )
   7.242 -            PARSE_ERR("Missing IRQ specifier.");
   7.243 -            
   7.244 -        conf++;
   7.245 -            
   7.246 -        uart->irq = simple_strtol(conf, &conf, 10);
   7.247 -        if ( (uart->irq <= 0) || (uart->irq >= 32) )
   7.248 -            PARSE_ERR("IRQ %d is outside the supported range.", uart->irq);
   7.249 -    }
   7.250 + out:
   7.251 +    spin_unlock_irqrestore(&port->lock, flags);
   7.252 +    return c;
   7.253  }
   7.254  
   7.255 -static void uart_config_stage1(struct uart *uart)
   7.256 -{
   7.257 -    unsigned char lcr;
   7.258 -
   7.259 -    if ( !UART_ENABLED(uart) )
   7.260 -        return;
   7.261 -
   7.262 -    lcr = (uart->data_bits - 5) | ((uart->stop_bits - 1) << 2) | uart->parity;
   7.263 -
   7.264 -    /* No interrupts. */
   7.265 -    outb(0, uart->io_base + IER);
   7.266 -
   7.267 -    /* Line control and baud-rate generator. */
   7.268 -    outb(lcr | LCR_DLAB,    uart->io_base + LCR);
   7.269 -    outb(115200/uart->baud, uart->io_base + DLL); /* baud lo */
   7.270 -    outb(0,                 uart->io_base + DLM); /* baud hi */
   7.271 -    outb(lcr,               uart->io_base + LCR); /* parity, data, stop */
   7.272 -
   7.273 -    /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */
   7.274 -    outb(MCR_DTR | MCR_RTS, uart->io_base + MCR);
   7.275 -
   7.276 -    /* Enable and clear the FIFOs. Set a large trigger threshold. */
   7.277 -    outb(FCR_ENABLE | FCR_CLRX | FCR_CLTX | FCR_TRG14, uart->io_base + FCR);
   7.278 -}
   7.279 -
   7.280 -static void uart_config_stage2(struct uart *uart)
   7.281 -{
   7.282 -    int rc;
   7.283 -
   7.284 -    if ( !UART_ENABLED(uart) )
   7.285 -        return;
   7.286 -
   7.287 -    uart->irqaction.handler = serial_interrupt;
   7.288 -    uart->irqaction.name    = "serial";
   7.289 -    uart->irqaction.dev_id  = uart;
   7.290 -    if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
   7.291 -        printk("ERROR: Failed to allocate serial IRQ %d\n", uart->irq);
   7.292 -
   7.293 -    /* For sanity, clear the receive FIFO. */
   7.294 -    outb(FCR_ENABLE | FCR_CLRX | FCR_TRG14, uart->io_base + FCR);
   7.295 -
   7.296 -    /* Master interrupt enable; also keep DTR/RTS asserted. */
   7.297 -    outb(MCR_OUT2 | MCR_DTR | MCR_RTS, uart->io_base + MCR);
   7.298 -
   7.299 -    /* Enable receive interrupts. */
   7.300 -    outb(IER_ERDAI, uart->io_base + IER);
   7.301 -}
   7.302 -
   7.303 -
   7.304 -/***********************
   7.305 - * PUBLIC FUNCTIONS
   7.306 - */
   7.307 -
   7.308 -void serial_init_stage1(void)
   7.309 -{
   7.310 -    parse_port_config(opt_com1, &com[0]);
   7.311 -    parse_port_config(opt_com2, &com[1]);
   7.312 -
   7.313 -    uart_config_stage1(&com[0]);
   7.314 -    uart_config_stage1(&com[1]);
   7.315 -}
   7.316 -
   7.317 -void serial_init_stage2(void)
   7.318 -{
   7.319 -    uart_config_stage2(&com[0]);
   7.320 -    uart_config_stage2(&com[1]);
   7.321 -}
   7.322 -
   7.323 -int parse_serial_handle(char *conf)
   7.324 +int serial_parse_handle(char *conf)
   7.325  {
   7.326      int handle;
   7.327  
   7.328 @@ -261,14 +148,6 @@ int parse_serial_handle(char *conf)
   7.329          goto fail;
   7.330      }
   7.331  
   7.332 -#ifndef NO_UART_CONFIG_OK
   7.333 -    if ( !UART_ENABLED(&com[handle]) )
   7.334 -    {
   7.335 -        printk("ERROR: cannot use unconfigured serial port COM%d\n", handle+1);
   7.336 -        return -1;
   7.337 -    }
   7.338 -#endif
   7.339 -
   7.340      if ( conf[4] == 'H' )
   7.341          handle |= SERHND_HI;
   7.342      else if ( conf[4] == 'L' )
   7.343 @@ -285,147 +164,80 @@ int parse_serial_handle(char *conf)
   7.344  
   7.345  void serial_set_rx_handler(int handle, serial_rx_fn fn)
   7.346  {
   7.347 -    struct uart *uart = &com[handle & SERHND_IDX];
   7.348 +    struct serial_port *port = &com[handle & SERHND_IDX];
   7.349      unsigned long flags;
   7.350  
   7.351      if ( handle == -1 )
   7.352          return;
   7.353  
   7.354 -    spin_lock_irqsave(&uart->lock, flags);
   7.355 +    spin_lock_irqsave(&port->lock, flags);
   7.356  
   7.357 -    if ( uart->rx != NULL )
   7.358 +    if ( port->rx != NULL )
   7.359          goto fail;
   7.360  
   7.361      if ( handle & SERHND_LO )
   7.362      {
   7.363 -        if ( uart->rx_lo != NULL )
   7.364 +        if ( port->rx_lo != NULL )
   7.365              goto fail;
   7.366 -        uart->rx_lo = fn;        
   7.367 +        port->rx_lo = fn;        
   7.368      }
   7.369      else if ( handle & SERHND_HI )
   7.370      {
   7.371 -        if ( uart->rx_hi != NULL )
   7.372 +        if ( port->rx_hi != NULL )
   7.373              goto fail;
   7.374 -        uart->rx_hi = fn;
   7.375 +        port->rx_hi = fn;
   7.376      }
   7.377      else
   7.378      {
   7.379 -        if ( (uart->rx_hi != NULL) || (uart->rx_lo != NULL) )
   7.380 +        if ( (port->rx_hi != NULL) || (port->rx_lo != NULL) )
   7.381              goto fail;
   7.382 -        uart->rx = fn;
   7.383 +        port->rx = fn;
   7.384      }
   7.385  
   7.386 -    spin_unlock_irqrestore(&uart->lock, flags);
   7.387 +    spin_unlock_irqrestore(&port->lock, flags);
   7.388      return;
   7.389  
   7.390   fail:
   7.391 -    spin_unlock_irqrestore(&uart->lock, flags);
   7.392 +    spin_unlock_irqrestore(&port->lock, flags);
   7.393      printk("ERROR: Conflicting receive handlers for COM%d\n", 
   7.394             handle & SERHND_IDX);
   7.395  }
   7.396  
   7.397 -void serial_putc(int handle, unsigned char c)
   7.398 -{
   7.399 -    struct uart *uart = &com[handle & SERHND_IDX];
   7.400 -
   7.401 -    if ( handle == -1 )
   7.402 -        return;
   7.403 -
   7.404 -    __serial_putc(uart, handle, c);
   7.405 -}
   7.406 -
   7.407 -void serial_puts(int handle, const char *s)
   7.408 +void serial_force_unlock(int handle)
   7.409  {
   7.410 -    struct uart *uart = &com[handle & SERHND_IDX];
   7.411 -
   7.412 -    if ( handle == -1 )
   7.413 -        return;
   7.414 -
   7.415 -    while ( *s != '\0' )
   7.416 -        __serial_putc(uart, handle, *s++);
   7.417 -}
   7.418 -
   7.419 -/* Returns TRUE if given character (*pc) matches the serial handle. */
   7.420 -static int byte_matches(int handle, unsigned char *pc)
   7.421 -{
   7.422 -    if ( !(handle & SERHND_HI) )
   7.423 -    {
   7.424 -        if ( !(handle & SERHND_LO) || !(*pc & 0x80) )
   7.425 -            return 1;
   7.426 -    }
   7.427 -    else if ( *pc & 0x80 )
   7.428 -    {
   7.429 -        *pc &= 0x7f;
   7.430 -        return 1;
   7.431 -    }
   7.432 -    return 0;
   7.433 +    struct serial_port *port = &com[handle & SERHND_IDX];
   7.434 +    if ( handle != -1 )
   7.435 +        port->lock = SPIN_LOCK_UNLOCKED;
   7.436  }
   7.437  
   7.438 -unsigned char irq_serial_getc(int handle)
   7.439 +void serial_init_preirq(void)
   7.440  {
   7.441 -    struct uart *uart = &com[handle & SERHND_IDX];
   7.442 -    unsigned char c;
   7.443 -
   7.444 -
   7.445 -    while ( uart->rxbufp != uart->rxbufc )
   7.446 -    {
   7.447 -        c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
   7.448 -        if ( byte_matches(handle, &c) )
   7.449 -            goto out;
   7.450 -    }
   7.451 -    
   7.452 -    /* We now wait for the UART to receive a suitable character. */
   7.453 -    do {
   7.454 -        while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 )
   7.455 -            barrier();
   7.456 -        c = inb(uart->io_base + RBR);
   7.457 -    }
   7.458 -    while ( !byte_matches(handle, &c) );
   7.459 -    
   7.460 - out:
   7.461 -    return c;
   7.462 +    int i;
   7.463 +    for ( i = 0; i < ARRAY_SIZE(com); i++ )
   7.464 +        if ( com[i].driver && com[i].driver->init_preirq )
   7.465 +            com[i].driver->init_preirq(&com[i]);
   7.466  }
   7.467  
   7.468 -unsigned char serial_getc(int handle)
   7.469 +void serial_init_postirq(void)
   7.470  {
   7.471 -    struct uart *uart = &com[handle & SERHND_IDX];
   7.472 -    unsigned char c;
   7.473 -    unsigned long flags;
   7.474 -
   7.475 -    spin_lock_irqsave(&uart->lock, flags);
   7.476 -
   7.477 -    while ( uart->rxbufp != uart->rxbufc )
   7.478 -    {
   7.479 -        c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
   7.480 -        if ( byte_matches(handle, &c) )
   7.481 -            goto out;
   7.482 -    }
   7.483 -    
   7.484 -    disable_irq(uart->irq);
   7.485 -
   7.486 -    c = irq_serial_getc(handle);
   7.487 -    
   7.488 -    enable_irq(uart->irq);
   7.489 - out:
   7.490 -    spin_unlock_irqrestore(&uart->lock, flags);
   7.491 -    return c;
   7.492 -}
   7.493 -
   7.494 -void serial_force_unlock(int handle)
   7.495 -{
   7.496 -    struct uart *uart = &com[handle & SERHND_IDX];
   7.497 -    if ( handle != -1 )
   7.498 -        uart->lock = SPIN_LOCK_UNLOCKED;
   7.499 +    int i;
   7.500 +    for ( i = 0; i < ARRAY_SIZE(com); i++ )
   7.501 +        if ( com[i].driver && com[i].driver->init_postirq )
   7.502 +            com[i].driver->init_postirq(&com[i]);
   7.503  }
   7.504  
   7.505  void serial_endboot(void)
   7.506  {
   7.507 -#ifdef CONFIG_X86
   7.508      int i;
   7.509      for ( i = 0; i < ARRAY_SIZE(com); i++ )
   7.510 -        if ( UART_ENABLED(&com[i]) )
   7.511 -            physdev_modify_ioport_access_range(dom0, 0, com[i].io_base, 8);
   7.512 -#endif
   7.513 +        if ( com[i].driver && com[i].driver->endboot )
   7.514 +            com[i].driver->endboot(&com[i]);
   7.515 +}
   7.516 +
   7.517 +void serial_register_uart(int idx, struct uart_driver *driver, void *uart)
   7.518 +{
   7.519 +    com[idx].driver = driver;
   7.520 +    com[idx].uart   = uart;
   7.521  }
   7.522  
   7.523  /*
     8.1 --- a/xen/include/asm-ia64/config.h	Sat May 28 15:21:07 2005 +0000
     8.2 +++ b/xen/include/asm-ia64/config.h	Sat May 28 21:18:17 2005 +0000
     8.3 @@ -160,9 +160,6 @@ void sort_main_extable(void);
     8.4      (likely(sizeof(count) <= 4) /* disallow 64-bit counts */ &&  \
     8.5       access_ok(type,addr,count*size))
     8.6  
     8.7 -// without this, uart_config_stageX does outb's which are non-portable
     8.8 -#define NO_UART_CONFIG_OK
     8.9 -
    8.10  // see drivers/char/console.c
    8.11  #ifndef CONFIG_VTI
    8.12  #define	OPT_CONSOLE_STR "com1"
     9.1 --- a/xen/include/asm-ia64/serial.h	Sat May 28 15:21:07 2005 +0000
     9.2 +++ b/xen/include/asm-ia64/serial.h	Sat May 28 21:18:17 2005 +0000
     9.3 @@ -10,21 +10,11 @@
     9.4  #define arch_serial_putc(_uart, _c)					\
     9.5  	( platform_is_hp_ski() ? (ia64_ssc(c,0,0,0,SSC_PUTCHAR), 1) :	\
     9.6  	( longs_peak_putc(c), 1 ))
     9.7 -
     9.8 -#define OPT_COM1_STR "115200"
     9.9 -#define OPT_COM2_STR ""
    9.10 -#else // CONFIG_VTI
    9.11 +#else
    9.12  #define arch_serial_putc(_uart, _c)					\
    9.13  	( platform_is_hp_ski() ? (ia64_ssc(c,0,0,0,SSC_PUTCHAR), 1) :	\
    9.14  	( (inb((_uart)->io_base + LSR) & LSR_THRE) ?    		\
    9.15  	(outb((_c), (_uart)->io_base + THR), 1) : 0 ))
    9.16 -
    9.17 -#define OPT_COM1_STR ""
    9.18 -#define OPT_COM2_STR "57600,8n1"
    9.19 -#endif // CONFIG_VTI
    9.20 -
    9.21 -unsigned char irq_serial_getc(int handle);
    9.22 -
    9.23 -void serial_force_unlock(int handle);
    9.24 +#endif
    9.25  
    9.26  #endif /* __ASM_SERIAL_H__ */
    10.1 --- a/xen/include/asm-x86/serial.h	Sat May 28 15:21:07 2005 +0000
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,22 +0,0 @@
    10.4 -
    10.5 -#ifndef __ASM_X86_SERIAL_H__
    10.6 -#define __ASM_X86_SERIAL_H__
    10.7 -
    10.8 -#define OPT_COM1_STR ""
    10.9 -#define OPT_COM2_STR ""
   10.10 -
   10.11 -#define arch_serial_putc(_uart, _c)                 \
   10.12 -    ( (inb((_uart)->io_base + LSR) & LSR_THRE) ?    \
   10.13 -      (outb((_c), (_uart)->io_base + THR), 1) : 0 )
   10.14 -
   10.15 -#endif /* __ASM_X86_SERIAL_H__ */
   10.16 -
   10.17 -/*
   10.18 - * Local variables:
   10.19 - * mode: C
   10.20 - * c-set-style: "BSD"
   10.21 - * c-basic-offset: 4
   10.22 - * tab-width: 4
   10.23 - * indent-tabs-mode: nil
   10.24 - * End:
   10.25 - */
    11.1 --- a/xen/include/xen/console.h	Sat May 28 15:21:07 2005 +0000
    11.2 +++ b/xen/include/xen/console.h	Sat May 28 21:18:17 2005 +0000
    11.3 @@ -22,8 +22,4 @@ void console_endboot(int disable_vga);
    11.4  void console_force_unlock(void);
    11.5  void console_force_lock(void);
    11.6  
    11.7 -void console_putc(char c);
    11.8 -int console_getc(void);
    11.9 -int irq_console_getc(void);
   11.10 -
   11.11  #endif /* __CONSOLE_H__ */
    12.1 --- a/xen/include/xen/serial.h	Sat May 28 15:21:07 2005 +0000
    12.2 +++ b/xen/include/xen/serial.h	Sat May 28 21:18:17 2005 +0000
    12.3 @@ -1,9 +1,7 @@
    12.4  /******************************************************************************
    12.5   * serial.h
    12.6   * 
    12.7 - * Driver for 16550-series UARTs. This driver is to be kept within Xen as
    12.8 - * it permits debugging of seriously-toasted machines (e.g., in situations
    12.9 - * where a device driver within a guest OS would be inaccessible).
   12.10 + * Framework for serial device drivers.
   12.11   * 
   12.12   * Copyright (c) 2003-2005, K A Fraser
   12.13   */
   12.14 @@ -11,94 +9,61 @@
   12.15  #ifndef __XEN_SERIAL_H__
   12.16  #define __XEN_SERIAL_H__
   12.17  
   12.18 -#include <xen/irq.h>
   12.19 -#include <asm/regs.h>
   12.20 -#include <asm/serial.h>
   12.21 -
   12.22 -/* Register offsets */
   12.23 -#define RBR             0x00    /* receive buffer       */
   12.24 -#define THR             0x00    /* transmit holding     */
   12.25 -#define IER             0x01    /* interrupt enable     */
   12.26 -#define IIR             0x02    /* interrupt identity   */
   12.27 -#define FCR             0x02    /* FIFO control         */
   12.28 -#define LCR             0x03    /* line control         */
   12.29 -#define MCR             0x04    /* Modem control        */
   12.30 -#define LSR             0x05    /* line status          */
   12.31 -#define MSR             0x06    /* Modem status         */
   12.32 -#define DLL             0x00    /* divisor latch (ls) (DLAB=1) */
   12.33 -#define DLM             0x01    /* divisor latch (ms) (DLAB=1) */
   12.34 -
   12.35 -/* Interrupt Enable Register */
   12.36 -#define IER_ERDAI       0x01    /* rx data recv'd       */
   12.37 -#define IER_ETHREI      0x02    /* tx reg. empty        */
   12.38 -#define IER_ELSI        0x04    /* rx line status       */
   12.39 -#define IER_EMSI        0x08    /* MODEM status         */
   12.40 -
   12.41 -/* FIFO control register */
   12.42 -#define FCR_ENABLE      0x01    /* enable FIFO          */
   12.43 -#define FCR_CLRX        0x02    /* clear Rx FIFO        */
   12.44 -#define FCR_CLTX        0x04    /* clear Tx FIFO        */
   12.45 -#define FCR_DMA         0x10    /* enter DMA mode       */
   12.46 -#define FCR_TRG1        0x00    /* Rx FIFO trig lev 1   */
   12.47 -#define FCR_TRG4        0x40    /* Rx FIFO trig lev 4   */
   12.48 -#define FCR_TRG8        0x80    /* Rx FIFO trig lev 8   */
   12.49 -#define FCR_TRG14       0xc0    /* Rx FIFO trig lev 14  */
   12.50 -
   12.51 -/* Line control register */
   12.52 -#define LCR_DLAB        0x80    /* Divisor Latch Access */
   12.53 -
   12.54 -/* Modem Control Register */
   12.55 -#define MCR_DTR         0x01    /* Data Terminal Ready  */
   12.56 -#define MCR_RTS         0x02    /* Request to Send      */
   12.57 -#define MCR_OUT2        0x08    /* OUT2: interrupt mask */
   12.58 -
   12.59 -/* Line Status Register */
   12.60 -#define LSR_DR          0x01    /* Data ready           */
   12.61 -#define LSR_OE          0x02    /* Overrun              */
   12.62 -#define LSR_PE          0x04    /* Parity error         */
   12.63 -#define LSR_FE          0x08    /* Framing error        */
   12.64 -#define LSR_BI          0x10    /* Break                */
   12.65 -#define LSR_THRE        0x20    /* Xmit hold reg empty  */
   12.66 -#define LSR_TEMT        0x40    /* Xmitter empty        */
   12.67 -#define LSR_ERR         0x80    /* Error                */
   12.68 -
   12.69 -/* These parity settings can be ORed directly into the LCR. */
   12.70 -#define PARITY_NONE     (0<<3)
   12.71 -#define PARITY_ODD      (1<<3)
   12.72 -#define PARITY_EVEN     (3<<3)
   12.73 -#define PARITY_MARK     (5<<3)
   12.74 -#define PARITY_SPACE    (7<<3)
   12.75 +struct cpu_user_regs;
   12.76  
   12.77  /* Register a character-receive hook on the specified COM port. */
   12.78 -typedef void (*serial_rx_fn)(unsigned char, struct cpu_user_regs *);
   12.79 +typedef void (*serial_rx_fn)(char, struct cpu_user_regs *);
   12.80  void serial_set_rx_handler(int handle, serial_rx_fn fn);
   12.81  
   12.82 +/* Number of characters we buffer for a polling receiver. */
   12.83  #define RXBUFSZ 32
   12.84  #define MASK_RXBUF_IDX(_i) ((_i)&(RXBUFSZ-1))
   12.85 -struct uart {
   12.86 -    int              baud, data_bits, parity, stop_bits, io_base, irq;
   12.87 -    serial_rx_fn     rx_lo, rx_hi, rx;
   12.88 -    spinlock_t       lock;
   12.89 -    unsigned char    rxbuf[RXBUFSZ];
   12.90 -    unsigned int     rxbufp, rxbufc;
   12.91 -    struct irqaction irqaction;
   12.92 +
   12.93 +struct uart_driver;
   12.94 +
   12.95 +struct serial_port {
   12.96 +    /* Uart-driver parameters. */
   12.97 +    struct uart_driver *driver;
   12.98 +    void               *uart;
   12.99 +    /* Receiver callback functions (asynchronous receivers). */
  12.100 +    serial_rx_fn        rx_lo, rx_hi, rx;
  12.101 +    /* Receive data buffer (polling receivers). */
  12.102 +    char                rxbuf[RXBUFSZ];
  12.103 +    unsigned int        rxbufp, rxbufc;
  12.104 +    /* Serial I/O is concurrency-safe. */
  12.105 +    spinlock_t          lock;
  12.106  };
  12.107  
  12.108 -/* 'Serial handles' are comprise the following fields. */
  12.109 +struct uart_driver {
  12.110 +    /* Driver initialisation (pre- and post-IRQ subsystem setup). */
  12.111 +    void (*init_preirq)(struct serial_port *);
  12.112 +    void (*init_postirq)(struct serial_port *);
  12.113 +    /* Hook to clean up after Xen bootstrap (before domain 0 runs). */
  12.114 +    void (*endboot)(struct serial_port *);
  12.115 +    /* Put a char onto the serial line. */
  12.116 +    void (*putc)(struct serial_port *, char);
  12.117 +    /* Get a char from the serial line: returns FALSE if no char available. */
  12.118 +    int  (*getc)(struct serial_port *, char *);
  12.119 +};
  12.120 +
  12.121 +/* 'Serial handles' are composed from the following fields. */
  12.122  #define SERHND_IDX      (1<<0) /* COM1 or COM2?                           */
  12.123  #define SERHND_HI       (1<<1) /* Mux/demux each transferred char by MSB. */
  12.124  #define SERHND_LO       (1<<2) /* Ditto, except that the MSB is cleared.  */
  12.125  #define SERHND_COOKED   (1<<3) /* Newline/carriage-return translation?    */
  12.126  
  12.127  /* Two-stage initialisation (before/after IRQ-subsystem initialisation). */
  12.128 -void serial_init_stage1(void);
  12.129 -void serial_init_stage2(void);
  12.130 +void serial_init_preirq(void);
  12.131 +void serial_init_postirq(void);
  12.132 +
  12.133 +/* Clean-up hook before domain 0 runs. */
  12.134 +void serial_endboot(void);
  12.135  
  12.136  /* Takes a config string and creates a numeric handle on the COM port. */
  12.137 -int parse_serial_handle(char *conf);
  12.138 +int serial_parse_handle(char *conf);
  12.139  
  12.140  /* Transmit a single character via the specified COM port. */
  12.141 -void serial_putc(int handle, unsigned char c);
  12.142 +void serial_putc(int handle, char c);
  12.143  
  12.144  /* Transmit a NULL-terminated string via the specified COM port. */
  12.145  void serial_puts(int handle, const char *s);
  12.146 @@ -108,15 +73,21 @@ void serial_puts(int handle, const char 
  12.147   * will not return until a character is available. It can safely be
  12.148   * called with interrupts disabled.
  12.149   */
  12.150 -unsigned char serial_getc(int handle);
  12.151 -/* 
  12.152 - * Same as serial_getc but can also be called from interrupt handlers.
  12.153 - */
  12.154 -unsigned char irq_serial_getc(int handle);
  12.155 +char serial_getc(int handle);
  12.156  
  12.157 +/* Forcibly prevent serial lockup when the system is in a bad way. */
  12.158  void serial_force_unlock(int handle);
  12.159  
  12.160 -void serial_endboot(void);
  12.161 +/* Register a uart on serial port @idx (e.g., @idx==0 is COM1). */
  12.162 +void serial_register_uart(int idx, struct uart_driver *driver, void *uart);
  12.163 +
  12.164 +/* Driver helper function: process receive work in interrupt context. */
  12.165 +void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs);
  12.166 +
  12.167 +/*
  12.168 + * Initialisers for individual uart drivers.
  12.169 + */
  12.170 +void ns16550_init(void);
  12.171  
  12.172  #endif /* __XEN_SERIAL_H__ */
  12.173