From: Pontus Fuchs (pontus.fuchs@tactel.se)
Date: Wed Apr 04 2001 - 11:40:05 EDT
Hi! > I've got really problems in using the serial device on netsilicons Net+40 > evaluation board. It is not possible to initialize the serial driver for non > canonnical reading. After setting up the device there is no chance to read > or write. > Has anybody solved this problem, or is a fix available ? Attached are 2 files. "serial_fix.tar.gz" is by netsilicon or redhat (I don't know) and fixes a few bugs. Apply it by unpacking in the top of the kernel sourcetree. "netarm-serial.diff1" is by me and fixes and fixes even more bugs. Apply it with patch to arch/armnommu/drivers/char/serial-netarm.c. This patch does: * Add debug-macro. * initialize rx_head, rx_tail and rx_cnt. * Disable port at shutdown. * Return number of bytes written in nas_write, not 0. * Don't oops when sending break. * Setting baudrate via nas_set_termios now works. * Don't crash when recieving other rx_interrupt than data available (break for example). Hope this helps you. If not, go chase more bugs (there definilty are). /Pontus Fuchs
--- serial-netarm.c.orig Thu Dec 28 15:59:54 2000
+++ serial-netarm.c Tue Jan 9 17:24:33 2001
@@ -32,8 +32,11 @@
#include <linux/autoconf.h>
+/* For debugging */
#if 0
-#define NAS_DEBUG_VERBOSE (1)
+#define NAS_DEBUG(args...) printk(args)
+#else
+#define NAS_DEBUG(args...)
#endif
#if !defined(MODULE) && !defined(CONFIG_ARCH_NETARM)
@@ -404,9 +407,9 @@
}
}
- port->tx_head = 0;
- port->tx_tail = 0;
- port->tx_cnt = 0;
+ port->rx_head = 0;
+ port->rx_tail = 0;
+ port->rx_cnt = 0;
if ( NULL != port->tx_buf )
{
@@ -421,9 +424,7 @@
port->tx_tail = 0;
port->tx_cnt = 0;
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_startup_port: setting port at 0x%08x to %d baud\n", (unsigned int)port, port->baud);
-#endif
+ NAS_DEBUG("nas_startup_port: setting port at 0x%08x to %d baud\n", (unsigned int)port, port->baud);
regs = port->registers;
regs->rx_match = 0;
@@ -437,9 +438,9 @@
regs->ctrl_b = NETARM_SER_CTLB_RCGT_EN | NETARM_SER_CTLB_UART_MODE;
#ifdef POLLED_SERIAL
regs->ctrl_a |= NETARM_SER_CTLA_ENABLE ;
-
+
#else
- regs->ctrl_a |= NETARM_SER_CTLA_ENABLE | NETARM_SER_CTLA_IE_RX_RDY |
+ regs->ctrl_a |= NETARM_SER_CTLA_ENABLE | NETARM_SER_CTLA_IE_RX_RDY |
NETARM_SER_CTLA_IE_RX_FULL ;
#endif
@@ -465,14 +466,10 @@
/* I assume we should free the tx buffer, but */
/* is the tty driver above still using the rx buf ??? */
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_shutdown_port: disabling port at 0x%08x\n", (unsigned int)port);
-#endif
+ NAS_DEBUG("nas_shutdown_port: disabling port at 0x%08x\n", (unsigned int)port);
-#if 0
/* turn off the port */
- regs->ctrl_a |= ~NETARM_SER_CTLA_ENABLE ;
-#endif
+ regs->ctrl_a &= ~NETARM_SER_CTLA_ENABLE ;
return 0;
}
@@ -495,7 +492,7 @@
major = MAJOR(tty->device);
line = MINOR(tty->device) - tty->driver.minor_start;
- printk("nas_open: major: %d, minor:%d\n", major, line);
+ NAS_DEBUG("nas_open: major: %d, minor:%d\n", major, line);
#if 0
netarm_dump_int_stats();
printk("port 1 status a 0x%08x\n",(nas_ports[1].registers)->status_a);
@@ -551,10 +548,7 @@
{
struct nas_port *port = (struct nas_port *) tty->driver_data;
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_close: called\n");
-#endif
- printk("nas_close: called\n");
+ NAS_DEBUG(__FUNCTION__ "()\n");
if (port) {
if (--port->count < 0) {
@@ -564,10 +558,8 @@
}
if (port->count) {
MOD_DEC_USE_COUNT;
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_close: not really closing, since count is %d (not 0)\n",
+ NAS_DEBUG(__FUNCTION__ "() Not really closing, since count is %d (not 0)\n",
port->count);
-#endif
return;
}
}
@@ -603,9 +595,9 @@
struct nas_port *port = (struct nas_port *) tty->driver_data;
int free_space;
unsigned char *fifo;
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_write: called with %d chars\n", count);
-#endif
+ int actual = 0;
+
+ NAS_DEBUG(__FUNCTION__ "() Going to write %d chars\n", count);
free_space = ( NAS_BUF_SIZE - 1 ) - port->tx_tail ;
@@ -620,9 +612,11 @@
*fifo = *buf;
buf++ ;
count--;
+ actual++;
}
- return count; // not supported
+ NAS_DEBUG(__FUNCTION__ "() Wrote %d chars\n", actual);
+ return actual;
}
//
@@ -631,9 +625,7 @@
static void
nas_flush_chars(struct tty_struct *tty)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_flush_chars: called\n");
-#endif
+ NAS_DEBUG(__FUNCTION__ "()\n");
}
//
@@ -645,9 +637,8 @@
{
struct nas_port *port = (struct nas_port *) tty->driver_data;
int free_space;
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_write_room: called\n");
-#endif
+
+ NAS_DEBUG(__FUNCTION__ "()\n");
free_space = ( NAS_BUF_SIZE - 1 ) - port->tx_tail ;
@@ -662,9 +653,8 @@
{
struct nas_port *port = (struct nas_port *) tty->driver_data;
int chars_in;
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_chars_in_buffer: called\n");
-#endif
+
+ NAS_DEBUG(__FUNCTION__ "()\n");
chars_in = port->tx_tail - port->tx_head ;
@@ -677,9 +667,7 @@
static void
nas_flush_buffer(struct tty_struct *tty)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_flush_buffer: called\n");
-#endif
+ NAS_DEBUG(__FUNCTION__ "()\n");
}
//
@@ -687,14 +675,14 @@
//
static void
-nas_send_break(struct tty_struct *tty, int duration)
+nas_send_break(struct nas_port *port, int duration)
{
- struct nas_port *port = (struct nas_port *) tty->driver_data;
volatile netarm_serial_channel_t *regs = port->registers;
/* set the SEND BREAK bit */
- regs->ctrl_a &= ~NETARM_SER_CTLA_BRK ;
-
+ regs->ctrl_a |= NETARM_SER_CTLA_BRK ;
+// regs->ctrl_a &= ~NETARM_SER_CTLA_BRK ;
+
/* let the system run... */
current->state = TASK_INTERRUPTIBLE ;
current->timeout = jiffies+duration ;
@@ -715,13 +703,11 @@
int retval;
struct nas_port *port = (struct nas_port *) tty->driver_data;
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_ioctl: called, cmd = 0x%x, arg = 0x%x\n", cmd, arg);
-#endif
switch (cmd)
{
case TCSBRK:
/* send BRK to line */
+ NAS_DEBUG(__FUNCTION__ "() Send break\n");
retval = tty_check_change(tty);
if (retval)
return retval;
@@ -730,8 +716,10 @@
nas_send_break(port,HZ/4);
return 0;
break;
+
case TCSBRKP:
/* send BRK to line */
+ NAS_DEBUG(__FUNCTION__ "() Send break\n");
retval = tty_check_change(tty);
if (retval)
return retval;
@@ -739,16 +727,19 @@
nas_send_break(port,arg ? arg*(HZ/10) : HZ/4);
return 0;
break;
+
default:
- if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ NAS_DEBUG(__FUNCTION__ "() Unsupported ioctl cmd = 0x%x, arg = 0x%x\n", (int) cmd, (int) arg);
+ return -ENOIOCTLCMD; // not supported
+/* if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ NAS_DEBUG(__FUNCTION__ "() cmd = 0x%x, arg = 0x%x\n", (int) cmd, (int) arg);
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
+*/
}
-
- return -ENOIOCTLCMD; // not supported
}
//
@@ -759,9 +750,7 @@
static void
nas_throttle(struct tty_struct * tty)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_throttle: called\n");
-#endif
+ NAS_DEBUG(__FUNCTION__ "()\n");
}
//
@@ -772,9 +761,7 @@
static void
nas_unthrottle(struct tty_struct * tty)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_unthrottle: called\n");
-#endif
+ NAS_DEBUG(__FUNCTION__ "()\n");
}
//
@@ -785,9 +772,17 @@
static void
nas_set_termios(struct tty_struct *tty, struct termios *old_termios)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_set_termios: called\n");
-#endif
+ struct nas_port *port = (struct nas_port *) tty->driver_data;
+ volatile netarm_serial_channel_t *regs = port->registers;
+ int baud;
+
+ NAS_DEBUG(__FUNCTION__ "()\n");
+
+ /* At least set baudrate */
+ baud = nas_tty_get_baud_rate(port->tty);
+ port->baud = baud;
+ regs->bitrate = NETARM_SER_BR_X16(baud);
+ regs->rx_char_timer = NETARM_SER_RXGAP(baud);
}
//
@@ -800,9 +795,7 @@
static void
nas_stop(struct tty_struct *tty)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_stop: called\n");
-#endif
+ NAS_DEBUG(__FUNCTION__ "()\n");
}
//
@@ -815,9 +808,7 @@
static void
nas_start(struct tty_struct *tty)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_start: called\n");
-#endif
+ NAS_DEBUG(__FUNCTION__ "()\n");
}
//
@@ -827,9 +818,7 @@
static void
nas_hangup(struct tty_struct *tty)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_hangup: called\n");
-#endif
+ NAS_DEBUG(__FUNCTION__ "()\n");
}
//
@@ -901,25 +890,23 @@
}
#if defined(CONFIG_ARCH_NETARM)
+
+
//
// Handler for transmit interrupts
//
static void
nas_tx_interrupt_1(int irq, void *dev_id, struct pt_regs *regs)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_tx_interrupt_0: int!\n");
-#endif
-
+ NAS_DEBUG(__FUNCTION__ "() int!\n");
nas_tx_interrupt(&nas_ports[0]) ;
}
static void
nas_tx_interrupt_2(int irq, void *dev_id, struct pt_regs *regs)
{
-#ifdef NAS_DEBUG_VERBOSE
+ NAS_DEBUG(__FUNCTION__ "() int!\n");
printk("nas_tx_interrupt_1: int!\n");
-#endif
nas_tx_interrupt(&nas_ports[0]) ;
}
@@ -927,14 +914,15 @@
static void
nas_tx_interrupt(struct nas_port *port)
{
+#if 0
struct tty_struct *tty = port->tty;
char ch;
int char_count = 0;
unsigned int status;
volatile netarm_serial_channel_t *regs = port->registers ;
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_tx_interrupt: int!\n");
#endif
+
+ NAS_DEBUG(__FUNCTION__ "() int!\n");
}
//
@@ -943,20 +931,14 @@
static void
nas_rx_interrupt_1(int irq, void *dev_id, struct pt_regs *regs)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_rx_interrupt: int!\n");
-#endif
-
+ NAS_DEBUG(__FUNCTION__ "() int!\n");
nas_rx_interrupt(&nas_ports[0]) ;
}
static void
nas_rx_interrupt_2(int irq, void *dev_id, struct pt_regs *regs)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_rx_interrupt: int!\n");
-#endif
-
+ NAS_DEBUG(__FUNCTION__ "() int!\n");
nas_rx_interrupt(&nas_ports[1]) ;
}
@@ -965,32 +947,29 @@
{
struct tty_struct *tty = port->tty;
unsigned int ch_uint;
- char ch;
- int ch_count;
int buf_count;
unsigned int status;
volatile unsigned int *fifo;
volatile unsigned char *fifo_char;
volatile netarm_serial_channel_t *regs = port->registers ;
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_rx_interrupt: int!\n");
-#endif
- /*printk("nas_rx_interrupt: int!\n");*/
- ch_count = 0 ;
+// NAS_DEBUG("nas_rx_interrupt: int!\n");
+ buf_count = 0 ;
fifo = (volatile unsigned int*)&(regs->fifo) ;
+ /* Service any pending interupts */
do
{
status = regs->status_a ;
+ fifo_char = (volatile unsigned char*) &ch_uint ;
+ /* FIXME : do we need to mask the status ??? as in serial.c */
+
if (status & NETARM_SER_STATA_RX_RDY )
{
/* need to read the whole buffer (1 to 4 bytes) */
ch_uint = *fifo ;
- fifo_char = &ch_uint ;
-
/* check the status word to see how many bytes are pending */
buf_count = NETARM_SER_STATA_RXFDB(status) ;
@@ -1009,28 +988,19 @@
buf_count = 1 ;
break;
default:
- printk("AIEE!! GARBAGE!\n");
+ NAS_DEBUG(__FUNCTION__ "() AIEE!! GARBAGE!\n");
}
/*printk("nas_rx_interrupt: read : %c\n",ch);*/
-#if 1
+#if 0
regs->status_a = NETARM_SER_STATA_CLR_ALL ;
#endif
}
- else
- {
- ch = 0;
- }
-
- /* don't want to overrun */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- {
- break;
- }
-
+
/* handle port error conditions */
if (status & NETARM_SER_STATA_RX_BRK )
{
*tty->flip.flag_buf_ptr = TTY_BREAK ;
+ NAS_DEBUG(__FUNCTION__ "() got break\n");
/* FIXME : do we need to handle ASYNC_SAK ??? as in serial.c */
}
else if ( status & NETARM_SER_STATA_RX_PARERR )
@@ -1053,24 +1023,26 @@
*tty->flip.flag_buf_ptr = 0 ;
}
-#if 0
+ /* Now clear all interrupts */
regs->status_a = NETARM_SER_STATA_CLR_ALL ;
-#endif
-
+
+ /* don't want to overrun */
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ {
+ break;
+ }
+
while ( buf_count-- > 0 )
{
- tty->flip.count++;
+ tty->flip.count++;
- /* ohyea... handle data also */
- *tty->flip.char_buf_ptr++ = *fifo_char ;
- fifo_char++ ;
+ /* ohyea... handle data also */
+ *tty->flip.char_buf_ptr++ = *fifo_char ;
+ fifo_char++ ;
}
- /* read status anew */
- status = regs->status_a ;
- /* FIXME : do we need to mask the status ??? as in serial.c */
} while ( status & NETARM_SER_STATA_RX_RDY ) ;
-
+
regs->ctrl_a |= NETARM_SER_CTLA_ENABLE | NETARM_SER_CTLA_IE_RX_RDY |
NETARM_SER_CTLA_IE_RX_FULL ;
@@ -1131,9 +1103,8 @@
static void
nas_do_serial_bh(void)
{
-#ifdef NAS_DEBUG_VERBOSE
- printk("nas_do_serial_bh: called\n");
-#endif
+ NAS_DEBUG(__FUNCTION__ "()\n");
+
#ifdef POLLED_SERIAL
run_task_queue(&poll_serial_tqueue);
#endif
This message resent by the uclinux-dev@uclinux.org list server http://www.uClinux.org/
This archive was generated by hypermail 2.1.4 : Thu Sep 19 2002 - 13:19:38 EDT