Special:Badtitle/NS100:EN/Using Moxa NPort 5450 Serial to IP Server with Linux Kernel Version 3.8.0 (tested with Ubuntu 13.04)
<summary>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.</summary>
Building the Patched Driver[edit]
- 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:
<syntaxhighlight lang="bash">
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
</syntaxhighlight>
- Extract the driver source code to
/tmp(line 1). - Download the patch for
npreal2.cfrom 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): <syntaxhighlight lang="bash"> user@ubuntu:/tmp/moxa$ sudo ./mxinst </syntaxhighlight>
- 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[edit]
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):
<syntaxhighlight lang="diff" line> --- npreal2.c Fri May 03 11:52:43 2013 +++ npreal2.c Tue Aug 06 16:58:36 2013 @@ -426,6 +426,39 @@
static struct semaphore npvar_tmp_buf_sem = MUTEX; #endif
+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0)) +struct n_tty_data { + unsigned int column; + unsigned long overrun_time; + int num_overrun; + + unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; + unsigned char echo_overrun:1; + + DECLARE_BITMAP(process_char_map, 256); + DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE); + + char *read_buf; + int read_head; + int read_tail; + int read_cnt; + int minimum_to_wake; + + unsigned char *echo_buf; + unsigned int echo_pos; + unsigned int echo_cnt; + + int canon_data; + unsigned long canon_head; + unsigned int canon_column; + + struct mutex atomic_read_lock; + struct mutex output_lock; + struct mutex echo_lock; + raw_spinlock_t read_lock; +}; +#endif +
#if (LINUX_VERSION_CODE < VERSION_CODE(2,4,0)) static struct inode_operations npreal_net_iops; #endif
@@ -3436,7 +3469,21 @@
} #endif
-#if ((LINUX_VERSION_CODE > VERSION_CODE(2,6,15)) || ((LINUX_VERSION_CODE == VERSION_CODE(2,6,15)) && defined(FEDORA))) +#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0)) +static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) +{ + /* Dumb strategy for now - should keep some stats */ + /* printk("Flip dispose %p\n", b); */ + if (b->size >= 512) + kfree(b); + else + { + b->next = tty->port->buf.free; + tty->port->buf.free = b; + } +} +#endif +#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)))
static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
{
/* Dumb strategy for now - should keep some stats */
@@ -3514,11 +3561,20 @@
tty->ldisc.receive_buf(tty, cp, fp, count);
//DBGPRINT(MX_DEBUG_TRACE, "flush %d bytes\n", count);
#else
- spin_lock_irqsave(&tty->buf.lock, flags); +#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0)) + spin_lock_irqsave(&tty->port->buf.lock, flags); + head = tty->port->buf.head; +#else + spin_lock_irqsave(&tty->port->buf.lock, flags);
head = tty->buf.head;
+#endif
if (head != NULL)
{
+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0)) + tty->port->buf.head = NULL; +#else
tty->buf.head = NULL;
+#endif
for (;;)
{
count = head->commit - head->read;
@@ -3545,17 +3601,29 @@
cp = head->char_buf_ptr + head->read;
fp = head->flag_buf_ptr + head->read;
head->read += count;
+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0)) + spin_unlock_irqrestore(&tty->port->buf.lock, flags); +#else
spin_unlock_irqrestore(&tty->buf.lock, flags);
+#endif
#if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,27))
disc->ops->receive_buf(tty, cp, fp, count);
#else
disc->receive_buf(tty, cp, fp, count);
#endif
+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0)) + spin_lock_irqsave(&tty->port->buf.lock, flags); + } + tty->port->buf.head = head; + } + spin_unlock_irqrestore(&tty->port->buf.lock, flags); +#else
spin_lock_irqsave(&tty->buf.lock, flags);
}
tty->buf.head = head;
}
spin_unlock_irqrestore(&tty->buf.lock, flags);
+#endif
tty_ldisc_deref(disc);
#endif
}
@@ -4303,6 +4371,7 @@
int cnt;
struct npreal_struct *info;
struct tty_struct * tty;
+ struct n_tty_data *ldata;
/*
* Get the node pointer, and quit if it doesn't exist.
@@ -4350,6 +4419,10 @@
up(&info->rx_semaphore);
goto done;
}
+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0)) + ldata = tty->disc_data; +#endif +
#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
#if 1
if(!info->tty->low_latency)
@@ -4392,8 +4465,11 @@
* that erase characters will be handled. Other excess
* characters will be beeped.
*/
- - if (!tty->icanon || tty->canon_data) +#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0)) + if (!ldata->icanon || ldata->canon_data) +#else + if (!tty->icanon || tty->canon_data) +#endif
{
#if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
if (!set_bit(TTY_THROTTLED,&tty->flags))
@@ -4408,9 +4484,15 @@
up(&info->rx_semaphore);
goto done;
}
+#if (LINUX_VERSION_CODE >= VERSION_CODE(3,8,0)) + if (!ldata->icanon || ldata->canon_data) + { + if ((cnt = MIN(cnt,(N_TTY_BUF_SIZE-1) - ldata->read_cnt )) <= 0) +#else
if (!tty->icanon || tty->canon_data)
{
if ((cnt = MIN(cnt,(N_TTY_BUF_SIZE-1) - tty->read_cnt )) <= 0)
+#endif
{
/*
</syntaxhighlight>
Driver Support for Other Moxa Products[edit]
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[edit]
- 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
Science