]> git.sur5r.net Git - u-boot/blobdiff - cpu/i386/serial.c
[PATCH] Avoid assigning PCI resources from zero address
[u-boot] / cpu / i386 / serial.c
index c0d2e8aa14f3dec6ccced3e5ea265f95233def23..e7299a7ebb0ea1d44955edcfa591633690935e6d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * (C) Copyright 2002
  * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
- * 
+ *
  * (C) Copyright 2000
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
@@ -24,6 +24,7 @@
  * MA 02111-1307 USA
  */
 /*------------------------------------------------------------------------------+ */
+
 /*
  * This source code has been made available to you by IBM on an AS-IS
  * basis.  Anyone receiving this source is licensed under IBM
 #include <asm/io.h>
 #include <asm/ibmpc.h>
 
-#if CONFIG_SERIAL_SOFTWARE_FIFO
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
 #include <malloc.h>
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #define UART_RBR    0x00
 #define UART_THR    0x00
 #define UART_IER    0x01
@@ -80,8 +83,7 @@
 #define asyncLSRRxFifoError1          0x80
 
 
-
-#if CONFIG_SERIAL_SOFTWARE_FIFO
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
 /*-----------------------------------------------------------------------------+
   | Fifo
   +-----------------------------------------------------------------------------*/
@@ -89,15 +91,17 @@ typedef struct {
        char *rx_buffer;
        ulong rx_put;
        ulong rx_get;
+       int cts;
 } serial_buffer_t;
 
-volatile static serial_buffer_t buf_info;
+volatile serial_buffer_t buf_info;
+static int serial_buffer_active=0;
 #endif
 
 
-static int serial_div (int baudrate )
+static int serial_div(int baudrate)
 {
-       
+
        switch (baudrate) {
        case 1200:
                return 96;
@@ -110,9 +114,10 @@ static int serial_div (int baudrate )
        case 57600:
                return 2;
        case 115200:
-               return 1;               
+               return 1;
        }
-       hang ();
+
+       return 12;
 }
 
 
@@ -121,37 +126,31 @@ static int serial_div (int baudrate )
  * as serial console interface.
  */
 
-int serial_init (void)
+int serial_init(void)
 {
-       DECLARE_GLOBAL_DATA_PTR;
-
        volatile char val;
-
        int bdiv = serial_div(gd->baudrate);
-    
 
        outb(0x80, UART0_BASE + UART_LCR);      /* set DLAB bit */
        outb(bdiv, UART0_BASE + UART_DLL);      /* set baudrate divisor */
        outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */
        outb(0x03, UART0_BASE + UART_LCR);      /* clear DLAB; set 8 bits, no parity */
-       outb(0x00, UART0_BASE + UART_FCR);      /* disable FIFO */
-       outb(0x00, UART0_BASE + UART_MCR);      /* no modem control DTR RTS */
+       outb(0x01, UART0_BASE + UART_FCR);      /* enable FIFO */
+       outb(0x0b, UART0_BASE + UART_MCR);      /* Set DTR and RTS active */
        val = inb(UART0_BASE + UART_LSR);       /* clear line status */
        val = inb(UART0_BASE + UART_RBR);       /* read receive buffer */
        outb(0x00, UART0_BASE + UART_SCR);      /* set scratchpad */
        outb(0x00, UART0_BASE + UART_IER);      /* set interrupt enable reg */
 
-       return (0);
+       return 0;
 }
 
 
-void serial_setbrg (void)
+void serial_setbrg(void)
 {
-       DECLARE_GLOBAL_DATA_PTR;
-
        unsigned short bdiv;
-       
-       bdiv = serial_div (gd->baudrate);
+
+       bdiv = serial_div(gd->baudrate);
 
        outb(0x80, UART0_BASE + UART_LCR);      /* set DLAB bit */
        outb(bdiv&0xff, UART0_BASE + UART_DLL); /* set baudrate divisor */
@@ -160,7 +159,7 @@ void serial_setbrg (void)
 }
 
 
-void serial_putc (const char c)
+void serial_putc(const char c)
 {
        int i;
 
@@ -169,31 +168,38 @@ void serial_putc (const char c)
 
        /* check THRE bit, wait for transmiter available */
        for (i = 1; i < 3500; i++) {
-               if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20)
+               if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20) {
                        break;
-               udelay (100);
+               }
+               udelay(100);
        }
        outb(c, UART0_BASE + UART_THR); /* put character out */
 }
 
 
-void serial_puts (const char *s)
+void serial_puts(const char *s)
 {
        while (*s) {
-               serial_putc (*s++);
+               serial_putc(*s++);
        }
 }
 
 
-int serial_getc ()
+int serial_getc(void)
 {
        unsigned char status = 0;
 
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+       if (serial_buffer_active) {
+               return serial_buffered_getc();
+       }
+#endif
+
        while (1) {
 #if defined(CONFIG_HW_WATCHDOG)
-               WATCHDOG_RESET ();      /* Reset HW Watchdog, if needed */
+               WATCHDOG_RESET();       /* Reset HW Watchdog, if needed */
 #endif /* CONFIG_HW_WATCHDOG */
-               status = inb (UART0_BASE + UART_LSR);
+               status = inb(UART0_BASE + UART_LSR);
                if ((status & asyncLSRDataReady1) != 0x0) {
                        break;
                }
@@ -211,11 +217,17 @@ int serial_getc ()
 }
 
 
-int serial_tstc ()
+int serial_tstc(void)
 {
        unsigned char status;
 
-       status = inb (UART0_BASE + UART_LSR);
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+       if (serial_buffer_active) {
+               return serial_buffered_tstc();
+       }
+#endif
+
+       status = inb(UART0_BASE + UART_LSR);
        if ((status & asyncLSRDataReady1) != 0x0) {
                return (1);
        }
@@ -232,38 +244,52 @@ int serial_tstc ()
 }
 
 
-#if CONFIG_SERIAL_SOFTWARE_FIFO
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
 
-void serial_isr (void *arg)
+void serial_isr(void *arg)
 {
        int space;
        int c;
-       const int rx_get = buf_info.rx_get;
        int rx_put = buf_info.rx_put;
 
-       if (rx_get <= rx_put) {
-               space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
+       if (buf_info.rx_get <= rx_put) {
+               space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - buf_info.rx_get);
        } else {
-               space = rx_get - rx_put;
+               space = buf_info.rx_get - rx_put;
        }
-       while (serial_tstc ()) {
-               c = serial_getc ();
+
+       while (inb(UART0_BASE + UART_LSR) & 1) {
+               c = inb(UART0_BASE);
                if (space) {
                        buf_info.rx_buffer[rx_put++] = c;
                        space--;
+
+                       if (rx_put == buf_info.rx_get) {
+                               buf_info.rx_get++;
+                               if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) {
+                                       buf_info.rx_get = 0;
+                               }
+                       }
+
+                       if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) {
+                               rx_put = 0;
+                               if (0 == buf_info.rx_get) {
+                                       buf_info.rx_get = 1;
+                               }
+
+                       }
+
                }
-               if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO)
-                       rx_put = 0;
                if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) {
                        /* Stop flow by setting RTS inactive */
-                       outb(inb (UART0_BASE + UART_MCR) & (0xFF ^ 0x02),
+                       outb(inb(UART0_BASE + UART_MCR) & (0xFF ^ 0x02),
                              UART0_BASE + UART_MCR);
                }
        }
        buf_info.rx_put = rx_put;
 }
 
-void serial_buffered_init (void)
+void serial_buffered_init(void)
 {
        serial_puts ("Switching to interrupt driven serial input mode.\n");
        buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO);
@@ -272,43 +298,62 @@ void serial_buffered_init (void)
 
        if (inb (UART0_BASE + UART_MSR) & 0x10) {
                serial_puts ("Check CTS signal present on serial port: OK.\n");
+               buf_info.cts = 1;
        } else {
                serial_puts ("WARNING: CTS signal not present on serial port.\n");
+               buf_info.cts = 0;
        }
 
-       irq_install_handler ( VECNUM_U0 /*UART0 *//*int vec */ ,
+       irq_install_handler ( VECNUM_U0 /*UART0 */ /*int vec */ ,
                              serial_isr /*interrupt_handler_t *handler */ ,
                              (void *) &buf_info /*void *arg */ );
 
        /* Enable "RX Data Available" Interrupt on UART */
        /* outb(inb(UART0_BASE + UART_IER) |0x01, UART0_BASE + UART_IER); */
        outb(0x01, UART0_BASE + UART_IER);
-       /* Set DTR active */
-       outb(inb (UART0_BASE + UART_MCR) | 0x01, UART0_BASE + UART_MCR);
-       /* Start flow by setting RTS active */
-       outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR);
-       /* Setup UART FIFO: RX trigger level: 4 byte, Enable FIFO */
-       outb((1 << 6) | 1, UART0_BASE + UART_FCR);
+
+       /* Set DTR and RTS active, enable interrupts  */
+       outb(inb (UART0_BASE + UART_MCR) | 0x0b, UART0_BASE + UART_MCR);
+
+       /* Setup UART FIFO: RX trigger level: 1 byte, Enable FIFO */
+       outb( /*(1 << 6) |*/  1, UART0_BASE + UART_FCR);
+
+       serial_buffer_active = 1;
 }
 
 void serial_buffered_putc (const char c)
 {
+       int i;
        /* Wait for CTS */
 #if defined(CONFIG_HW_WATCHDOG)
        while (!(inb (UART0_BASE + UART_MSR) & 0x10))
                WATCHDOG_RESET ();
 #else
-       while (!(inb (UART0_BASE + UART_MSR) & 0x10));
+       if (buf_info.cts)  {
+               for (i=0;i<1000;i++) {
+                       if ((inb (UART0_BASE + UART_MSR) & 0x10)) {
+                               break;
+                       }
+               }
+               if (i!=1000) {
+                       buf_info.cts = 0;
+               }
+       } else {
+               if ((inb (UART0_BASE + UART_MSR) & 0x10)) {
+                       buf_info.cts = 1;
+               }
+       }
+
 #endif
        serial_putc (c);
 }
 
-void serial_buffered_puts (const char *s)
+void serial_buffered_puts(const char *s)
 {
        serial_puts (s);
 }
 
-int serial_buffered_getc (void)
+int serial_buffered_getc(void)
 {
        int space;
        int c;
@@ -322,8 +367,9 @@ int serial_buffered_getc (void)
        while (rx_get == buf_info.rx_put);
 #endif
        c = buf_info.rx_buffer[rx_get++];
-       if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO)
+       if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO) {
                rx_get = 0;
+       }
        buf_info.rx_get = rx_get;
 
        rx_put = buf_info.rx_put;
@@ -340,7 +386,7 @@ int serial_buffered_getc (void)
        return c;
 }
 
-int serial_buffered_tstc (void)
+int serial_buffered_tstc(void)
 {
        return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0;
 }
@@ -358,10 +404,8 @@ int serial_buffered_tstc (void)
   configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE
 */
 #if (CONFIG_KGDB_SER_INDEX & 2)
-void kgdb_serial_init (void)
+void kgdb_serial_init(void)
 {
-       DECLARE_GLOBAL_DATA_PTR;
-
        volatile char val;
        bdiv = serial_div (CONFIG_KGDB_BAUDRATE);
 
@@ -381,7 +425,7 @@ void kgdb_serial_init (void)
 }
 
 
-void putDebugChar (const char c)
+void putDebugChar(const char c)
 {
        if (c == '\n')
                serial_putc ('\r');
@@ -393,7 +437,7 @@ void putDebugChar (const char c)
 }
 
 
-void putDebugStr (const char *s)
+void putDebugStr(const char *s)
 {
        while (*s) {
                serial_putc(*s++);
@@ -401,7 +445,7 @@ void putDebugStr (const char *s)
 }
 
 
-int getDebugChar (void)
+int getDebugChar(void)
 {
        unsigned char status = 0;
 
@@ -424,37 +468,36 @@ int getDebugChar (void)
 }
 
 
-void kgdb_interruptible (int yes)
+void kgdb_interruptible(int yes)
 {
        return;
 }
 
 #else  /* ! (CONFIG_KGDB_SER_INDEX & 2) */
 
-void kgdb_serial_init (void)
+void kgdb_serial_init(void)
 {
        serial_printf ("[on serial] ");
 }
 
-void putDebugChar (int c)
+void putDebugChar(int c)
 {
        serial_putc (c);
 }
 
-void putDebugStr (const char *str)
+void putDebugStr(const char *str)
 {
        serial_puts (str);
 }
 
-int getDebugChar (void)
+int getDebugChar(void)
 {
        return serial_getc ();
 }
 
-void kgdb_interruptible (int yes)
+void kgdb_interruptible(int yes)
 {
        return;
 }
 #endif /* (CONFIG_KGDB_SER_INDEX & 2) */
 #endif /* CFG_CMD_KGDB */
-