diff options
Diffstat (limited to 'drivers/char/moxa.c')
-rw-r--r-- | drivers/char/moxa.c | 360 |
1 files changed, 139 insertions, 221 deletions
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index fdfa7783e992..f737fbb8598c 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -150,6 +150,12 @@ struct moxa_port { ushort breakCnt; }; +struct mon_str { + int tick; + int rxcnt[MAX_PORTS]; + int txcnt[MAX_PORTS]; +}; + /* statusflags */ #define TXSTOPPED 0x1 #define LOWWAIT 0x2 @@ -161,6 +167,8 @@ struct moxa_port { #define WAKEUP_CHARS 256 static int ttymajor = MOXAMAJOR; +static struct mon_str moxaLog; +static unsigned int moxaFuncTout = HZ / 2; /* Variables for insmod */ #ifdef MODULE static unsigned long baseaddr[MAX_BOARDS]; @@ -192,7 +200,6 @@ static void moxa_flush_buffer(struct tty_struct *); static int moxa_chars_in_buffer(struct tty_struct *); static void moxa_flush_chars(struct tty_struct *); static void moxa_put_char(struct tty_struct *, unsigned char); -static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static void moxa_throttle(struct tty_struct *); static void moxa_unthrottle(struct tty_struct *); static void moxa_set_termios(struct tty_struct *, struct ktermios *); @@ -213,7 +220,6 @@ static void moxa_receive_data(struct moxa_port *); /* * moxa board interface functions: */ -static int MoxaDriverIoctl(struct tty_struct *, unsigned int, unsigned long); static int MoxaDriverPoll(void); static void MoxaPortEnable(struct moxa_port *); static void MoxaPortDisable(struct moxa_port *); @@ -233,11 +239,131 @@ static int MoxaPortTxFree(struct moxa_port *); static void MoxaPortTxDisable(struct moxa_port *); static void MoxaPortTxEnable(struct moxa_port *); static int MoxaPortResetBrkCnt(struct moxa_port *); -static void MoxaPortSendBreak(struct moxa_port *, int); static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *); static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *); static void MoxaSetFifo(struct moxa_port *port, int enable); +/* + * I/O functions + */ + +static void moxa_wait_finish(void __iomem *ofsAddr) +{ + unsigned long end = jiffies + moxaFuncTout; + + while (readw(ofsAddr + FuncCode) != 0) + if (time_after(jiffies, end)) + return; + if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit()) + printk(KERN_WARNING "moxa function expired\n"); +} + +static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg) +{ + writew(arg, ofsAddr + FuncArg); + writew(cmd, ofsAddr + FuncCode); + moxa_wait_finish(ofsAddr); +} + +/* + * TTY operations + */ + +static int moxa_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct moxa_port *ch = tty->driver_data; + void __user *argp = (void __user *)arg; + int status; + + if (tty->index == MAX_PORTS) { + if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE && + cmd != MOXA_GETMSTATUS) + return -EINVAL; + } else if (!ch) + return -ENODEV; + + switch (cmd) { + case MOXA_GETDATACOUNT: + moxaLog.tick = jiffies; + return copy_to_user(argp, &moxaLog, sizeof(moxaLog)) ? + -EFAULT : 0; + case MOXA_FLUSH_QUEUE: + MoxaPortFlushData(ch, arg); + return 0; + case MOXA_GET_IOQUEUE: { + struct moxaq_str __user *argm = argp; + struct moxaq_str tmp; + struct moxa_port *p; + unsigned int i, j; + + for (i = 0; i < MAX_BOARDS; i++) { + p = moxa_boards[i].ports; + for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { + memset(&tmp, 0, sizeof(tmp)); + if (moxa_boards[i].ready) { + tmp.inq = MoxaPortRxQueue(p); + tmp.outq = MoxaPortTxQueue(p); + } + if (copy_to_user(argm, &tmp, sizeof(tmp))) + return -EFAULT; + } + } + return 0; + } case MOXA_GET_OQUEUE: + status = MoxaPortTxQueue(ch); + return put_user(status, (unsigned long __user *)argp); + case MOXA_GET_IQUEUE: + status = MoxaPortRxQueue(ch); + return put_user(status, (unsigned long __user *)argp); + case MOXA_GETMSTATUS: { + struct mxser_mstatus __user *argm = argp; + struct mxser_mstatus tmp; + struct moxa_port *p; + unsigned int i, j; + + for (i = 0; i < MAX_BOARDS; i++) { + p = moxa_boards[i].ports; + for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { + memset(&tmp, 0, sizeof(tmp)); + if (!moxa_boards[i].ready) + goto copy; + + status = MoxaPortLineStatus(p); + if (status & 1) + tmp.cts = 1; + if (status & 2) + tmp.dsr = 1; + if (status & 4) + tmp.dcd = 1; + + if (!p->tty || !p->tty->termios) + tmp.cflag = p->cflag; + else + tmp.cflag = p->tty->termios->c_cflag; +copy: + if (copy_to_user(argm, &tmp, sizeof(tmp))) + return -EFAULT; + } + } + return 0; + } + case TIOCGSERIAL: + return moxa_get_serial_info(ch, argp); + case TIOCSSERIAL: + return moxa_set_serial_info(ch, argp); + } + return -ENOIOCTLCMD; +} + +static void moxa_break_ctl(struct tty_struct *tty, int state) +{ + struct moxa_port *port = tty->driver_data; + + moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak, + Magic_code); +} + static const struct tty_operations moxa_ops = { .open = moxa_open, .close = moxa_close, @@ -254,6 +380,7 @@ static const struct tty_operations moxa_ops = { .stop = moxa_stop, .start = moxa_start, .hangup = moxa_hangup, + .break_ctl = moxa_break_ctl, .tiocmget = moxa_tiocmget, .tiocmset = moxa_tiocmset, }; @@ -262,6 +389,10 @@ static struct tty_driver *moxaDriver; static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); static DEFINE_SPINLOCK(moxa_lock); +/* + * HW init + */ + static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model) { switch (brd->boardType) { @@ -938,7 +1069,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) port = tty->index; if (port == MAX_PORTS) { - return (0); + return capable(CAP_SYS_ADMIN) ? 0 : -EPERM; } brd = &moxa_boards[port / MAX_PORTS_PER_BOARD]; if (!brd->ready) @@ -1123,8 +1254,8 @@ static int moxa_tiocmget(struct tty_struct *tty, struct file *file) struct moxa_port *ch = tty->driver_data; int flag = 0, dtr, rts; - if ((tty->index != MAX_PORTS) && (!ch)) - return (-EINVAL); + if (!ch) + return -EINVAL; MoxaPortGetLineOut(ch, &dtr, &rts); if (dtr) @@ -1149,8 +1280,8 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, int dtr, rts; port = tty->index; - if ((port != MAX_PORTS) && (!ch)) - return (-EINVAL); + if (!ch) + return -EINVAL; MoxaPortGetLineOut(ch, &dtr, &rts); if (set & TIOCM_RTS) @@ -1165,60 +1296,6 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, return 0; } -static int moxa_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct moxa_port *ch = tty->driver_data; - register int port; - void __user *argp = (void __user *)arg; - int retval; - - port = tty->index; - if ((port != MAX_PORTS) && (!ch)) - return (-EINVAL); - - switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return (retval); - moxa_setup_empty_event(tty); - tty_wait_until_sent(tty, 0); - if (!arg) - MoxaPortSendBreak(ch, 0); - return (0); - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return (retval); - moxa_setup_empty_event(tty); - tty_wait_until_sent(tty, 0); - MoxaPortSendBreak(ch, arg); - return (0); - case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)argp); - case TIOCSSOFTCAR: - if (get_user(retval, (int __user *)argp)) - return -EFAULT; - arg = retval; - tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - if (C_CLOCAL(tty)) - ch->asyncflags &= ~ASYNC_CHECK_CD; - else - ch->asyncflags |= ASYNC_CHECK_CD; - return (0); - case TIOCGSERIAL: - return moxa_get_serial_info(ch, argp); - - case TIOCSSERIAL: - return moxa_set_serial_info(ch, argp); - default: - retval = MoxaDriverIoctl(tty, cmd, arg); - } - return (retval); -} - static void moxa_throttle(struct tty_struct *tty) { struct moxa_port *ch = (struct moxa_port *) tty->driver_data; @@ -1533,38 +1610,17 @@ static void moxa_receive_data(struct moxa_port *ch) * Query */ -struct mon_str { - int tick; - int rxcnt[MAX_PORTS]; - int txcnt[MAX_PORTS]; -}; - #define DCD_changed 0x01 #define DCD_oldstate 0x80 static int moxaLowWaterChk; -static struct mon_str moxaLog; -static int moxaFuncTout = HZ / 2; -static void moxafunc(void __iomem *, int, ushort); -static void moxa_wait_finish(void __iomem *); static void moxa_low_water_check(void __iomem *); /***************************************************************************** * Driver level functions: * - * 2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); * * 3. MoxaDriverPoll(void); * *****************************************************************************/ -#define MOXA 0x400 -#define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */ -#define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */ -#define MOXA_GETDATACOUNT (MOXA + 23) -#define MOXA_GET_IOQUEUE (MOXA + 27) -#define MOXA_FLUSH_QUEUE (MOXA + 28) -#define MOXA_GET_CONF (MOXA + 35) /* configuration */ -#define MOXA_GET_MAJOR (MOXA + 63) -#define MOXA_GET_CUMAJOR (MOXA + 64) -#define MOXA_GETMSTATUS (MOXA + 65) static void MoxaPortFlushData(struct moxa_port *port, int mode) { @@ -1579,100 +1635,6 @@ static void MoxaPortFlushData(struct moxa_port *port, int mode) } } -static int MoxaDriverIoctl(struct tty_struct *tty, unsigned int cmd, - unsigned long arg) -{ - struct moxa_port *port = tty->driver_data; - int i; - int status; - void __user *argp = (void __user *)arg; - - if (tty->index == MAX_PORTS) { - if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_GETDATACOUNT) && - (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) && - (cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS)) - return (-EINVAL); - } - switch (cmd) { - case MOXA_GETDATACOUNT: - moxaLog.tick = jiffies; - if(copy_to_user(argp, &moxaLog, sizeof(struct mon_str))) - return -EFAULT; - return (0); - case MOXA_FLUSH_QUEUE: - MoxaPortFlushData(port, arg); - return (0); - case MOXA_GET_IOQUEUE: { - struct moxaq_str __user *argm = argp; - struct moxaq_str tmp; - struct moxa_port *p; - unsigned int j; - - for (i = 0; i < MAX_BOARDS; i++) { - p = moxa_boards[i].ports; - for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { - memset(&tmp, 0, sizeof(tmp)); - if (moxa_boards[i].ready) { - tmp.inq = MoxaPortRxQueue(p); - tmp.outq = MoxaPortTxQueue(p); - } - if (copy_to_user(argm, &tmp, sizeof(tmp))) - return -EFAULT; - } - } - return 0; - } case MOXA_GET_OQUEUE: - i = MoxaPortTxQueue(port); - return put_user(i, (unsigned long __user *)argp); - case MOXA_GET_IQUEUE: - i = MoxaPortRxQueue(port); - return put_user(i, (unsigned long __user *)argp); - case MOXA_GET_MAJOR: - if(copy_to_user(argp, &ttymajor, sizeof(int))) - return -EFAULT; - return 0; - case MOXA_GET_CUMAJOR: - i = 0; - if(copy_to_user(argp, &i, sizeof(int))) - return -EFAULT; - return 0; - case MOXA_GETMSTATUS: { - struct mxser_mstatus __user *argm = argp; - struct mxser_mstatus tmp; - struct moxa_port *p; - unsigned int j; - - for (i = 0; i < MAX_BOARDS; i++) { - p = moxa_boards[i].ports; - for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { - memset(&tmp, 0, sizeof(tmp)); - if (!moxa_boards[i].ready) - goto copy; - - status = MoxaPortLineStatus(p); - if (status & 1) - tmp.cts = 1; - if (status & 2) - tmp.dsr = 1; - if (status & 4) - tmp.dcd = 1; - - if (!p->tty || !p->tty->termios) - tmp.cflag = p->cflag; - else - tmp.cflag = p->tty->termios->c_cflag; -copy: - if (copy_to_user(argm, &tmp, sizeof(tmp))) - return -EFAULT; - } - } - return 0; - } - } - - return -ENOIOCTLCMD; -} - static int MoxaDriverPoll(void) { struct moxa_board_conf *brd; @@ -1756,7 +1718,6 @@ static int MoxaDriverPoll(void) * 24. MoxaPortTxDisable(int port); * * 25. MoxaPortTxEnable(int port); * * 27. MoxaPortResetBrkCnt(int port); * - * 30. MoxaPortSendBreak(int port, int ticks); * *****************************************************************************/ /* * Moxa Port Number Description: @@ -1984,14 +1945,6 @@ static int MoxaDriverPoll(void) * return: 0 - .. : BREAK signal count * * - * Function 34: Send out a BREAK signal. - * Syntax: - * void MoxaPortSendBreak(int port, int ms100); - * int port : port number (0 - 127) - * int ms100 : break signal time interval. - * unit: 100 mini-second. if ms100 == 0, it will - * send out a about 250 ms BREAK signal. - * */ static void MoxaPortEnable(struct moxa_port *port) @@ -2397,21 +2350,6 @@ static int MoxaPortResetBrkCnt(struct moxa_port *port) return (cnt); } - -static void MoxaPortSendBreak(struct moxa_port *port, int ms100) -{ - void __iomem *ofsAddr = port->tableAddr; - - if (ms100) { - moxafunc(ofsAddr, FC_SendBreak, Magic_code); - msleep(ms100 * 10); - } else { - moxafunc(ofsAddr, FC_SendBreak, Magic_code); - msleep(250); - } - moxafunc(ofsAddr, FC_StopBreak, Magic_code); -} - static int moxa_get_serial_info(struct moxa_port *info, struct serial_struct __user *retinfo) { @@ -2474,26 +2412,6 @@ static int moxa_set_serial_info(struct moxa_port *info, /***************************************************************************** * Static local functions: * *****************************************************************************/ -static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg) -{ - - writew(arg, ofsAddr + FuncArg); - writew(cmd, ofsAddr + FuncCode); - moxa_wait_finish(ofsAddr); -} - -static void moxa_wait_finish(void __iomem *ofsAddr) -{ - unsigned long i, j; - - i = jiffies; - while (readw(ofsAddr + FuncCode) != 0) { - j = jiffies; - if ((j - i) > moxaFuncTout) { - return; - } - } -} static void moxa_low_water_check(void __iomem *ofsAddr) { |