ia64/xen-unstable

changeset 758:f9c3bc6eb199

bitkeeper revision 1.456 (3f6de470w7_JGb139gaotteaX7UDcQ)

xen_serial.c, kernel.c:
Robustify Xen's serial handling. We now assert DTR and RTS so that we play nicely with flow control. Also the rx interrupt reads all chars from the fifo rather than just one. TODO: tx should be interrupt driven, and domains shouldn't be echo to serial but should go to DOM0 only.
author kaf24@scramble.cl.cam.ac.uk
date Sun Sep 21 17:48:32 2003 +0000 (2003-09-21)
parents d697d8000a55
children 977a79f98c2f
files xen/common/kernel.c xen/drivers/char/xen_serial.c
line diff
     1.1 --- a/xen/common/kernel.c	Sun Sep 21 15:25:14 2003 +0000
     1.2 +++ b/xen/common/kernel.c	Sun Sep 21 17:48:32 2003 +0000
     1.3 @@ -218,8 +218,6 @@ void cmain (unsigned long magic, multibo
     1.4  }
     1.5  
     1.6  
     1.7 -#ifdef CONFIG_OUTPUT_SERIAL
     1.8 -
     1.9  #define SERIAL_BASE 0x3f8
    1.10  #define RX_BUF      0
    1.11  #define TX_HOLD     0
    1.12 @@ -239,24 +237,24 @@ void init_serial(void)
    1.13      outb(115200/opt_ser_baud, SERIAL_BASE+DIVISOR_LO);
    1.14      outb(0, SERIAL_BASE+DIVISOR_HI);
    1.15      outb(0x03, SERIAL_BASE+DATA_FORMAT);
    1.16 +    
    1.17 +    /* DTR and RTS should both be high, to keep other end happy. */
    1.18 +    outb(0x02, SERIAL_BASE+LINE_CTL);
    1.19  
    1.20      /* No interrupts. */
    1.21      outb(0x00, SERIAL_BASE+INT_ENABLE);
    1.22  }
    1.23  
    1.24  
    1.25 +#ifdef CONFIG_OUTPUT_SERIAL
    1.26  void putchar_serial(unsigned char c)
    1.27  {
    1.28      if ( c == '\n' ) putchar_serial('\r');
    1.29      while ( !(inb(SERIAL_BASE+LINE_STATUS)&(1<<5)) ) barrier();
    1.30      outb(c, SERIAL_BASE+TX_HOLD);
    1.31  }
    1.32 -
    1.33  #else
    1.34 -
    1.35 -void init_serial(void) {}
    1.36  void putchar_serial(unsigned char c) {}
    1.37 -
    1.38  #endif
    1.39  
    1.40  
     2.1 --- a/xen/drivers/char/xen_serial.c	Sun Sep 21 15:25:14 2003 +0000
     2.2 +++ b/xen/drivers/char/xen_serial.c	Sun Sep 21 17:48:32 2003 +0000
     2.3 @@ -56,15 +56,16 @@ static void serial_rx_int(int irq, void 
     2.4      u_char c; 
     2.5      key_handler *handler; 
     2.6  
     2.7 -    /* clear the interrupt by reading the character */
     2.8 -    c = inb(SERIAL_BASE + NS16550_RBR);
     2.9 +    while ( (inb(SERIAL_BASE + NS16550_LSR) & 1) == 1 )
    2.10 +    {
    2.11 +        c = inb(SERIAL_BASE + NS16550_RBR);
    2.12  
    2.13 -    /* if there's a handler, call it: we trust it won't screw us too badly */
    2.14 -    if((handler = get_key_handler(c)) != NULL) 
    2.15 -	(*handler)(c, dev_id, regs); 
    2.16 +        if( (handler = get_key_handler(c)) != NULL ) 
    2.17 +            (*handler)(c, dev_id, regs); 
    2.18  
    2.19 -    if(serial_echo) 
    2.20 -	printk("%c", c); 
    2.21 +        if ( serial_echo ) 
    2.22 +            printk("%c", c);
    2.23 +    } 
    2.24  }
    2.25  
    2.26  void initialize_serial() 
    2.27 @@ -74,16 +75,17 @@ void initialize_serial()
    2.28      /* setup key handler */
    2.29      add_key_handler('~', toggle_echo, "toggle serial echo");
    2.30      
    2.31 -    /* Should detect this, but must be a ns16550a at least, surely? */
    2.32 -    fifo = 1;  
    2.33 -    if(fifo) {
    2.34 -	/* Clear FIFOs, enable, trigger at 1 byte */
    2.35 -	outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE |
    2.36 -	     NS16550_FCR_CLRX  | NS16550_FCR_CLTX, SERIAL_BASE+NS16550_FCR);
    2.37 -    }
    2.38 +    /* This assumes we have a 16550. It's pretty darned likely really! */
    2.39 +    /* Clear FIFOs, enable, trigger at 1 byte */
    2.40 +    outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE |
    2.41 +         NS16550_FCR_CLRX  | NS16550_FCR_CLTX, 
    2.42 +         SERIAL_BASE+NS16550_FCR);
    2.43  
    2.44 -    outb(NS16550_MCR_OUT2, SERIAL_BASE + NS16550_MCR);   /* Modem control */
    2.45 -    outb(NS16550_IER_ERDAI, SERIAL_BASE + NS16550_IER ); /* Setup interrupts */
    2.46 +    /* Enable receive interrupts. Also remember to keep DTR/RTS asserted. */
    2.47 +    outb(NS16550_MCR_OUT2|NS16550_MCR_DTR|NS16550_MCR_RTS, 
    2.48 +         SERIAL_BASE + NS16550_MCR);
    2.49 +    outb(NS16550_IER_ERDAI, 
    2.50 +         SERIAL_BASE + NS16550_IER );
    2.51  
    2.52      if((rc = request_irq(4, serial_rx_int, SA_NOPROFILE, "serial", 0)))
    2.53  	printk("initialize_serial: failed to get IRQ4, rc=%d\n", rc);