+ssize_t rtlx_write(int index, void *buffer, size_t count, int user)
+{
+ struct rtlx_channel *rt;
+ size_t fl;
+
+ if (rtlx == NULL)
+ return(-ENOSYS);
+
+ rt = &rtlx->channel[index];
+
+ /* total number of bytes to copy */
+ count = min(count,
+ (size_t)write_spacefree(rt->rt_read, rt->rt_write,
+ rt->buffer_size));
+
+ /* first bit from write pointer to the end of the buffer, or count */
+ fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
+
+ copy_from (&rt->rt_buffer[rt->rt_write], buffer, fl, user);
+
+ /* if there's any left copy to the beginning of the buffer */
+ if( count - fl )
+ copy_from (rt->rt_buffer, buffer + fl, count - fl, user);
+
+ rt->rt_write += count;
+ rt->rt_write %= rt->buffer_size;
+
+ return(count);
+}
+
+
+static int file_open(struct inode *inode, struct file *filp)
+{
+ int minor = iminor(inode);
+
+ return rtlx_open(minor, (filp->f_flags & O_NONBLOCK) ? 0 : 1);
+}
+
+static int file_release(struct inode *inode, struct file *filp)
+{
+ int minor = iminor(inode);
+
+ return rtlx_release(minor);
+}
+
+static unsigned int file_poll(struct file *file, poll_table * wait)
+{
+ int minor;
+ unsigned int mask = 0;
+
+ minor = iminor(file->f_path.dentry->d_inode);
+
+ poll_wait(file, &channel_wqs[minor].rt_queue, wait);
+ poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+
+ if (rtlx == NULL)
+ return 0;
+
+ /* data available to read? */
+ if (rtlx_read_poll(minor, 0))
+ mask |= POLLIN | POLLRDNORM;
+
+ /* space to write */
+ if (rtlx_write_poll(minor))
+ mask |= POLLOUT | POLLWRNORM;
+
+ return mask;
+}
+
+static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
+ loff_t * ppos)
+{
+ int minor = iminor(file->f_path.dentry->d_inode);
+
+ /* data available? */
+ if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) {
+ return 0; // -EAGAIN makes cat whinge
+ }
+
+ return rtlx_read(minor, buffer, count, 1);
+}
+
+static ssize_t file_write(struct file *file, const char __user * buffer,