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
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
- Download the NPort Real TTY Driver for Linux in version 1.18.7 Build 13050317 from this forum post (unofficial build, Russian forum)
- 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).
- Extract the driver source code to
- You are now ready to compile and install the driver (root privileges required):
user@ubuntu:/tmp/moxa$ sudo ./mxinst
- 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
- https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/commit/?id=ecbbfd44a08fa80e0d664814efd4c187721b85f6
- https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/commit/?id=ba2e68ac6157004ee4922fb39ebd9459bbae883e
- https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/commit/?id=53c5ee2cfb4dadc4f5c24fe671e2fbfc034c875e
- http://lxr.free-electrons.com/source/drivers/tty/n_tty.c