Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74d7d97b authored by Jiri Slaby's avatar Jiri Slaby Committed by Linus Torvalds
Browse files

Char: moxa, ioctl cleanup



- allow stats only for sys_admin
- move TCSBRK* processing to .break_ctl tty op
- let TIOCGSOFTCAR and TIOCSSOFTCAR be processed by ldisc
- remove MOXA_GET_MAJOR, MOXA_GET_CUMAJOR
- fix jiffies subtraction by time_after
- move moxa ioctl numbers into the header; still not exported to userspace,
  needs _IOC and 32/64 compat cleanup anyways

Signed-off-by: default avatarJiri Slaby <jirislaby@gmail.com>
Tested-by: default avatarOyvind Aabling <Oyvind.Aabling@uni-c.dk>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 0bcc4caa
Loading
Loading
Loading
Loading
+139 −221
Original line number Diff line number Diff line
@@ -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)
{
+8 −0
Original line number Diff line number Diff line
#ifndef MOXA_H_FILE
#define MOXA_H_FILE

#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_GETMSTATUS         (MOXA + 65)

/*
 *    System Configuration
 */