Facebook Social Icon Twitter Social Icon YouTube Social Icon

Using Moxa NPort 5450 Serial to IP Server with Linux Kernel Version 3.8.0 (tested with Ubuntu 13.04)

From M.Eng. René Schwarz, Bremen/Merseburg
Jump to: navigation, search

Unfortunately, Moxa's NPort Real TTY Driver for Linux is currently (version 1.18, released 2012/03/20) not compatible with Linux kernel 3.8.0. When I tried to install this driver for the NPort 5450 Serial to IP Server on my Ubuntu 13.04 machine (currently with kernel 3.8.0-27), the driver didn't compile. It turned out, that it is possible to patch the driver source code in order to get it work with Linux kernel 3.8.0 – here is a short documentation what I did.


Building the Patched Driver

  1. Download the NPort Real TTY Driver for Linux in version 1.18.7 Build 13050317 from this forum post (unofficial build, Russian forum)
  2. Prepare the code base for compilation:
    user@ubuntu:~$ tar -xzvf npreal2_1.18.7_Build_13050317.tgz -C /tmp
    user@ubuntu:~$ cd /tmp/moxa
    user@ubuntu:/tmp/moxa$ wget https://downloads.rene-schwarz.com/download/npreal2.c_1-18-7_b13050317.patch
    user@ubuntu:/tmp/moxa$ patch < npreal2.c_1-18-7_b13050317.patch
    
    • Extract the driver source code to /tmp (line 1).
    • Download the patch for npreal2.c from here (lines 2 et seq.).
    • Patch the C source file npreal2.c (line 4).
  3. You are now ready to compile and install the driver (root privileges required):
    user@ubuntu:/tmp/moxa$ sudo ./mxinst
    
  4. The driver should compile now without any errors. If so, the driver should be properly installed now and you can configure it (please refer to /tmp/moxa/README.TXT).


Changes for Linux Kernel 3.8.0

The changes that were necessary to let the driver compile against the Linux kernel 3.8.0 are the following (identical to the patch provided above):

  1--- npreal2.c	Fri May 03 11:52:43 2013
  2+++ npreal2.c	Tue Aug 06 16:58:36 2013
  3@@ -426,6 +426,39 @@
  4 static struct semaphore 	npvar_tmp_buf_sem = MUTEX;
  5 #endif
  6 
  7+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0))
  8+struct n_tty_data {
  9+	unsigned int column;
 10+	unsigned long overrun_time;
 11+	int num_overrun;
 12+
 13+	unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
 14+	unsigned char echo_overrun:1;
 15+
 16+	DECLARE_BITMAP(process_char_map, 256);
 17+	DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE);
 18+
 19+	char *read_buf;
 20+	int read_head;
 21+	int read_tail;
 22+	int read_cnt;
 23+	int minimum_to_wake;
 24+
 25+	unsigned char *echo_buf;
 26+	unsigned int echo_pos;
 27+	unsigned int echo_cnt;
 28+
 29+	int canon_data;
 30+	unsigned long canon_head;
 31+	unsigned int canon_column;
 32+
 33+	struct mutex atomic_read_lock;
 34+	struct mutex output_lock;
 35+	struct mutex echo_lock;
 36+	raw_spinlock_t read_lock;
 37+};
 38+#endif
 39+
 40 #if (LINUX_VERSION_CODE < VERSION_CODE(2,4,0))
 41 static struct inode_operations npreal_net_iops;
 42 #endif
 43@@ -3436,7 +3469,21 @@
 44 }
 45 #endif
 46 
 47-#if ((LINUX_VERSION_CODE > VERSION_CODE(2,6,15)) || ((LINUX_VERSION_CODE == VERSION_CODE(2,6,15)) && defined(FEDORA)))
 48+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0))
 49+static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
 50+{
 51+    /* Dumb strategy for now - should keep some stats */
 52+    /* 	printk("Flip dispose %p\n", b); */
 53+    if (b->size >= 512)
 54+        kfree(b);
 55+    else
 56+    {
 57+        b->next = tty->port->buf.free;
 58+        tty->port->buf.free = b;
 59+    }
 60+}
 61+#endif
 62+#if ((LINUX_VERSION_CODE > VERSION_CODE(2,6,15) && LINUX_VERSION_CODE < VERSION_CODE(3,8,0)) || ((LINUX_VERSION_CODE == VERSION_CODE(2,6,15)) && defined(FEDORA)))
 63 static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
 64 {
 65     /* Dumb strategy for now - should keep some stats */
 66@@ -3514,11 +3561,20 @@
 67         tty->ldisc.receive_buf(tty, cp, fp, count);
 68         //DBGPRINT(MX_DEBUG_TRACE, "flush %d bytes\n", count);
 69 #else
 70-        spin_lock_irqsave(&tty->buf.lock, flags);
 71+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0))
 72+        spin_lock_irqsave(&tty->port->buf.lock, flags);
 73+	head = tty->port->buf.head;
 74+#else
 75+        spin_lock_irqsave(&tty->port->buf.lock, flags);
 76         head = tty->buf.head;
 77+#endif
 78         if (head != NULL)
 79         {
 80+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0))
 81+            tty->port->buf.head = NULL;
 82+#else
 83             tty->buf.head = NULL;
 84+#endif
 85             for (;;)
 86             {
 87                 count = head->commit - head->read;
 88@@ -3545,17 +3601,29 @@
 89                 cp = head->char_buf_ptr + head->read;
 90                 fp = head->flag_buf_ptr + head->read;
 91                 head->read += count;
 92+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0))
 93+                spin_unlock_irqrestore(&tty->port->buf.lock, flags);
 94+#else
 95                 spin_unlock_irqrestore(&tty->buf.lock, flags);
 96+#endif
 97 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,27))
 98                 disc->ops->receive_buf(tty, cp, fp, count);
 99 #else
100                 disc->receive_buf(tty, cp, fp, count);
101 #endif
102+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0))
103+                spin_lock_irqsave(&tty->port->buf.lock, flags);
104+            }
105+            tty->port->buf.head = head;
106+        }
107+        spin_unlock_irqrestore(&tty->port->buf.lock, flags);
108+#else
109                 spin_lock_irqsave(&tty->buf.lock, flags);
110             }
111             tty->buf.head = head;
112         }
113         spin_unlock_irqrestore(&tty->buf.lock, flags);
114+#endif
115         tty_ldisc_deref(disc);
116 #endif
117     }
118@@ -4303,6 +4371,7 @@
119     int cnt;
120     struct npreal_struct *info;
121     struct tty_struct *	tty;
122+    struct n_tty_data *ldata;
123 
124     /*
125      *  Get the node pointer, and quit if it doesn't exist.
126@@ -4350,6 +4419,10 @@
127         up(&info->rx_semaphore);
128         goto done;
129     }
130+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0))
131+    ldata = tty->disc_data;
132+#endif
133+
134 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
135 #if 1
136     if(!info->tty->low_latency)
137@@ -4392,8 +4465,11 @@
138         	* that erase characters will be handled.  Other excess
139         	* characters will be beeped.
140         	*/
141-
142-        if (!tty->icanon || tty->canon_data)
143+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0))
144+	if (!ldata->icanon || ldata->canon_data)
145+#else
146+	if (!tty->icanon || tty->canon_data)
147+#endif
148         {
149 #if (LINUX_VERSION_CODE <  VERSION_CODE(2,1,0))
150             if (!set_bit(TTY_THROTTLED,&tty->flags))
151@@ -4408,9 +4484,15 @@
152         up(&info->rx_semaphore);
153         goto done;
154     }
155+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0))
156+    if (!ldata->icanon || ldata->canon_data)
157+    {
158+        if ((cnt = MIN(cnt,(N_TTY_BUF_SIZE-1) - ldata->read_cnt )) <= 0)
159+#else
160     if (!tty->icanon || tty->canon_data)
161     {
162         if ((cnt = MIN(cnt,(N_TTY_BUF_SIZE-1) - tty->read_cnt )) <= 0)
163+#endif
164         {
165 
166             /*


Driver Support for Other Moxa Products

This driver should also work for other Moxa products, namely the following ones:

  • CN2510 Series
  • CN2610/2650 Series
  • MiiNePort E1 Series
  • MiiNePort E2 Series
  • MiiNePort E3 Series
  • MiiNePort W1 Series
  • NE-4000T/NE-4000T-ST
  • NE-4100T
  • NE-4110A
  • NE-4110S
  • NE-4120A
  • NE-4120S
  • NPort 5110/5130/5150 Series
  • NPort 5110A/5130A/5150A Series
  • NPort 5130
  • NPort 5150
  • NPort 5150AI-M12/5250AI-M12/5450AI-M12 Series
  • NPort 5210/5230/5232 Series
  • NPort 5210A/5230A/5250A Series
  • NPort 5230 Series
  • NPort 5410/5430/5450 Series
  • NPort 5430 Series
  • NPort 5450 Series
  • NPort 5600-8-DT/5650-8-DT Series
  • NPort 5610/5630 Series
  • NPort 5610-8-DTL/5650-8-DTL Series
  • NPort 5650 Series
  • NPort 6150 Series
  • NPort 6250 Series
  • NPort 6450 Series
  • NPort 6610/6650 Series
  • NPort DE-311M
  • NPort Express DE-211
  • NPort Express DE-311
  • NPort IA5150/5250 Series
  • NPort IA5150A/IA5250A/IA5450A Series
  • NPort P5150A Series
  • NPort S8455/S8458 Series
  • NPort Server Lite DE-301/302/304/331/332/334
  • NPort Server Pro DE-303, DE-308
  • NPort W2004 Series
  • NPort W2150/2250 Plus
  • NPort W2150A/W2250A
  • NPort W2250/2150
  • WE-2100T


References