summaryrefslogtreecommitdiff
path: root/cpu/i386/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/i386/serial.c')
-rw-r--r--cpu/i386/serial.c153
1 files changed, 102 insertions, 51 deletions
diff --git a/cpu/i386/serial.c b/cpu/i386/serial.c
index c0d2e8aa14f..22c3c2aac37 100644
--- a/cpu/i386/serial.c
+++ b/cpu/i386/serial.c
@@ -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
@@ -89,13 +90,15 @@ 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) {
@@ -112,7 +115,8 @@ static int serial_div (int baudrate )
case 115200:
return 1;
}
- hang ();
+
+ return 12;
}
@@ -121,7 +125,7 @@ static int serial_div (int baudrate )
* as serial console interface.
*/
-int serial_init (void)
+int serial_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
@@ -134,24 +138,24 @@ int serial_init (void)
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 +164,7 @@ void serial_setbrg (void)
}
-void serial_putc (const char c)
+void serial_putc(const char c)
{
int i;
@@ -169,31 +173,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;
+#if 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 +222,17 @@ int serial_getc ()
}
-int serial_tstc ()
+int serial_tstc(void)
{
unsigned char status;
- status = inb (UART0_BASE + UART_LSR);
+#if 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);
}
@@ -234,36 +251,50 @@ int serial_tstc ()
#if 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,8 +303,10 @@ 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 */ ,
@@ -283,32 +316,49 @@ void serial_buffered_init (void)
/* 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 +372,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 +391,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,7 +409,7 @@ 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;
@@ -381,7 +432,7 @@ void kgdb_serial_init (void)
}
-void putDebugChar (const char c)
+void putDebugChar(const char c)
{
if (c == '\n')
serial_putc ('\r');
@@ -393,7 +444,7 @@ void putDebugChar (const char c)
}
-void putDebugStr (const char *s)
+void putDebugStr(const char *s)
{
while (*s) {
serial_putc(*s++);
@@ -401,7 +452,7 @@ void putDebugStr (const char *s)
}
-int getDebugChar (void)
+int getDebugChar(void)
{
unsigned char status = 0;
@@ -424,34 +475,34 @@ 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;
}