summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPaul Fulghum <paulkf@microgate.com>2010-10-28 00:34:22 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-28 03:03:14 +0200
commit9807224f1dce5fb746ee33fb67ea2e38dafe3e9c (patch)
treed9a9bdb1ae4196dec24b9c98bdd753c7b72de4df /drivers
parentdrivers/char/synclink_gt.c: fix information leak to userland (diff)
downloadlinux-9807224f1dce5fb746ee33fb67ea2e38dafe3e9c.tar.xz
linux-9807224f1dce5fb746ee33fb67ea2e38dafe3e9c.zip
drivers/char/synclink_gt.c: add extended sync feature
Add support for extended byte synchronous mode feature of hardware. Signed-off-by: Paul Fulghum <paulkf@microgate.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/synclink_gt.c111
1 files changed, 108 insertions, 3 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 9f7fc71474b4..d01fffeac951 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -301,6 +301,8 @@ struct slgt_info {
unsigned int rx_pio;
unsigned int if_mode;
unsigned int base_clock;
+ unsigned int xsync;
+ unsigned int xctrl;
/* device status */
@@ -405,6 +407,8 @@ static MGSL_PARAMS default_params = {
#define TDCSR 0x94 /* tx DMA control/status */
#define RDDAR 0x98 /* rx DMA descriptor address */
#define TDDAR 0x9c /* tx DMA descriptor address */
+#define XSR 0x40 /* extended sync pattern */
+#define XCR 0x44 /* extended control */
#define RXIDLE BIT14
#define RXBREAK BIT14
@@ -517,6 +521,10 @@ static int set_interface(struct slgt_info *info, int if_mode);
static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
+static int get_xsync(struct slgt_info *info, int __user *if_mode);
+static int set_xsync(struct slgt_info *info, int if_mode);
+static int get_xctrl(struct slgt_info *info, int __user *if_mode);
+static int set_xctrl(struct slgt_info *info, int if_mode);
/*
* driver functions
@@ -1056,6 +1064,14 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return get_gpio(info, argp);
case MGSL_IOCWAITGPIO:
return wait_gpio(info, argp);
+ case MGSL_IOCGXSYNC:
+ return get_xsync(info, argp);
+ case MGSL_IOCSXSYNC:
+ return set_xsync(info, (int)arg);
+ case MGSL_IOCGXCTRL:
+ return get_xctrl(info, argp);
+ case MGSL_IOCSXCTRL:
+ return set_xctrl(info, (int)arg);
}
mutex_lock(&info->port.mutex);
switch (cmd) {
@@ -1213,12 +1229,16 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
case MGSL_IOCSGPIO:
case MGSL_IOCGGPIO:
case MGSL_IOCWAITGPIO:
+ case MGSL_IOCGXSYNC:
+ case MGSL_IOCGXCTRL:
case MGSL_IOCSTXIDLE:
case MGSL_IOCTXENABLE:
case MGSL_IOCRXENABLE:
case MGSL_IOCTXABORT:
case TIOCMIWAIT:
case MGSL_IOCSIF:
+ case MGSL_IOCSXSYNC:
+ case MGSL_IOCSXCTRL:
rc = ioctl(tty, file, cmd, arg);
break;
}
@@ -1961,6 +1981,7 @@ static void bh_handler(struct work_struct *work)
case MGSL_MODE_RAW:
case MGSL_MODE_MONOSYNC:
case MGSL_MODE_BISYNC:
+ case MGSL_MODE_XSYNC:
while(rx_get_buf(info));
break;
}
@@ -2889,6 +2910,69 @@ static int set_interface(struct slgt_info *info, int if_mode)
return 0;
}
+static int get_xsync(struct slgt_info *info, int __user *xsync)
+{
+ DBGINFO(("%s get_xsync=%x\n", info->device_name, info->xsync));
+ if (put_user(info->xsync, xsync))
+ return -EFAULT;
+ return 0;
+}
+
+/*
+ * set extended sync pattern (1 to 4 bytes) for extended sync mode
+ *
+ * sync pattern is contained in least significant bytes of value
+ * most significant byte of sync pattern is oldest (1st sent/detected)
+ */
+static int set_xsync(struct slgt_info *info, int xsync)
+{
+ unsigned long flags;
+
+ DBGINFO(("%s set_xsync=%x)\n", info->device_name, xsync));
+ spin_lock_irqsave(&info->lock, flags);
+ info->xsync = xsync;
+ wr_reg32(info, XSR, xsync);
+ spin_unlock_irqrestore(&info->lock, flags);
+ return 0;
+}
+
+static int get_xctrl(struct slgt_info *info, int __user *xctrl)
+{
+ DBGINFO(("%s get_xctrl=%x\n", info->device_name, info->xctrl));
+ if (put_user(info->xctrl, xctrl))
+ return -EFAULT;
+ return 0;
+}
+
+/*
+ * set extended control options
+ *
+ * xctrl[31:19] reserved, must be zero
+ * xctrl[18:17] extended sync pattern length in bytes
+ * 00 = 1 byte in xsr[7:0]
+ * 01 = 2 bytes in xsr[15:0]
+ * 10 = 3 bytes in xsr[23:0]
+ * 11 = 4 bytes in xsr[31:0]
+ * xctrl[16] 1 = enable terminal count, 0=disabled
+ * xctrl[15:0] receive terminal count for fixed length packets
+ * value is count minus one (0 = 1 byte packet)
+ * when terminal count is reached, receiver
+ * automatically returns to hunt mode and receive
+ * FIFO contents are flushed to DMA buffers with
+ * end of frame (EOF) status
+ */
+static int set_xctrl(struct slgt_info *info, int xctrl)
+{
+ unsigned long flags;
+
+ DBGINFO(("%s set_xctrl=%x)\n", info->device_name, xctrl));
+ spin_lock_irqsave(&info->lock, flags);
+ info->xctrl = xctrl;
+ wr_reg32(info, XCR, xctrl);
+ spin_unlock_irqrestore(&info->lock, flags);
+ return 0;
+}
+
/*
* set general purpose IO pin state and direction
*
@@ -3768,7 +3852,9 @@ module_exit(slgt_exit);
#define CALC_REGADDR() \
unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \
if (addr >= 0x80) \
- reg_addr += (info->port_num) * 32;
+ reg_addr += (info->port_num) * 32; \
+ else if (addr >= 0x40) \
+ reg_addr += (info->port_num) * 16;
static __u8 rd_reg8(struct slgt_info *info, unsigned int addr)
{
@@ -4187,7 +4273,13 @@ static void sync_mode(struct slgt_info *info)
/* TCR (tx control)
*
- * 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync
+ * 15..13 mode
+ * 000=HDLC/SDLC
+ * 001=raw bit synchronous
+ * 010=asynchronous/isochronous
+ * 011=monosync byte synchronous
+ * 100=bisync byte synchronous
+ * 101=xsync byte synchronous
* 12..10 encoding
* 09 CRC enable
* 08 CRC32
@@ -4202,6 +4294,9 @@ static void sync_mode(struct slgt_info *info)
val = BIT2;
switch(info->params.mode) {
+ case MGSL_MODE_XSYNC:
+ val |= BIT15 + BIT13;
+ break;
case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
case MGSL_MODE_BISYNC: val |= BIT15; break;
case MGSL_MODE_RAW: val |= BIT13; break;
@@ -4256,7 +4351,13 @@ static void sync_mode(struct slgt_info *info)
/* RCR (rx control)
*
- * 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync
+ * 15..13 mode
+ * 000=HDLC/SDLC
+ * 001=raw bit synchronous
+ * 010=asynchronous/isochronous
+ * 011=monosync byte synchronous
+ * 100=bisync byte synchronous
+ * 101=xsync byte synchronous
* 12..10 encoding
* 09 CRC enable
* 08 CRC32
@@ -4268,6 +4369,9 @@ static void sync_mode(struct slgt_info *info)
val = 0;
switch(info->params.mode) {
+ case MGSL_MODE_XSYNC:
+ val |= BIT15 + BIT13;
+ break;
case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
case MGSL_MODE_BISYNC: val |= BIT15; break;
case MGSL_MODE_RAW: val |= BIT13; break;
@@ -4684,6 +4788,7 @@ static bool rx_get_buf(struct slgt_info *info)
switch(info->params.mode) {
case MGSL_MODE_MONOSYNC:
case MGSL_MODE_BISYNC:
+ case MGSL_MODE_XSYNC:
/* ignore residue in byte synchronous modes */
if (desc_residue(info->rbufs[i]))
count--;