2004-01-13 11:00:55

by Jozef Vesely

[permalink] [raw]
Subject: [PROBLEM] ircomm ioctls

Hi,

since upgrading to the 2.6.1 (from 2.4.22)

I am gettig this error (while connecting to my mobile phone):
------
# gsmctl -d /dev/ircomm0 ALL
gsmctl[ERROR]: clearing DTR failed (errno: 22/Invalid argument)
------

the code in: gsmlib-1.10/gsmlib/gsm_unix_serial.cc
------
// toggle DTR to reset modem
int mctl = TIOCM_DTR;
if (ioctl(_fd, TIOCMBIC, &mctl) < 0)
throwModemException(_("clearing DTR failed"));
// the waiting time for DTR toggling is increased with each loop
usleep(holdoff[initTries]);
if (ioctl(_fd, TIOCMBIS, &mctl) < 0)
throwModemException(_("setting DTR failed"));
------

pointed me to tke kernel:
the ioctls TIOCMBIC, TIOCMBIS, TIOCMSET and TIOCMGET are handled both in

net/irda/ircomm/ircomm_tty_ioctl.c function ircomm_tty_ioctl()
-----
switch (cmd) {
case TIOCMGET:
ret = ircomm_tty_get_modem_info(self, (unsigned int *) arg);
break;
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
ret = ircomm_tty_set_modem_info(self, cmd, (unsigned int *) arg);
break;
-----

and in
drivers/char/tty_io.c function tty_ioctl()
-----
switch (cmd) {
...
case TIOCMGET:
return tty_tiocmget(tty, file, arg);

case TIOCMSET:
case TIOCMBIC:
case TIOCMBIS:
return tty_tiocmset(tty, file, cmd, arg);
}
if (tty->driver->ioctl) {
int retval = (tty->driver->ioctl)(tty, file, cmd, arg);
if (retval != -ENOIOCTLCMD)
return retval;
}
-----

The tty_tiocmset() checks for driver->tiocmset and calls it. In case
of ircomm driver->tiocmset is not set since those ioctls are meant
to be handled by driver->ioctl, however tty_tiocmset returns with -EINVAL
and driver->ioctl never gets called.

I am beginner in the kernel programing, and therefore I would rather let more
experienced to create the patch (I don't want to mess up something).

I hope this descrition would be helpful, and somebody fixes the problem.

Thank you in advance

Jozef Vesely
[email protected]




2004-01-13 11:37:05

by Russell King

[permalink] [raw]
Subject: Re: [PROBLEM] ircomm ioctls

On Tue, Jan 13, 2004 at 12:00:15PM +0100, Jozef Vesely wrote:
> I am gettig this error (while connecting to my mobile phone):
> ------
> # gsmctl -d /dev/ircomm0 ALL
> gsmctl[ERROR]: clearing DTR failed (errno: 22/Invalid argument)
> ------

ircomm needs updating to use the tiocmset/tiocmget driver calls. Could
you see if the following patch solves your problem please?

===== ircomm/ircomm_tty.c 1.31 vs edited =====
--- 1.31/net/irda/ircomm/ircomm_tty.c Fri Jan 9 10:10:13 2004
+++ edited/ircomm/ircomm_tty.c Tue Jan 13 11:33:58 2004
@@ -75,6 +75,9 @@
static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
int *eof, void *unused);
#endif /* CONFIG_PROC_FS */
+static int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file);
+static int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
static struct tty_driver *driver;

hashbin_t *ircomm_tty = NULL;
@@ -98,6 +101,8 @@
#ifdef CONFIG_PROC_FS
.read_proc = ircomm_tty_read_proc,
#endif /* CONFIG_PROC_FS */
+ .tiocmget = ircomm_tty_tiocmget,
+ .tiocmset = ircomm_tty_tiocmset,
};

/*
@@ -1408,6 +1413,62 @@
return ((len < begin+count-offset) ? len : begin+count-offset);
}
#endif /* CONFIG_PROC_FS */
+
+/*
+ * Function ircomm_tty_tiocmget (tty, file)
+ *
+ *
+ *
+ */
+static int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+ IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
+
+ return ((self->settings.dte & IRCOMM_RTS) ? TIOCM_RTS : 0)
+ | ((self->settings.dte & IRCOMM_DTR) ? TIOCM_DTR : 0)
+ | ((self->settings.dce & IRCOMM_CD) ? TIOCM_CAR : 0)
+ | ((self->settings.dce & IRCOMM_RI) ? TIOCM_RNG : 0)
+ | ((self->settings.dce & IRCOMM_DSR) ? TIOCM_DSR : 0)
+ | ((self->settings.dce & IRCOMM_CTS) ? TIOCM_CTS : 0);
+}
+
+/*
+ * Function ircomm_tty_tiocmset (driver, cmd, value)
+ *
+ *
+ *
+ */
+static int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+ IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
+
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+ if (set & TIOCM_RTS)
+ self->settings.dte |= IRCOMM_RTS;
+ if (set & TIOCM_DTR)
+ self->settings.dte |= IRCOMM_DTR;
+
+ if (clear & TIOCM_RTS)
+ self->settings.dte &= ~IRCOMM_RTS;
+ if (clear & TIOCM_DTR)
+ self->settings.dte &= ~IRCOMM_DTR;
+
+ if ((set|clear) & TIOCM_RTS)
+ self->settings.dte |= IRCOMM_DELTA_RTS;
+ if ((set|clear) & TIOCM_DTR)
+ self->settings.dte |= IRCOMM_DELTA_DTR;
+
+ ircomm_param_request(self, IRCOMM_DTE, TRUE);
+
+ return 0;
+}

MODULE_AUTHOR("Dag Brattli <[email protected]>");
MODULE_DESCRIPTION("IrCOMM serial TTY driver");
===== ircomm/ircomm_tty_ioctl.c 1.6 vs edited =====
--- 1.6/net/irda/ircomm/ircomm_tty_ioctl.c Tue Sep 24 00:34:20 2002
+++ edited/ircomm/ircomm_tty_ioctl.c Tue Jan 13 11:34:03 2004
@@ -190,89 +190,6 @@
}

/*
- * Function ircomm_tty_get_modem_info (self, value)
- *
- *
- *
- */
-static int ircomm_tty_get_modem_info(struct ircomm_tty_cb *self,
- unsigned int *value)
-{
- unsigned int result;
-
- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-
- result = ((self->settings.dte & IRCOMM_RTS) ? TIOCM_RTS : 0)
- | ((self->settings.dte & IRCOMM_DTR) ? TIOCM_DTR : 0)
- | ((self->settings.dce & IRCOMM_CD) ? TIOCM_CAR : 0)
- | ((self->settings.dce & IRCOMM_RI) ? TIOCM_RNG : 0)
- | ((self->settings.dce & IRCOMM_DSR) ? TIOCM_DSR : 0)
- | ((self->settings.dce & IRCOMM_CTS) ? TIOCM_CTS : 0);
-
- return put_user(result, value);
-}
-
-/*
- * Function set_modem_info (driver, cmd, value)
- *
- *
- *
- */
-static int ircomm_tty_set_modem_info(struct ircomm_tty_cb *self,
- unsigned int cmd, unsigned int *value)
-{
- unsigned int arg;
- __u8 old_rts, old_dtr;
-
- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
-
- if (get_user(arg, value))
- return -EFAULT;
-
- old_rts = self->settings.dte & IRCOMM_RTS;
- old_dtr = self->settings.dte & IRCOMM_DTR;
-
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- self->settings.dte |= IRCOMM_RTS;
- if (arg & TIOCM_DTR)
- self->settings.dte |= IRCOMM_DTR;
- break;
-
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- self->settings.dte &= ~IRCOMM_RTS;
- if (arg & TIOCM_DTR)
- self->settings.dte &= ~IRCOMM_DTR;
- break;
-
- case TIOCMSET:
- self->settings.dte =
- ((self->settings.dte & ~(IRCOMM_RTS | IRCOMM_DTR))
- | ((arg & TIOCM_RTS) ? IRCOMM_RTS : 0)
- | ((arg & TIOCM_DTR) ? IRCOMM_DTR : 0));
- break;
-
- default:
- return -EINVAL;
- }
-
- if ((self->settings.dte & IRCOMM_RTS) != old_rts)
- self->settings.dte |= IRCOMM_DELTA_RTS;
-
- if ((self->settings.dte & IRCOMM_DTR) != old_dtr)
- self->settings.dte |= IRCOMM_DELTA_DTR;
-
- ircomm_param_request(self, IRCOMM_DTE, TRUE);
-
- return 0;
-}
-
-/*
* Function get_serial_info (driver, retinfo)
*
*
@@ -406,14 +323,6 @@
}

switch (cmd) {
- case TIOCMGET:
- ret = ircomm_tty_get_modem_info(self, (unsigned int *) arg);
- break;
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- ret = ircomm_tty_set_modem_info(self, cmd, (unsigned int *) arg);
- break;
case TIOCGSERIAL:
ret = ircomm_tty_get_serial_info(self, (struct serial_struct *) arg);
break;


--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-13 11:49:55

by Russell King

[permalink] [raw]
Subject: Outstanding fixups (was: Re: [PROBLEM] ircomm ioctls)

On Tue, Jan 13, 2004 at 11:36:51AM +0000, Russell King wrote:
> ircomm needs updating to use the tiocmset/tiocmget driver calls. Could
> you see if the following patch solves your problem please?

And as a follow up, there are about 30 other drivers which still
reference TIOCM{GET,SET,BIC,BIS} most of which won't work. Some of
them include drivers that were dumped into drivers/serial (despite
not using the serial_core stuff.)

The list currently looks like this. Some of these drivers have been
updated since the change was made back in April, but it seems that
this particular update was missed.

I'm going to work through this list and update these drivers today.
However, I will be unable to test most if not all of these drivers.

drivers/char/rio/rio_linux.c
drivers/char/amiserial.c
drivers/char/cyclades.c
drivers/char/epca.c
drivers/char/esp.c
drivers/char/ip2main.c
drivers/char/isicom.c
drivers/char/istallion.c
drivers/char/moxa.c
drivers/char/mxser.c
drivers/char/pcxx.c
drivers/char/riscom8.c
drivers/char/rocket.c
drivers/char/serial167.c
drivers/char/sh-sci.c
drivers/char/specialix.c
drivers/char/stallion.c
drivers/char/sx.c
drivers/isdn/i4l/isdn_tty.c
drivers/macintosh/macserial.c
drivers/net/wan/pc300_tty.c
drivers/s390/net/ctctty.c
drivers/sbus/char/aurora.c
drivers/serial/68360serial.c
drivers/serial/mcfserial.c
drivers/tc/zs.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/io_edgeport.c

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-13 17:15:55

by Russell King

[permalink] [raw]
Subject: Re: Outstanding fixups (was: Re: [PROBLEM] ircomm ioctls)

On Tue, Jan 13, 2004 at 11:49:48AM +0000, Russell King wrote:
> And as a follow up, there are about 30 other drivers which still
> reference TIOCM{GET,SET,BIC,BIS} most of which won't work. Some of
> them include drivers that were dumped into drivers/serial (despite
> not using the serial_core stuff.)

Ok, I've just finished giving all those drivers the once over for this
specific problem (and no others.) A general comment is that we have
a hell of a lot of unmaintained crud here. Many of these serial drivers
are still using the global IRQ macros, and therefore are unbuildable in
2.6 kernels.

Specific drivers:

- 68360serial, amiserial, serial167
These need attention - they appear to have had the global IRQ stuff
"cleaned up". IOW, the global IRQ macros have become local IRQ macros
with no regard what so ever to any SMP locking issues.

- moxa
This has a complete lack of locking what so ever.

- pcxx, epca
These seem to do something weird with the semantics of TIOCMSET/BIC/BIS.
and as such have nonstandard behaviour. The driver author needs to
look at this and resolve the issue. As the driver stood previously,
TIOCMBIC/BIS took explicit control of the modem control lines. TIOCMSET
also did this, but only when the modem control line was _set_. If it
were cleared using TIOCMSET, control over this line was returned to the
chip.

This is not how 16x50 ports work when they are in "auto RTS" mode. The
RTS signal is the logical and of the RTS setting and the hardware flow
control, when the hardware flow control is enabled.

- pc300_tty
This seems to think that TIOCMBIC/TIOCMBIS are only used to manipulate
the DTR signal. This is an invalid assumption, so it now has a #error
and comment explaining this fact - IMO the driver author needs to fix
this themselves.

The patch:

drivers/char/amiserial.c | 63 ++++-------
drivers/char/cyclades.c | 157 +++++------------------------
drivers/char/epca.c | 177 ++++++++++++++++++---------------
drivers/char/esp.c | 63 +++++------
drivers/char/ip2main.c | 196 +++++++++++++++----------------------
drivers/char/isicom.c | 72 ++++---------
drivers/char/istallion.c | 94 ++++++++++-------
drivers/char/moxa.c | 97 +++++++++---------
drivers/char/mxser.c | 67 +++++-------
drivers/char/pcxx.c | 146 ++++++++++++++++-----------
drivers/char/rio/rio_linux.c | 5
drivers/char/riscom8.c | 64 +++++-------
drivers/char/rocket.c | 59 -----------
drivers/char/serial167.c | 77 ++------------
drivers/char/sh-sci.c | 46 +++++---
drivers/char/specialix.c | 108 +++++++-------------
drivers/char/stallion.c | 75 ++++++++------
drivers/char/sx.c | 56 +++++-----
drivers/isdn/i4l/isdn_tty.c | 111 +++++++-------------
drivers/macintosh/macserial.c | 72 ++++++++-----
drivers/net/wan/pc300_tty.c | 8 +
drivers/s390/net/ctctty.c | 87 +++++-----------
drivers/sbus/char/aurora.c | 61 ++++-------
drivers/serial/68360serial.c | 98 +++++++-----------
drivers/serial/mcfserial.c | 78 +++++++-------
drivers/tc/zs.c | 68 ++++++------
drivers/usb/serial/ftdi_sio.c | 181 +++++++++++++++-------------------
net/irda/ircomm/ircomm_tty.c | 67 ++++++++++++
net/irda/ircomm/ircomm_tty_ioctl.c | 91 -----------------
29 files changed, 1106 insertions(+), 1438 deletions(-)

Because of the size of the patch, I'm going to mail it out as several
chunks, and will follow up this mail.

1 - drivers which someone has tested and say works.
2 - drivers which have been updated but are untested but should work.
3 - drivers which have been updated but are broken in some way.

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-13 17:24:52

by Russell King

[permalink] [raw]
Subject: [1/3] Serial fixups (mostly tested)

This patch fixes the ircomm_tty driver to use the tiocmget/set calls.
Jozef Vesely kindly tested a similar patch and said it solved the
problem. This patch adds the extra error checking which was missing
in the previous patch.

===== net/irda/ircomm/ircomm_tty.c 1.31 vs edited =====
--- 1.31/net/irda/ircomm/ircomm_tty.c Fri Jan 9 10:10:13 2004
+++ edited/net/irda/ircomm/ircomm_tty.c Tue Jan 13 13:08:40 2004
@@ -75,6 +75,9 @@
static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
int *eof, void *unused);
#endif /* CONFIG_PROC_FS */
+static int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file);
+static int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
static struct tty_driver *driver;

hashbin_t *ircomm_tty = NULL;
@@ -98,6 +101,8 @@
#ifdef CONFIG_PROC_FS
.read_proc = ircomm_tty_read_proc,
#endif /* CONFIG_PROC_FS */
+ .tiocmget = ircomm_tty_tiocmget,
+ .tiocmset = ircomm_tty_tiocmset,
};

/*
@@ -1408,6 +1413,68 @@
return ((len < begin+count-offset) ? len : begin+count-offset);
}
#endif /* CONFIG_PROC_FS */
+
+/*
+ * Function ircomm_tty_tiocmget (tty, file)
+ *
+ *
+ *
+ */
+static int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+ IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
+
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+ return ((self->settings.dte & IRCOMM_RTS) ? TIOCM_RTS : 0)
+ | ((self->settings.dte & IRCOMM_DTR) ? TIOCM_DTR : 0)
+ | ((self->settings.dce & IRCOMM_CD) ? TIOCM_CAR : 0)
+ | ((self->settings.dce & IRCOMM_RI) ? TIOCM_RNG : 0)
+ | ((self->settings.dce & IRCOMM_DSR) ? TIOCM_DSR : 0)
+ | ((self->settings.dce & IRCOMM_CTS) ? TIOCM_CTS : 0);
+}
+
+/*
+ * Function ircomm_tty_tiocmset (driver, cmd, value)
+ *
+ *
+ *
+ */
+static int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+ IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
+
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+ if (set & TIOCM_RTS)
+ self->settings.dte |= IRCOMM_RTS;
+ if (set & TIOCM_DTR)
+ self->settings.dte |= IRCOMM_DTR;
+
+ if (clear & TIOCM_RTS)
+ self->settings.dte &= ~IRCOMM_RTS;
+ if (clear & TIOCM_DTR)
+ self->settings.dte &= ~IRCOMM_DTR;
+
+ if ((set|clear) & TIOCM_RTS)
+ self->settings.dte |= IRCOMM_DELTA_RTS;
+ if ((set|clear) & TIOCM_DTR)
+ self->settings.dte |= IRCOMM_DELTA_DTR;
+
+ ircomm_param_request(self, IRCOMM_DTE, TRUE);
+
+ return 0;
+}

MODULE_AUTHOR("Dag Brattli <[email protected]>");
MODULE_DESCRIPTION("IrCOMM serial TTY driver");
===== net/irda/ircomm/ircomm_tty_ioctl.c 1.6 vs edited =====
--- 1.6/net/irda/ircomm/ircomm_tty_ioctl.c Tue Sep 24 00:34:20 2002
+++ edited/net/irda/ircomm/ircomm_tty_ioctl.c Tue Jan 13 11:34:03 2004
@@ -190,89 +190,6 @@
}

/*
- * Function ircomm_tty_get_modem_info (self, value)
- *
- *
- *
- */
-static int ircomm_tty_get_modem_info(struct ircomm_tty_cb *self,
- unsigned int *value)
-{
- unsigned int result;
-
- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-
- result = ((self->settings.dte & IRCOMM_RTS) ? TIOCM_RTS : 0)
- | ((self->settings.dte & IRCOMM_DTR) ? TIOCM_DTR : 0)
- | ((self->settings.dce & IRCOMM_CD) ? TIOCM_CAR : 0)
- | ((self->settings.dce & IRCOMM_RI) ? TIOCM_RNG : 0)
- | ((self->settings.dce & IRCOMM_DSR) ? TIOCM_DSR : 0)
- | ((self->settings.dce & IRCOMM_CTS) ? TIOCM_CTS : 0);
-
- return put_user(result, value);
-}
-
-/*
- * Function set_modem_info (driver, cmd, value)
- *
- *
- *
- */
-static int ircomm_tty_set_modem_info(struct ircomm_tty_cb *self,
- unsigned int cmd, unsigned int *value)
-{
- unsigned int arg;
- __u8 old_rts, old_dtr;
-
- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
-
- if (get_user(arg, value))
- return -EFAULT;
-
- old_rts = self->settings.dte & IRCOMM_RTS;
- old_dtr = self->settings.dte & IRCOMM_DTR;
-
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- self->settings.dte |= IRCOMM_RTS;
- if (arg & TIOCM_DTR)
- self->settings.dte |= IRCOMM_DTR;
- break;
-
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- self->settings.dte &= ~IRCOMM_RTS;
- if (arg & TIOCM_DTR)
- self->settings.dte &= ~IRCOMM_DTR;
- break;
-
- case TIOCMSET:
- self->settings.dte =
- ((self->settings.dte & ~(IRCOMM_RTS | IRCOMM_DTR))
- | ((arg & TIOCM_RTS) ? IRCOMM_RTS : 0)
- | ((arg & TIOCM_DTR) ? IRCOMM_DTR : 0));
- break;
-
- default:
- return -EINVAL;
- }
-
- if ((self->settings.dte & IRCOMM_RTS) != old_rts)
- self->settings.dte |= IRCOMM_DELTA_RTS;
-
- if ((self->settings.dte & IRCOMM_DTR) != old_dtr)
- self->settings.dte |= IRCOMM_DELTA_DTR;
-
- ircomm_param_request(self, IRCOMM_DTE, TRUE);
-
- return 0;
-}
-
-/*
* Function get_serial_info (driver, retinfo)
*
*
@@ -406,14 +323,6 @@
}

switch (cmd) {
- case TIOCMGET:
- ret = ircomm_tty_get_modem_info(self, (unsigned int *) arg);
- break;
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- ret = ircomm_tty_set_modem_info(self, cmd, (unsigned int *) arg);
- break;
case TIOCGSERIAL:
ret = ircomm_tty_get_serial_info(self, (struct serial_struct *) arg);
break;


--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-13 17:36:10

by Russell King

[permalink] [raw]
Subject: [2/3]

Here are patches to drivers in the 2.6 kernel which have not been tested
to correct the tiocmset/tiocmget problem.

You can find the full thread at the following URL:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=1dvnl-5Pr-1%40gated-at.bofh.it&rnum=1&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DISO-8859-1%26q%3DOutstanding%2Bfixups%26btnG%3DGoogle%2BSearch%26meta%3Dgroup%253Dlinux.kernel

===== drivers/char/cyclades.c 1.32 vs edited =====
--- 1.32/drivers/char/cyclades.c Tue Sep 30 01:34:28 2003
+++ edited/drivers/char/cyclades.c Tue Jan 13 14:01:24 2004
@@ -3632,8 +3632,9 @@
}

static int
-get_modem_info(struct cyclades_port * info, unsigned int *value)
+cy_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
int card,chip,channel,index;
unsigned char *base_addr;
unsigned long flags;
@@ -3645,6 +3646,9 @@
struct BOARD_CTRL *board_ctrl;
struct CH_CTRL *ch_ctrl;

+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
card = info->card;
channel = (info->line) - (cy_card[card].first_line);
if (!IS_CYC_Z(cy_card[card])) {
@@ -3700,14 +3704,15 @@
}

}
- return cy_put_user(result, value);
-} /* get_modem_info */
+ return result;
+} /* cy_tiomget */


static int
-set_modem_info(struct cyclades_port * info, unsigned int cmd,
- unsigned int *value)
+cy_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
int card,chip,channel,index;
unsigned char *base_addr;
unsigned long flags;
@@ -3718,6 +3723,9 @@
struct CH_CTRL *ch_ctrl;
int retval;

+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
card = info->card;
channel = (info->line) - (cy_card[card].first_line);
if (!IS_CYC_Z(cy_card[card])) {
@@ -3728,66 +3736,7 @@
(cy_card[card].base_addr
+ (cy_chip_offset[chip]<<index));

- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS){
- CY_LOCK(info, flags);
- cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
- if (info->rtsdtr_inv) {
- cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
- } else {
- cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
- }
- CY_UNLOCK(info, flags);
- }
- if (arg & TIOCM_DTR){
- CY_LOCK(info, flags);
- cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
- if (info->rtsdtr_inv) {
- cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
- } else {
- cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
- }
-#ifdef CY_DEBUG_DTR
- printk("cyc:set_modem_info raising DTR\n");
- printk(" status: 0x%x, 0x%x\n",
- cy_readb(base_addr+(CyMSVR1<<index)),
- cy_readb(base_addr+(CyMSVR2<<index)));
-#endif
- CY_UNLOCK(info, flags);
- }
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS){
- CY_LOCK(info, flags);
- cy_writeb((u_long)base_addr+(CyCAR<<index),
- (u_char)channel);
- if (info->rtsdtr_inv) {
- cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
- } else {
- cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
- }
- CY_UNLOCK(info, flags);
- }
- if (arg & TIOCM_DTR){
- CY_LOCK(info, flags);
- cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
- if (info->rtsdtr_inv) {
- cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
- } else {
- cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
- }
-#ifdef CY_DEBUG_DTR
- printk("cyc:set_modem_info dropping DTR\n");
- printk(" status: 0x%x, 0x%x\n",
- cy_readb(base_addr+(CyMSVR1<<index)),
- cy_readb(base_addr+(CyMSVR2<<index)));
-#endif
- CY_UNLOCK(info, flags);
- }
- break;
- case TIOCMSET:
- if (arg & TIOCM_RTS){
+ if (set & TIOCM_RTS){
CY_LOCK(info, flags);
cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
if (info->rtsdtr_inv) {
@@ -3796,7 +3745,8 @@
cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
}
CY_UNLOCK(info, flags);
- }else{
+ }
+ if (clear & TIOCM_RTS) {
CY_LOCK(info, flags);
cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
if (info->rtsdtr_inv) {
@@ -3805,8 +3755,8 @@
cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
}
CY_UNLOCK(info, flags);
- }
- if (arg & TIOCM_DTR){
+ }
+ if (set & TIOCM_DTR){
CY_LOCK(info, flags);
cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
if (info->rtsdtr_inv) {
@@ -3821,7 +3771,8 @@
cy_readb(base_addr+(CyMSVR2<<index)));
#endif
CY_UNLOCK(info, flags);
- }else{
+ }
+ if (clear & TIOCM_DTR) {
CY_LOCK(info, flags);
cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
if (info->rtsdtr_inv) {
@@ -3837,10 +3788,6 @@
cy_readb(base_addr+(CyMSVR2<<index)));
#endif
CY_UNLOCK(info, flags);
- }
- break;
- default:
- return -EINVAL;
}
} else {
base_addr = (unsigned char*) (cy_card[card].base_addr);
@@ -3854,54 +3801,19 @@
board_ctrl = &zfw_ctrl->board_ctrl;
ch_ctrl = zfw_ctrl->ch_ctrl;

- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS){
- CY_LOCK(info, flags);
- cy_writel(&ch_ctrl[channel].rs_control,
- cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS);
- CY_UNLOCK(info, flags);
- }
- if (arg & TIOCM_DTR){
- CY_LOCK(info, flags);
- cy_writel(&ch_ctrl[channel].rs_control,
- cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
-#ifdef CY_DEBUG_DTR
- printk("cyc:set_modem_info raising Z DTR\n");
-#endif
- CY_UNLOCK(info, flags);
- }
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS){
- CY_LOCK(info, flags);
- cy_writel(&ch_ctrl[channel].rs_control,
- cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS);
- CY_UNLOCK(info, flags);
- }
- if (arg & TIOCM_DTR){
- CY_LOCK(info, flags);
- cy_writel(&ch_ctrl[channel].rs_control,
- cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
-#ifdef CY_DEBUG_DTR
- printk("cyc:set_modem_info clearing Z DTR\n");
-#endif
- CY_UNLOCK(info, flags);
- }
- break;
- case TIOCMSET:
- if (arg & TIOCM_RTS){
+ if (set & TIOCM_RTS){
CY_LOCK(info, flags);
cy_writel(&ch_ctrl[channel].rs_control,
cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS);
CY_UNLOCK(info, flags);
- }else{
+ }
+ if (clear & TIOCM_RTS) {
CY_LOCK(info, flags);
cy_writel(&ch_ctrl[channel].rs_control,
cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS);
CY_UNLOCK(info, flags);
- }
- if (arg & TIOCM_DTR){
+ }
+ if (set & TIOCM_DTR){
CY_LOCK(info, flags);
cy_writel(&ch_ctrl[channel].rs_control,
cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
@@ -3909,7 +3821,8 @@
printk("cyc:set_modem_info raising Z DTR\n");
#endif
CY_UNLOCK(info, flags);
- }else{
+ }
+ if (clear & TIOCM_DTR) {
CY_LOCK(info, flags);
cy_writel(&ch_ctrl[channel].rs_control,
cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
@@ -3917,10 +3830,6 @@
printk("cyc:set_modem_info clearing Z DTR\n");
#endif
CY_UNLOCK(info, flags);
- }
- break;
- default:
- return -EINVAL;
}
}else{
return -ENODEV;
@@ -3935,7 +3844,7 @@
CY_UNLOCK(info, flags);
}
return 0;
-} /* set_modem_info */
+} /* cy_tiocmset */

/*
* cy_break() --- routine which turns the break handling on or off
@@ -4242,14 +4151,6 @@
case CYGETWAIT:
ret_val = info->closing_wait / (HZ/100);
break;
- case TIOCMGET:
- ret_val = get_modem_info(info, (unsigned int *) arg);
- break;
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- ret_val = set_modem_info(info, cmd, (unsigned int *) arg);
- break;
case TIOCGSERIAL:
ret_val = get_serial_info(info, (struct serial_struct *) arg);
break;
@@ -5429,6 +5330,8 @@
.break_ctl = cy_break,
.wait_until_sent = cy_wait_until_sent,
.read_proc = cyclades_get_proc_info,
+ .tiocmget = cy_tiocmget,
+ .tiocmset = cy_tiocmset,
};

static int __init
===== drivers/char/ip2main.c 1.42 vs edited =====
--- 1.42/drivers/char/ip2main.c Tue Sep 30 01:23:52 2003
+++ edited/drivers/char/ip2main.c Tue Jan 13 16:06:56 2004
@@ -186,6 +186,9 @@
static void ip2_stop(PTTY);
static void ip2_start(PTTY);
static void ip2_hangup(PTTY);
+static int ip2_tiocmget(struct tty_struct *tty, struct file *file);
+static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);

static void set_irq(int, int);
static void ip2_interrupt_bh(i2eBordStrPtr pB);
@@ -466,6 +469,8 @@
.start = ip2_start,
.hangup = ip2_hangup,
.read_proc = ip2_read_proc,
+ .tiocmget = ip2_tiocmget,
+ .tiocmset = ip2_tiocmset,
};

/******************************************************************************/
@@ -1951,6 +1956,80 @@
/* Device Ioctl Section */
/******************************************************************************/

+static int ip2_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ i2ChanStrPtr pCh = DevTable[tty->index];
+ wait_queue_t wait;
+
+ if (pCh == NULL)
+ return -ENODEV;
+
+/*
+ FIXME - the following code is causing a NULL pointer dereference in
+ 2.3.51 in an interrupt handler. It's suppose to prompt the board
+ to return the DSS signal status immediately. Why doesn't it do
+ the same thing in 2.2.14?
+*/
+
+/* This thing is still busted in the 1.2.12 driver on 2.4.x
+ and even hoses the serial console so the oops can be trapped.
+ /\/\|=mhw=|\/\/ */
+
+#ifdef ENABLE_DSSNOW
+ i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
+
+ init_waitqueue_entry(&wait, current);
+ add_wait_queue(&pCh->dss_now_wait, &wait);
+ set_current_state( TASK_INTERRUPTIBLE );
+
+ serviceOutgoingFifo( pCh->pMyBord );
+
+ schedule();
+
+ set_current_state( TASK_RUNNING );
+ remove_wait_queue(&pCh->dss_now_wait, &wait);
+
+ if (signal_pending(current)) {
+ return -EINTR;
+ }
+#endif
+ return ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
+ | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
+ | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0)
+ | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0)
+ | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0)
+ | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0);
+}
+
+static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ i2ChanStrPtr pCh = DevTable[tty->index];
+
+ if (pCh == NULL)
+ return -ENODEV;
+
+ if (set & TIOCM_RTS) {
+ i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
+ pCh->dataSetOut |= I2_RTS;
+ }
+ if (set & TIOCM_DTR) {
+ i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
+ pCh->dataSetOut |= I2_DTR;
+ }
+
+ if (clear & TIOCM_RTS) {
+ i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
+ pCh->dataSetOut &= ~I2_RTS;
+ }
+ if (clear & TIOCM_DTR) {
+ i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
+ pCh->dataSetOut &= ~I2_DTR;
+ }
+ serviceOutgoingFifo( pCh->pMyBord );
+ return 0;
+}
+
/******************************************************************************/
/* Function: ip2_ioctl() */
/* Parameters: Pointer to tty structure */
@@ -2078,57 +2157,6 @@

break;

- case TIOCMGET:
-
- ip2trace (CHANN, ITRC_IOCTL, 8, 1, rc );
-
-/*
- FIXME - the following code is causing a NULL pointer dereference in
- 2.3.51 in an interrupt handler. It's suppose to prompt the board
- to return the DSS signal status immediately. Why doesn't it do
- the same thing in 2.2.14?
-*/
-
-/* This thing is still busted in the 1.2.12 driver on 2.4.x
- and even hoses the serial console so the oops can be trapped.
- /\/\|=mhw=|\/\/ */
-
-#ifdef ENABLE_DSSNOW
- i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
-
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&pCh->dss_now_wait, &wait);
- set_current_state( TASK_INTERRUPTIBLE );
-
- serviceOutgoingFifo( pCh->pMyBord );
-
- schedule();
-
- set_current_state( TASK_RUNNING );
- remove_wait_queue(&pCh->dss_now_wait, &wait);
-
- if (signal_pending(current)) {
- return -EINTR;
- }
-#endif
- rc = put_user(
- ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
- | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
- | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0)
- | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0)
- | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0)
- | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0),
- (unsigned int *) arg);
- break;
-
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- ip2trace (CHANN, ITRC_IOCTL, 9, 0 );
-
- rc = set_modem_info(pCh, cmd, (unsigned int *) arg);
- break;
-
/*
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
* passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
@@ -2239,70 +2267,6 @@
}

/******************************************************************************/
-/* Function: set_modem_info() */
-/* Parameters: Pointer to channel structure */
-/* Specific ioctl command */
-/* Pointer to source for new settings */
-/* Returns: Nothing */
-/* */
-/* Description: */
-/* This returns the current settings of the dataset signal inputs to the user */
-/* program. */
-/******************************************************************************/
-static int
-set_modem_info(i2ChanStrPtr pCh, unsigned cmd, unsigned int *value)
-{
- int rc;
- unsigned int arg;
-
- rc = get_user(arg,value);
- if (rc)
- return rc;
- switch(cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS) {
- i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
- pCh->dataSetOut |= I2_RTS;
- }
- if (arg & TIOCM_DTR) {
- i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
- pCh->dataSetOut |= I2_DTR;
- }
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS) {
- i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
- pCh->dataSetOut &= ~I2_RTS;
- }
- if (arg & TIOCM_DTR) {
- i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
- pCh->dataSetOut &= ~I2_DTR;
- }
- break;
- case TIOCMSET:
- if ( (arg & TIOCM_RTS) && !(pCh->dataSetOut & I2_RTS) ) {
- i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
- pCh->dataSetOut |= I2_RTS;
- } else if ( !(arg & TIOCM_RTS) && (pCh->dataSetOut & I2_RTS) ) {
- i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
- pCh->dataSetOut &= ~I2_RTS;
- }
- if ( (arg & TIOCM_DTR) && !(pCh->dataSetOut & I2_DTR) ) {
- i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
- pCh->dataSetOut |= I2_DTR;
- } else if ( !(arg & TIOCM_DTR) && (pCh->dataSetOut & I2_DTR) ) {
- i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
- pCh->dataSetOut &= ~I2_DTR;
- }
- break;
- default:
- return -EINVAL;
- }
- serviceOutgoingFifo( pCh->pMyBord );
- return 0;
-}
-
-/******************************************************************************/
/* Function: GetSerialInfo() */
/* Parameters: Pointer to channel structure */
/* Pointer to old termios structure */
@@ -2964,7 +2928,7 @@
rc = put_user(ip2_throttle, pIndex++ );
rc = put_user(ip2_unthrottle, pIndex++ );
rc = put_user(ip2_ioctl, pIndex++ );
- rc = put_user(set_modem_info, pIndex++ );
+ rc = put_user(0, pIndex++ );
rc = put_user(get_serial_info, pIndex++ );
rc = put_user(set_serial_info, pIndex++ );
rc = put_user(ip2_set_termios, pIndex++ );
===== drivers/char/istallion.c 1.34 vs edited =====
--- 1.34/drivers/char/istallion.c Tue Sep 30 01:34:28 2003
+++ edited/drivers/char/istallion.c Tue Jan 13 16:12:50 2004
@@ -1990,6 +1990,61 @@

/*****************************************************************************/

+static int stli_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ stliport_t *portp = tty->driver_data;
+ stlibrd_t *brdp;
+ int rc;
+
+ if (portp == (stliport_t *) NULL)
+ return(-ENODEV);
+ if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+ return(0);
+ brdp = stli_brds[portp->brdnr];
+ if (brdp == (stlibrd_t *) NULL)
+ return(0);
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return(-EIO);
+
+ if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
+ &portp->asig, sizeof(asysigs_t), 1)) < 0)
+ return(rc);
+
+ return stli_mktiocm(portp->asig.sigvalue);
+}
+
+static int stli_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ stliport_t *portp = tty->driver_data;
+ stlibrd_t *brdp;
+ int rts = -1, dtr = -1;
+
+ if (portp == (stliport_t *) NULL)
+ return(-ENODEV);
+ if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+ return(0);
+ brdp = stli_brds[portp->brdnr];
+ if (brdp == (stlibrd_t *) NULL)
+ return(0);
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return(-EIO);
+
+ if (set & TIOCM_RTS)
+ rts = 1;
+ if (set & TIOCM_DTR)
+ dtr = 1;
+ if (clear & TIOCM_RTS)
+ rts = 0;
+ if (clear & TIOCM_DTR)
+ dtr = 0;
+
+ stli_mkasysigs(&portp->asig, dtr, rts);
+
+ return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
+ sizeof(asysigs_t), 0);
+}
+
static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
stliport_t *portp;
@@ -2033,43 +2088,6 @@
(tty->termios->c_cflag & ~CLOCAL) |
(ival ? CLOCAL : 0);
break;
- case TIOCMGET:
- if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))) == 0) {
- if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
- &portp->asig, sizeof(asysigs_t), 1)) < 0)
- return(rc);
- lval = stli_mktiocm(portp->asig.sigvalue);
- put_user(lval, (unsigned int *) arg);
- }
- break;
- case TIOCMBIS:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- stli_mkasysigs(&portp->asig,
- ((ival & TIOCM_DTR) ? 1 : -1),
- ((ival & TIOCM_RTS) ? 1 : -1));
- rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
- &portp->asig, sizeof(asysigs_t), 0);
- }
- break;
- case TIOCMBIC:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- stli_mkasysigs(&portp->asig,
- ((ival & TIOCM_DTR) ? 0 : -1),
- ((ival & TIOCM_RTS) ? 0 : -1));
- rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
- &portp->asig, sizeof(asysigs_t), 0);
- }
- break;
- case TIOCMSET:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- stli_mkasysigs(&portp->asig,
- ((ival & TIOCM_DTR) ? 1 : 0),
- ((ival & TIOCM_RTS) ? 1 : 0));
- rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
- &portp->asig, sizeof(asysigs_t), 0);
- }
- break;
case TIOCGSERIAL:
if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(struct serial_struct))) == 0)
@@ -5254,6 +5272,8 @@
.wait_until_sent = stli_waituntilsent,
.send_xchar = stli_sendxchar,
.read_proc = stli_readproc,
+ .tiocmget = stli_tiocmget,
+ .tiocmset = stli_tiocmset,
};

/*****************************************************************************/
===== drivers/char/rio/rio_linux.c 1.32 vs edited =====
--- 1.32/drivers/char/rio/rio_linux.c Tue Sep 30 01:34:28 2003
+++ edited/drivers/char/rio/rio_linux.c Tue Jan 13 15:01:40 2004
@@ -728,6 +728,11 @@
rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
break;
#if 0
+ /*
+ * note: these IOCTLs no longer reach here. Use
+ * tiocmset/tiocmget driver methods instead. The
+ * #if 0 disablement predates this comment.
+ */
case TIOCMGET:
if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(unsigned int))) == 0) {
===== drivers/char/rocket.c 1.36 vs edited =====
--- 1.36/drivers/char/rocket.c Thu Oct 9 23:13:53 2003
+++ edited/drivers/char/rocket.c Tue Jan 13 16:28:49 2004
@@ -1216,59 +1216,6 @@
/********************************************************************************************/
/* Here are the routines used by rp_ioctl. These are all called from exception handlers. */

-static int get_modem_info(struct r_port *info, unsigned int *value)
-{
- unsigned int control, result, ChanStatus;
-
- ChanStatus = sGetChanStatusLo(&info->channel);
-
- control = info->channel.TxControl[3];
- result = ((control & SET_RTS) ? TIOCM_RTS : 0) |
- ((control & SET_DTR) ? TIOCM_DTR : 0) |
- ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
- (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
- ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
- ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
-
- if (copy_to_user(value, &result, sizeof (int)))
- return -EFAULT;
- return 0;
-}
-
-static int set_modem_info(struct r_port *info, unsigned int cmd,
- unsigned int *value)
-{
- unsigned int arg;
-
- if (copy_from_user(&arg, value, sizeof (int)))
- return -EFAULT;
-
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- info->channel.TxControl[3] |= SET_RTS;
- if (arg & TIOCM_DTR)
- info->channel.TxControl[3] |= SET_DTR;
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- info->channel.TxControl[3] &= ~SET_RTS;
- if (arg & TIOCM_DTR)
- info->channel.TxControl[3] &= ~SET_DTR;
- break;
- case TIOCMSET:
- info->channel.TxControl[3] = ((info->channel.TxControl[3] & ~(SET_RTS | SET_DTR)) |
- ((arg & TIOCM_RTS) ? SET_RTS : 0) |
- ((arg & TIOCM_DTR) ? SET_DTR : 0));
- break;
- default:
- return -EINVAL;
- }
-
- sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0]));
- return 0;
-}
-
/*
* Returns the state of the serial modem control lines. These next 2 functions
* are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
@@ -1432,12 +1379,6 @@
return -ENXIO;

switch (cmd) {
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
case RCKP_GET_STRUCT:
if (copy_to_user((void *) arg, info, sizeof (struct r_port)))
return -EFAULT;
===== drivers/char/sh-sci.c 1.25 vs edited =====
--- 1.25/drivers/char/sh-sci.c Wed Jun 11 20:32:39 2003
+++ edited/drivers/char/sh-sci.c Tue Jan 13 15:17:23 2004
@@ -859,6 +859,31 @@
return retval;
}

+static int sci_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct sci_port *port = tty->driver_data;
+ return sci_getsignals(port);
+}
+
+static int sci_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct sci_port *port = tty->driver_data;
+ int rts = -1, dtr = -1;
+
+ if (set & TIOCM_RTS)
+ rts = 1;
+ if (set & TIOCM_DTR)
+ dtr = 1;
+ if (clear & TIOCM_RTS)
+ rts = 0;
+ if (clear & TIOCM_DTR)
+ dtr = 0;
+
+ sci_setsignals(port, dtr, rts);
+ return 0;
+}
+
static int sci_ioctl(struct tty_struct * tty, struct file * filp,
unsigned int cmd, unsigned long arg)
{
@@ -889,25 +914,6 @@
rc = gs_setserial(&port->gs,
(struct serial_struct *) arg);
break;
- case TIOCMGET:
- ival = sci_getsignals(port);
- rc = put_user(ival, (unsigned int *) arg);
- break;
- case TIOCMBIS:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0)
- sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
- ((ival & TIOCM_RTS) ? 1 : -1));
- break;
- case TIOCMBIC:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0)
- sci_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
- ((ival & TIOCM_RTS) ? 0 : -1));
- break;
- case TIOCMSET:
- if ((rc = get_user(ival, (unsigned int *)arg)) == 0)
- sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
- ((ival & TIOCM_RTS) ? 1 : 0));
- break;

default:
rc = -ENOIOCTLCMD;
@@ -991,6 +997,8 @@
#ifdef CONFIG_PROC_FS
.read_proc = sci_read_proc,
#endif
+ .tiocmget = sci_tiocmget,
+ .tiocmset = sci_tiocmset,
};

/* ********************************************************************** *
===== drivers/char/stallion.c 1.37 vs edited =====
--- 1.37/drivers/char/stallion.c Tue Sep 30 01:34:28 2003
+++ edited/drivers/char/stallion.c Tue Jan 13 15:10:39 2004
@@ -1514,6 +1514,48 @@

/*****************************************************************************/

+static int stl_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ stlport_t *portp;
+
+ if (tty == (struct tty_struct *) NULL)
+ return(-ENODEV);
+ portp = tty->driver_data;
+ if (portp == (stlport_t *) NULL)
+ return(-ENODEV);
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return(-EIO);
+
+ return stl_getsignals(portp);
+}
+
+static int stl_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ stlport_t *portp;
+ int rts = -1, dtr = -1;
+
+ if (tty == (struct tty_struct *) NULL)
+ return(-ENODEV);
+ portp = tty->driver_data;
+ if (portp == (stlport_t *) NULL)
+ return(-ENODEV);
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return(-EIO);
+
+ if (set & TIOCM_RTS)
+ rts = 1;
+ if (set & TIOCM_DTR)
+ dtr = 1;
+ if (clear & TIOCM_RTS)
+ rts = 0;
+ if (clear & TIOCM_DTR)
+ dtr = 0;
+
+ stl_setsignals(portp, dtr, rts);
+ return 0;
+}
+
static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
stlport_t *portp;
@@ -1553,37 +1595,6 @@
(ival ? CLOCAL : 0);
}
break;
- case TIOCMGET:
- if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))) == 0) {
- ival = stl_getsignals(portp);
- put_user(ival, (unsigned int *) arg);
- }
- break;
- case TIOCMBIS:
- if ((rc = verify_area(VERIFY_READ, (void *) arg,
- sizeof(unsigned int))) == 0) {
- get_user(ival, (unsigned int *) arg);
- stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : -1),
- ((ival & TIOCM_RTS) ? 1 : -1));
- }
- break;
- case TIOCMBIC:
- if ((rc = verify_area(VERIFY_READ, (void *) arg,
- sizeof(unsigned int))) == 0) {
- get_user(ival, (unsigned int *) arg);
- stl_setsignals(portp, ((ival & TIOCM_DTR) ? 0 : -1),
- ((ival & TIOCM_RTS) ? 0 : -1));
- }
- break;
- case TIOCMSET:
- if ((rc = verify_area(VERIFY_READ, (void *) arg,
- sizeof(unsigned int))) == 0) {
- get_user(ival, (unsigned int *) arg);
- stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : 0),
- ((ival & TIOCM_RTS) ? 1 : 0));
- }
- break;
case TIOCGSERIAL:
if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(struct serial_struct))) == 0)
@@ -3137,6 +3148,8 @@
.wait_until_sent = stl_waituntilsent,
.send_xchar = stl_sendxchar,
.read_proc = stl_readproc,
+ .tiocmget = stl_tiocmget,
+ .tiocmset = stl_tiocmset,
};

/*****************************************************************************/
===== drivers/char/sx.c 1.42 vs edited =====
--- 1.42/drivers/char/sx.c Tue Dec 30 08:41:41 2003
+++ edited/drivers/char/sx.c Tue Jan 13 14:59:30 2004
@@ -1743,6 +1743,32 @@
}


+static int sx_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct sx_port *port = tty->driver_data;
+ return sx_getsignals(port);
+}
+
+static int sx_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct sx_port *port = tty->driver_data;
+ int rts = -1, cts = -1;
+
+ if (set & TIOCM_RTS)
+ rts = 1;
+ if (set & TIOCM_DTR)
+ dtr = 1;
+ if (clear & TIOCM_RTS)
+ rts = 0;
+ if (clear & TIOCM_DTR)
+ dtr = 0;
+
+ sx_setsignals(port, dtr, rts);
+ sx_reconfigure_port(port);
+ return 0;
+}
+
static int sx_ioctl (struct tty_struct * tty, struct file * filp,
unsigned int cmd, unsigned long arg)
{
@@ -1775,34 +1801,6 @@
sizeof(struct serial_struct))) == 0)
rc = gs_setserial(&port->gs, (struct serial_struct *) arg);
break;
- case TIOCMGET:
- if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))) == 0) {
- ival = sx_getsignals(port);
- put_user(ival, (unsigned int *) arg);
- }
- break;
- case TIOCMBIS:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
- ((ival & TIOCM_RTS) ? 1 : -1));
- sx_reconfigure_port(port);
- }
- break;
- case TIOCMBIC:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- sx_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
- ((ival & TIOCM_RTS) ? 0 : -1));
- sx_reconfigure_port(port);
- }
- break;
- case TIOCMSET:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
- ((ival & TIOCM_RTS) ? 1 : 0));
- sx_reconfigure_port(port);
- }
- break;
default:
rc = -ENOIOCTLCMD;
break;
@@ -2217,6 +2215,8 @@
.stop = gs_stop,
.start = gs_start,
.hangup = gs_hangup,
+ .tiocmget = sx_tiocmget,
+ .tiocmset = sx_tiocmset,
};

static int sx_init_drivers(void)
===== drivers/macintosh/macserial.c 1.30 vs edited =====
--- 1.30/drivers/macintosh/macserial.c Wed Sep 24 07:15:15 2003
+++ edited/drivers/macintosh/macserial.c Tue Jan 13 14:55:37 2004
@@ -1777,47 +1777,65 @@
return put_user(status,value);
}

-static int get_modem_info(struct mac_serial *info, unsigned int *value)
+static int rs_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct mac_serial * info = (struct mac_serial *)tty->driver_data;
unsigned char control, status;
- unsigned int result;
unsigned long flags;

+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel)
+ return -ENODEV;
+#endif
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+
spin_lock_irqsave(&info->lock, flags);
control = info->curregs[5];
status = read_zsreg(info->zs_channel, 0);
spin_unlock_irqrestore(&info->lock, flags);
- result = ((control & RTS) ? TIOCM_RTS: 0)
+ return ((control & RTS) ? TIOCM_RTS: 0)
| ((control & DTR) ? TIOCM_DTR: 0)
| ((status & DCD) ? TIOCM_CAR: 0)
| ((status & CTS) ? 0: TIOCM_CTS);
- return put_user(result,value);
}

-static int set_modem_info(struct mac_serial *info, unsigned int cmd,
- unsigned int *value)
+static int rs_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct mac_serial * info = (struct mac_serial *)tty->driver_data;
unsigned int arg, bits;
unsigned long flags;

- if (get_user(arg, value))
- return -EFAULT;
- bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0);
- spin_lock_irqsave(&info->lock, flags);
- switch (cmd) {
- case TIOCMBIS:
- info->curregs[5] |= bits;
- break;
- case TIOCMBIC:
- info->curregs[5] &= ~bits;
- break;
- case TIOCMSET:
- info->curregs[5] = (info->curregs[5] & ~(DTR | RTS)) | bits;
- break;
- default:
- spin_unlock_irqrestore(&info->lock, flags);
- return -EINVAL;
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel)
+ return -ENODEV;
+#endif
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
}
+
+ spin_lock_irqsave(&info->lock, flags);
+ if (set & TIOCM_RTS)
+ info->curregs[5] |= RTS;
+ if (set & TIOCM_DTR)
+ info->curregs[5] |= DTR;
+ if (clear & TIOCM_RTS)
+ info->curregs[5] &= ~RTS;
+ if (clear & TIOCM_DTR)
+ info->curregs[5] &= ~DTR;
+
info->pendregs[5] = info->curregs[5];
write_zsreg(info->zs_channel, 5, info->curregs[5]);
spin_unlock_irqrestore(&info->lock, flags);
@@ -1863,12 +1881,6 @@
}

switch (cmd) {
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
case TIOCGSERIAL:
return get_serial_info(info,
(struct serial_struct __user *) arg);
@@ -2488,6 +2500,8 @@
.break_ctl = rs_break,
.wait_until_sent = rs_wait_until_sent,
.read_proc = macserial_read_proc,
+ .tiocmget = rs_tiocmget,
+ .tiocmset = rs_tiocmset,
};

static int macserial_init(void)
===== drivers/s390/net/ctctty.c 1.20 vs edited =====
--- 1.20/drivers/s390/net/ctctty.c Mon Oct 6 11:59:26 2003
+++ edited/drivers/s390/net/ctctty.c Tue Jan 13 14:51:50 2004
@@ -655,14 +655,19 @@
}


-static int
-ctc_tty_get_ctc_tty_info(ctc_tty_info * info, uint * value)
+static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file)
{
+ ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
u_char control,
status;
uint result;
ulong flags;

+ if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
control = info->mcr;
spin_lock_irqsave(&ctc_tty_lock, flags);
status = info->msr;
@@ -673,51 +678,31 @@
| ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
| ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
| ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
- put_user(result, (uint *) value);
- return 0;
+ return result;
}

static int
-ctc_tty_set_ctc_tty_info(ctc_tty_info * info, uint cmd, uint * value)
+ctc_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
- uint arg;
- int old_mcr = info->mcr & (UART_MCR_RTS | UART_MCR_DTR);
+ ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;

- get_user(arg, (uint *) value);
- switch (cmd) {
- case TIOCMBIS:
-#ifdef CTC_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "%s%d ioctl TIOCMBIS\n", CTC_TTY_NAME,
- info->line);
-#endif
- if (arg & TIOCM_RTS)
- info->mcr |= UART_MCR_RTS;
- if (arg & TIOCM_DTR)
- info->mcr |= UART_MCR_DTR;
- break;
- case TIOCMBIC:
-#ifdef CTC_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "%s%d ioctl TIOCMBIC\n", CTC_TTY_NAME,
- info->line);
-#endif
- if (arg & TIOCM_RTS)
- info->mcr &= ~UART_MCR_RTS;
- if (arg & TIOCM_DTR)
- info->mcr &= ~UART_MCR_DTR;
- break;
- case TIOCMSET:
-#ifdef CTC_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "%s%d ioctl TIOCMSET\n", CTC_TTY_NAME,
- info->line);
-#endif
- info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR))
- | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
- | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
- break;
- default:
- return -EINVAL;
- }
- if ((info->mcr & (UART_MCR_RTS | UART_MCR_DTR)) != old_mcr)
+ if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+ if (set & TIOCM_RTS)
+ info->mcr |= UART_MCR_RTS;
+ if (set & TIOCM_DTR)
+ info->mcr |= UART_MCR_DTR;
+
+ if (clear & TIOCM_RTS)
+ info->mcr &= ~UART_MCR_RTS;
+ if (clear & TIOCM_DTR)
+ info->mcr &= ~UART_MCR_DTR;
+
+ if ((set | clear) & (TIOCM_RTS|TIOCM_DTR))
ctc_tty_transmit_status(info);
return 0;
}
@@ -775,22 +760,6 @@
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
return 0;
- case TIOCMGET:
-#ifdef CTC_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "%s%d ioctl TIOCMGET\n", CTC_TTY_NAME,
- info->line);
-#endif
- error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
- if (error)
- return error;
- return ctc_tty_get_ctc_tty_info(info, (uint *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint));
- if (error)
- return error;
- return ctc_tty_set_ctc_tty_info(info, cmd, (uint *) arg);
case TIOCSERGETLSR: /* Get line status register */
#ifdef CTC_DEBUG_MODEM_IOCTL
printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME,
@@ -1142,6 +1111,8 @@
.unthrottle = ctc_tty_unthrottle,
.set_termios = ctc_tty_set_termios,
.hangup = ctc_tty_hangup,
+ .tiocmget = ctc_tty_tiocmget,
+ .tiocmset = ctc_tty_tiocmset,
};

int
===== drivers/serial/mcfserial.c 1.17 vs edited =====
--- 1.17/drivers/serial/mcfserial.c Thu Jul 3 02:18:07 2003
+++ edited/drivers/serial/mcfserial.c Tue Jan 13 13:22:09 2004
@@ -985,6 +985,43 @@
local_irq_restore(flags);
}

+static int mcfrs_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+ return mcfrs_getsignals(info);
+}
+
+static int mcfrs_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
+ int rts = -1, dtr = -1;
+
+ if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+ if (set & TIOCM_RTS)
+ rts = 1;
+ if (set & TIOCM_DTR)
+ dtr = 1;
+ if (clear & TIOCM_RTS)
+ rts = 0;
+ if (clear & TIOCM_DTR)
+ dtr = 0;
+
+ mcfrs_setsignals(info, dtr, rts);
+
+ return 0;
+}
+
static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
@@ -1059,45 +1096,6 @@
info, sizeof(struct mcf_serial));
return 0;

- case TIOCMGET:
- if ((error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))))
- return(error);
- val = mcfrs_getsignals(info);
- put_user(val, (unsigned int *) arg);
- break;
-
- case TIOCMBIS:
- if ((error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))))
- return(error);
-
- get_user(val, (unsigned int *) arg);
- rts = (val & TIOCM_RTS) ? 1 : -1;
- dtr = (val & TIOCM_DTR) ? 1 : -1;
- mcfrs_setsignals(info, dtr, rts);
- break;
-
- case TIOCMBIC:
- if ((error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))))
- return(error);
- get_user(val, (unsigned int *) arg);
- rts = (val & TIOCM_RTS) ? 0 : -1;
- dtr = (val & TIOCM_DTR) ? 0 : -1;
- mcfrs_setsignals(info, dtr, rts);
- break;
-
- case TIOCMSET:
- if ((error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))))
- return(error);
- get_user(val, (unsigned int *) arg);
- rts = (val & TIOCM_RTS) ? 1 : 0;
- dtr = (val & TIOCM_DTR) ? 1 : 0;
- mcfrs_setsignals(info, dtr, rts);
- break;
-
#ifdef TIOCSET422
case TIOCSET422:
get_user(val, (unsigned int *) arg);
@@ -1563,6 +1561,8 @@
.start = mcfrs_start,
.hangup = mcfrs_hangup,
.read_proc = mcfrs_readproc,
+ .tiocmget = mcfrs_tiocmget,
+ .tiocmset = mcfrs_tiocmset,
};

/* mcfrs_init inits the driver */
===== drivers/usb/serial/ftdi_sio.c 1.55 vs edited =====
--- 1.55/drivers/usb/serial/ftdi_sio.c Tue Oct 28 13:44:01 2003
+++ edited/drivers/usb/serial/ftdi_sio.c Tue Jan 13 14:16:51 2004
@@ -580,6 +580,8 @@
static void ftdi_break_ctl (struct usb_serial_port *port, int break_state );
static void ftdi_throttle (struct usb_serial_port *port);
static void ftdi_unthrottle (struct usb_serial_port *port);
+static int ftdi_tiocmget (struct usb_serial_port *port, struct file * file);
+static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);

static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base);
static unsigned short int ftdi_232am_baud_to_divisor (int baud);
@@ -608,6 +610,8 @@
.break_ctl = ftdi_break_ctl,
.attach = ftdi_SIO_startup,
.shutdown = ftdi_shutdown,
+ .tiocmget = ftdi_tiocmget,
+ .tiocmset = ftdi_tiocmset,
};

static struct usb_serial_device_type ftdi_8U232AM_device = {
@@ -632,6 +636,8 @@
.break_ctl = ftdi_break_ctl,
.attach = ftdi_8U232AM_startup,
.shutdown = ftdi_shutdown,
+ .tiocmget = ftdi_tiocmget,
+ .tiocmset = ftdi_tiocmset,
};

static struct usb_serial_device_type ftdi_FT232BM_device = {
@@ -656,6 +662,8 @@
.break_ctl = ftdi_break_ctl,
.attach = ftdi_FT232BM_startup,
.shutdown = ftdi_shutdown,
+ .tiocmget = ftdi_tiocmget,
+ .tiocmset = ftdi_tiocmset,
};

static struct usb_serial_device_type ftdi_USB_UIRT_device = {
@@ -680,6 +688,8 @@
.break_ctl = ftdi_break_ctl,
.attach = ftdi_USB_UIRT_startup,
.shutdown = ftdi_shutdown,
+ .tiocmget = ftdi_tiocmget,
+ .tiocmset = ftdi_tiocmset,
};

/* The TIRA1 is based on a FT232BM which requires a fixed baud rate of 100000
@@ -706,6 +716,8 @@
.break_ctl = ftdi_break_ctl,
.attach = ftdi_HE_TIRA1_startup,
.shutdown = ftdi_shutdown,
+ .tiocmget = ftdi_tiocmget,
+ .tiocmset = ftdi_tiocmset,
};


@@ -1808,119 +1820,94 @@
} /* ftdi_termios */


-static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int ftdi_tiocmget (struct usb_serial_port *port, struct file * file)
{
struct usb_serial *serial = port->serial;
struct ftdi_private *priv = usb_get_serial_port_data(port);
-
- __u16 urb_value=0; /* Will hold the new flags */
char buf[2];
- int ret, mask;
-
- dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
-
- /* Based on code from acm.c and others */
- switch (cmd) {
+ int ret;

- case TIOCMGET:
- dbg("%s TIOCMGET", __FUNCTION__);
- switch (priv->chip_type) {
- case SIO:
- /* Request the status from the device */
- if ((ret = usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- FTDI_SIO_GET_MODEM_STATUS_REQUEST,
- FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
- 0, 0,
- buf, 1, WDR_TIMEOUT)) < 0 ) {
- err("%s Could not get modem status of device - err: %d", __FUNCTION__,
- ret);
- return(ret);
- }
- break;
- case FT8U232AM:
- case FT232BM:
- /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
- format as the data returned from the in point */
- if ((ret = usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- FTDI_SIO_GET_MODEM_STATUS_REQUEST,
- FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
- 0, 0,
- buf, 2, WDR_TIMEOUT)) < 0 ) {
- err("%s Could not get modem status of device - err: %d", __FUNCTION__,
- ret);
- return(ret);
- }
- break;
- default:
- return -EFAULT;
- break;
+ dbg("%s TIOCMGET", __FUNCTION__);
+ switch (priv->chip_type) {
+ case SIO:
+ /* Request the status from the device */
+ if ((ret = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, 0,
+ buf, 1, WDR_TIMEOUT)) < 0 ) {
+ err("%s Could not get modem status of device - err: %d", __FUNCTION__,
+ ret);
+ return(ret);
}
-
- return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
- (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
- (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
- (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
- priv->last_dtr_rts,
- (unsigned long *) arg);
break;
+ case FT8U232AM:
+ case FT232BM:
+ /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
+ format as the data returned from the in point */
+ if ((ret = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, 0,
+ buf, 2, WDR_TIMEOUT)) < 0 ) {
+ err("%s Could not get modem status of device - err: %d", __FUNCTION__,
+ ret);
+ return(ret);
+ }
+ break;
+ default:
+ return -EFAULT;
+ break;
+ }
+
+ return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
+ (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
+ (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
+ (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
+ priv->last_dtr_rts;
+}
+
+static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
+{
+ struct usb_serial *serial = port->serial;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ __u16 urb_value;
+ int ret;
+
+ dbg("%s TIOCMSET/BIC/BIS", __FUNCTION__);

- case TIOCMSET: /* Turns on and off the lines as specified by the mask */
- dbg("%s TIOCMSET", __FUNCTION__);
- if (get_user(mask, (unsigned long *) arg))
- return -EFAULT;
- urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
+ if ((set | clear) & TIOCM_DTR) {
+ urb_value = (set & TIOCM_DTR) ? HIGH : LOW;
if ((ret = set_dtr(port, urb_value)) < 0){
- err("Error from DTR set urb (TIOCMSET)");
+ err("Error from DTR set urb (TIOCM)");
return(ret);
}
- urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW);
+ }
+ if ((set | clear) & TIOCM_RTS) {
+ urb_value = (set & TIOCM_RTS) ? HIGH : LOW;
if ((ret = set_rts(port, urb_value)) < 0){
- err("Error from RTS set urb (TIOCMSET)");
+ err("Error from RTS set urb (TIOCM)");
return(ret);
}
- return(0);
- break;
-
- case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
- dbg("%s TIOCMBIS", __FUNCTION__);
- if (get_user(mask, (unsigned long *) arg))
- return -EFAULT;
- if (mask & TIOCM_DTR){
- if ((ret = set_dtr(port, HIGH)) < 0) {
- err("Urb to set DTR failed");
- return(ret);
- }
- }
- if (mask & TIOCM_RTS) {
- if ((ret = set_rts(port, HIGH)) < 0){
- err("Urb to set RTS failed");
- return(ret);
- }
- }
- return(0);
- break;
+ }
+ return(0);
+}

- case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
- dbg("%s TIOCMBIC", __FUNCTION__);
- if (get_user(mask, (unsigned long *) arg))
- return -EFAULT;
- if (mask & TIOCM_DTR){
- if ((ret = set_dtr(port, LOW)) < 0){
- err("Urb to unset DTR failed");
- return(ret);
- }
- }
- if (mask & TIOCM_RTS) {
- if ((ret = set_rts(port, LOW)) < 0){
- err("Urb to unset RTS failed");
- return(ret);
- }
- }
- return(0);
- break;
+static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+{
+ struct usb_serial *serial = port->serial;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);

+ __u16 urb_value=0; /* Will hold the new flags */
+ char buf[2];
+ int ret, mask;
+
+ dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
+
+ /* Based on code from acm.c and others */
+ switch (cmd) {
/*
* I had originally implemented TCSET{A,S}{,F,W} and
* TCGET{A,S} here separately, however when testing I

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-13 17:44:16

by Russell King

[permalink] [raw]
Subject: [3/3] 2.6 broken serial drivers

Here is a patch which updates various serial drivers in the kernel to
make them less broken than they were before. Nevertheless, they are
still broken.

The improvement is to make these drivers use the tiocmget/tiocmset
methods, which are present in the 2.6 kernel.

Many of these have been incorrectly converted from the old global IRQ
locking without regard for SMP issues, or still use the old global IRQ
locking methods which are no longer present in 2.6 kernels.

The full message thread can be found at:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=1dvnl-5Pr-1%40gated-at.bofh.it&rnum=1&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DISO-8859-1%26q%3DOutstanding%2Bfixups%26btnG%3DGoogle%2BSearch%26meta%3Dgroup%253Dlinux.kernel

===== drivers/char/amiserial.c 1.28 vs edited =====
--- 1.28/drivers/char/amiserial.c Tue Sep 30 01:23:52 2003
+++ edited/drivers/char/amiserial.c Tue Jan 13 15:30:32 2004
@@ -1248,57 +1248,48 @@
}


-static int get_modem_info(struct async_struct * info, unsigned int *value)
+static int rs_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct async_struct * info = (struct async_struct *)tty->driver_data;
unsigned char control, status;
- unsigned int result;
unsigned long flags;

+ if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
control = info->MCR;
local_irq_save(flags);
status = ciab.pra;
local_irq_restore(flags);
- result = ((control & SER_RTS) ? TIOCM_RTS : 0)
+ return ((control & SER_RTS) ? TIOCM_RTS : 0)
| ((control & SER_DTR) ? TIOCM_DTR : 0)
| (!(status & SER_DCD) ? TIOCM_CAR : 0)
| (!(status & SER_DSR) ? TIOCM_DSR : 0)
| (!(status & SER_CTS) ? TIOCM_CTS : 0);
- if (copy_to_user(value, &result, sizeof(int)))
- return -EFAULT;
- return 0;
}

-static int set_modem_info(struct async_struct * info, unsigned int cmd,
- unsigned int *value)
+static int rs_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
- unsigned int arg;
+ struct async_struct * info = (struct async_struct *)tty->driver_data;
unsigned long flags;

- if (copy_from_user(&arg, value, sizeof(int)))
- return -EFAULT;
+ if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;

- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- info->MCR |= SER_RTS;
- if (arg & TIOCM_DTR)
- info->MCR |= SER_DTR;
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- info->MCR &= ~SER_RTS;
- if (arg & TIOCM_DTR)
- info->MCR &= ~SER_DTR;
- break;
- case TIOCMSET:
- info->MCR = ((info->MCR & ~(SER_RTS | SER_DTR))
- | ((arg & TIOCM_RTS) ? SER_RTS : 0)
- | ((arg & TIOCM_DTR) ? SER_DTR : 0));
- break;
- default:
- return -EINVAL;
- }
local_irq_save(flags);
+ if (set & TIOCM_RTS)
+ info->MCR |= SER_RTS;
+ if (set & TIOCM_DTR)
+ info->MCR |= SER_DTR;
+ if (clear & TIOCM_RTS)
+ info->MCR &= ~SER_RTS;
+ if (clear & TIOCM_DTR)
+ info->MCR &= ~SER_DTR;
rtsdtr_ctrl(info->MCR);
local_irq_restore(flags);
return 0;
@@ -1344,12 +1335,6 @@
}

switch (cmd) {
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
case TIOCGSERIAL:
return get_serial_info(info,
(struct serial_struct *) arg);
@@ -2045,6 +2030,8 @@
.send_xchar = rs_send_xchar,
.wait_until_sent = rs_wait_until_sent,
.read_proc = rs_read_proc,
+ .tiocmget = rs_tiocmget,
+ .tiocmset = rs_tiocmset,
};

/*
===== drivers/char/epca.c 1.32 vs edited =====
--- 1.32/drivers/char/epca.c Thu Sep 11 23:46:11 2003
+++ edited/drivers/char/epca.c Tue Jan 13 15:51:58 2004
@@ -2931,6 +2931,96 @@
}
/* --------------------- Begin pc_ioctl ----------------------- */

+static int pc_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct channel *ch = (struct channel *) tty->driver_data;
+ volatile struct board_chan *bc;
+ unsigned int mstat, mflag = 0;
+ unsigned long flags;
+
+ if (ch)
+ bc = ch->brdchan;
+ else
+ {
+ printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmget!\n");
+ return(-EINVAL);
+ }
+
+ save_flags(flags);
+ cli();
+ globalwinon(ch);
+ mstat = bc->mstat;
+ memoff(ch);
+ restore_flags(flags);
+
+ if (mstat & ch->m_dtr)
+ mflag |= TIOCM_DTR;
+
+ if (mstat & ch->m_rts)
+ mflag |= TIOCM_RTS;
+
+ if (mstat & ch->m_cts)
+ mflag |= TIOCM_CTS;
+
+ if (mstat & ch->dsr)
+ mflag |= TIOCM_DSR;
+
+ if (mstat & ch->m_ri)
+ mflag |= TIOCM_RI;
+
+ if (mstat & ch->dcd)
+ mflag |= TIOCM_CD;
+
+ return mflag;
+}
+
+static int pc_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct channel *ch = (struct channel *) tty->driver_data;
+ unsigned long flags;
+
+ if (!ch) {
+ printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmset!\n");
+ return(-EINVAL);
+ }
+
+ save_flags(flags);
+ cli();
+ /*
+ * I think this modemfake stuff is broken. It doesn't
+ * correctly reflect the behaviour desired by the TIOCM*
+ * ioctls. Therefore this is probably broken.
+ */
+ if (set & TIOCM_RTS) {
+ ch->modemfake |= ch->m_rts;
+ ch->modem |= ch->m_rts;
+ }
+ if (set & TIOCM_DTR) {
+ ch->modemfake |= ch->m_dtr;
+ ch->modem |= ch->m_dtr;
+ }
+ if (clear & TIOCM_RTS) {
+ ch->modemfake |= ch->m_rts;
+ ch->modem &= ~ch->m_rts;
+ }
+ if (clear & TIOCM_DTR) {
+ ch->modemfake |= ch->m_dtr;
+ ch->modem &= ~ch->m_dtr;
+ }
+
+ globalwinon(ch);
+
+ /* --------------------------------------------------------------
+ The below routine generally sets up parity, baud, flow control
+ issues, etc.... It effect both control flags and input flags.
+ ------------------------------------------------------------------ */
+
+ epcaparam(tty,ch);
+ memoff(ch);
+ restore_flags(flags);
+}
+
static int pc_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{ /* Begin pc_ioctl */
@@ -3021,90 +3111,15 @@
}

case TIOCMODG:
- case TIOCMGET:
-
- mflag = 0;
-
- cli();
- globalwinon(ch);
- mstat = bc->mstat;
- memoff(ch);
- restore_flags(flags);
-
- if (mstat & ch->m_dtr)
- mflag |= TIOCM_DTR;
-
- if (mstat & ch->m_rts)
- mflag |= TIOCM_RTS;
-
- if (mstat & ch->m_cts)
- mflag |= TIOCM_CTS;
-
- if (mstat & ch->dsr)
- mflag |= TIOCM_DSR;
-
- if (mstat & ch->m_ri)
- mflag |= TIOCM_RI;
-
- if (mstat & ch->dcd)
- mflag |= TIOCM_CD;
-
- error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
-
- if (error)
- return error;
-
- putUser(mflag, (unsigned int *) arg);
-
+ mflag = pc_tiocmget(tty, file);
+ if (putUser(mflag, (unsigned int *) arg))
+ return -EFAULT;
break;

- case TIOCMBIS:
- case TIOCMBIC:
case TIOCMODS:
- case TIOCMSET:
-
- getUser(mstat, (unsigned int *)arg);
-
- mflag = 0;
- if (mstat & TIOCM_DTR)
- mflag |= ch->m_dtr;
-
- if (mstat & TIOCM_RTS)
- mflag |= ch->m_rts;
-
- switch (cmd)
- { /* Begin switch cmd */
-
- case TIOCMODS:
- case TIOCMSET:
- ch->modemfake = ch->m_dtr|ch->m_rts;
- ch->modem = mflag;
- break;
-
- case TIOCMBIS:
- ch->modemfake |= mflag;
- ch->modem |= mflag;
- break;
-
- case TIOCMBIC:
- ch->modemfake |= mflag;
- ch->modem &= ~mflag;
- break;
-
- } /* End switch cmd */
-
- cli();
- globalwinon(ch);
-
- /* --------------------------------------------------------------
- The below routine generally sets up parity, baud, flow control
- issues, etc.... It effect both control flags and input flags.
- ------------------------------------------------------------------ */
-
- epcaparam(tty,ch);
- memoff(ch);
- restore_flags(flags);
- break;
+ if (getUser(mstat, (unsigned int *)arg))
+ return -EFAULT;
+ return pc_tiocmset(tty, file, mstat, ~mstat);

case TIOCSDTR:
ch->omodem |= ch->m_dtr;
===== drivers/char/esp.c 1.26 vs edited =====
--- 1.26/drivers/char/esp.c Sun Oct 5 07:51:01 2003
+++ edited/drivers/char/esp.c Tue Jan 13 15:56:56 2004
@@ -1753,55 +1753,52 @@
}


-static int get_modem_info(struct esp_struct * info, unsigned int *value)
+static int esp_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct esp_struct * info = (struct esp_struct *)tty->driver_data;
unsigned char control, status;
- unsigned int result;
+
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;

control = info->MCR;
cli();
serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
status = serial_in(info, UART_ESI_STAT2);
sti();
- result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+ return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
| ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
| ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
| ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
| ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
- return put_user(result,value);
}

-static int set_modem_info(struct esp_struct * info, unsigned int cmd,
- unsigned int *value)
+static int esp_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct esp_struct * info = (struct esp_struct *)tty->driver_data;
unsigned int arg;

- if (get_user(arg, value))
- return -EFAULT;
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;

- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- info->MCR |= UART_MCR_RTS;
- if (arg & TIOCM_DTR)
- info->MCR |= UART_MCR_DTR;
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- info->MCR &= ~UART_MCR_RTS;
- if (arg & TIOCM_DTR)
- info->MCR &= ~UART_MCR_DTR;
- break;
- case TIOCMSET:
- info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR))
- | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
- | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
- break;
- default:
- return -EINVAL;
- }
cli();
+
+ if (set & TIOCM_RTS)
+ info->MCR |= UART_MCR_RTS;
+ if (set & TIOCM_DTR)
+ info->MCR |= UART_MCR_DTR;
+
+ if (clear & TIOCM_RTS)
+ info->MCR &= ~UART_MCR_RTS;
+ if (clear & TIOCM_DTR)
+ info->MCR &= ~UART_MCR_DTR;
+
serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
serial_out(info, UART_ESI_CMD2, UART_MCR);
serial_out(info, UART_ESI_CMD2, info->MCR);
@@ -1853,12 +1850,6 @@
}

switch (cmd) {
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
case TIOCGSERIAL:
return get_serial_info(info,
(struct serial_struct *) arg);
@@ -2444,6 +2435,8 @@
.hangup = esp_hangup,
.break_ctl = esp_break,
.wait_until_sent = rs_wait_until_sent,
+ .tiocmget = esp_tiocmget,
+ .tiocmset = esp_tiocmset,
};

/*
===== drivers/char/isicom.c 1.27 vs edited =====
--- 1.27/drivers/char/isicom.c Sun Oct 5 07:51:01 2003
+++ edited/drivers/char/isicom.c Tue Jan 13 13:48:05 2004
@@ -1291,63 +1291,44 @@
out: restore_flags(flags);
}

-static int isicom_get_modem_info(struct isi_port * port, unsigned int * value)
+static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
/* just send the port status */
- unsigned int info;
unsigned short status = port->status;
+
+ if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
+ return -ENODEV;

- info = ((status & ISI_RTS) ? TIOCM_RTS : 0) |
+ return ((status & ISI_RTS) ? TIOCM_RTS : 0) |
((status & ISI_DTR) ? TIOCM_DTR : 0) |
((status & ISI_DCD) ? TIOCM_CAR : 0) |
((status & ISI_DSR) ? TIOCM_DSR : 0) |
((status & ISI_CTS) ? TIOCM_CTS : 0) |
((status & ISI_RI ) ? TIOCM_RI : 0);
- return put_user(info, (unsigned int *) value);
}

-static int isicom_set_modem_info(struct isi_port * port, unsigned int cmd,
- unsigned int * value)
+static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
unsigned int arg;
unsigned long flags;

- if(get_user(arg, value))
- return -EFAULT;
+ if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
+ return -ENODEV;

save_flags(flags); cli();
-
- switch(cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- raise_rts(port);
- if (arg & TIOCM_DTR)
- raise_dtr(port);
- break;
-
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- drop_rts(port);
- if (arg & TIOCM_DTR)
- drop_dtr(port);
- break;
-
- case TIOCMSET:
- if (arg & TIOCM_RTS)
- raise_rts(port);
- else
- drop_rts(port);
-
- if (arg & TIOCM_DTR)
- raise_dtr(port);
- else
- drop_dtr(port);
- break;
-
- default:
- restore_flags(flags);
- return -EINVAL;
- }
+ if (set & TIOCM_RTS)
+ raise_rts(port);
+ if (set & TIOCM_DTR)
+ raise_dtr(port);
+
+ if (clear & TIOCM_RTS)
+ drop_rts(port);
+ if (clear & TIOCM_DTR)
+ drop_dtr(port);
+
restore_flags(flags);
return 0;
}
@@ -1445,15 +1426,6 @@
(arg ? CLOCAL : 0));
return 0;

- case TIOCMGET:
- return isicom_get_modem_info(port, (unsigned int*) arg);
-
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return isicom_set_modem_info(port, cmd,
- (unsigned int *) arg);
-
case TIOCGSERIAL:
return isicom_get_serial_info(port,
(struct serial_struct *) arg);
@@ -1640,6 +1612,8 @@
.start = isicom_start,
.hangup = isicom_hangup,
.flush_buffer = isicom_flush_buffer,
+ .tiocmget = isicom_tiocmget,
+ .tiocmset = isicom_tiocmset,
};

static int register_drivers(void)
===== drivers/char/moxa.c 1.27 vs edited =====
--- 1.27/drivers/char/moxa.c Tue Sep 30 01:23:52 2003
+++ edited/drivers/char/moxa.c Tue Jan 13 16:18:08 2004
@@ -231,6 +231,9 @@
static void moxa_stop(struct tty_struct *);
static void moxa_start(struct tty_struct *);
static void moxa_hangup(struct tty_struct *);
+static int moxa_tiocmget(struct tty_struct *tty, struct file *file);
+static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
static void moxa_poll(unsigned long);
static void set_tty_param(struct tty_struct *);
static int block_till_ready(struct tty_struct *, struct file *,
@@ -288,6 +291,8 @@
.stop = moxa_stop,
.start = moxa_start,
.hangup = moxa_hangup,
+ .tiocmget = moxa_tiocmget,
+ .tiocmset = moxa_tiocmset,
};

static int __init moxa_init(void)
@@ -741,6 +746,53 @@
ch->statusflags |= LOWWAIT;
}

+static int moxa_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+ int flag = 0, dtr, rts;
+
+ port = PORTNO(tty);
+ if ((port != MAX_PORTS) && (!ch))
+ return (-EINVAL);
+
+ MoxaPortGetLineOut(ch->port, &dtr, &rts);
+ if (dtr)
+ flag |= TIOCM_DTR;
+ if (rts)
+ flag |= TIOCM_RTS;
+ dtr = MoxaPortLineStatus(ch->port);
+ if (dtr & 1)
+ flag |= TIOCM_CTS;
+ if (dtr & 2)
+ flag |= TIOCM_DSR;
+ if (dtr & 4)
+ flag |= TIOCM_CD;
+ return flag;
+}
+
+static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+ int flag = 0, dtr, rts;
+
+ port = PORTNO(tty);
+ if ((port != MAX_PORTS) && (!ch))
+ return (-EINVAL);
+
+ MoxaPortGetLineOut(ch->port, &dtr, &rts);
+ if (set & TIOCM_RTS)
+ rts = 1;
+ if (set & TIOCM_DTR)
+ dtr = 1;
+ if (clear & TIOCM_RTS)
+ rts = 0;
+ if (clear & TIOCM_DTR)
+ dtr = 0;
+ MoxaPortLineCtrl(ch->port, dtr, rts);
+ return 0;
+}
+
static int moxa_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -783,51 +835,6 @@
ch->asyncflags &= ~ASYNC_CHECK_CD;
else
ch->asyncflags |= ASYNC_CHECK_CD;
- return (0);
- case TIOCMGET:
- flag = 0;
- MoxaPortGetLineOut(ch->port, &dtr, &rts);
- if (dtr)
- flag |= TIOCM_DTR;
- if (rts)
- flag |= TIOCM_RTS;
- dtr = MoxaPortLineStatus(ch->port);
- if (dtr & 1)
- flag |= TIOCM_CTS;
- if (dtr & 2)
- flag |= TIOCM_DSR;
- if (dtr & 4)
- flag |= TIOCM_CD;
- return put_user(flag, (unsigned int *) arg);
- case TIOCMBIS:
- if(get_user(retval, (unsigned int *) arg))
- return -EFAULT;
- MoxaPortGetLineOut(ch->port, &dtr, &rts);
- if (retval & TIOCM_RTS)
- rts = 1;
- if (retval & TIOCM_DTR)
- dtr = 1;
- MoxaPortLineCtrl(ch->port, dtr, rts);
- return (0);
- case TIOCMBIC:
- if(get_user(retval, (unsigned int *) arg))
- return -EFAULT;
- MoxaPortGetLineOut(ch->port, &dtr, &rts);
- if (retval & TIOCM_RTS)
- rts = 0;
- if (retval & TIOCM_DTR)
- dtr = 0;
- MoxaPortLineCtrl(ch->port, dtr, rts);
- return (0);
- case TIOCMSET:
- if(get_user(retval, (unsigned long *) arg))
- return -EFAULT;
- dtr = rts = 0;
- if (retval & TIOCM_RTS)
- rts = 1;
- if (retval & TIOCM_DTR)
- dtr = 1;
- MoxaPortLineCtrl(ch->port, dtr, rts);
return (0);
case TIOCGSERIAL:
return (moxa_get_serial_info(ch, (struct serial_struct *) arg));
===== drivers/char/mxser.c 1.29 vs edited =====
--- 1.29/drivers/char/mxser.c Tue Sep 30 01:23:52 2003
+++ edited/drivers/char/mxser.c Tue Jan 13 16:23:48 2004
@@ -349,8 +349,8 @@
static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct *);
static int mxser_get_lsr_info(struct mxser_struct *, unsigned int *);
static void mxser_send_break(struct mxser_struct *, int);
-static int mxser_get_modem_info(struct mxser_struct *, unsigned int *);
-static int mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned int *);
+static int mxser_tiocmget(struct tty_struct *, struct file *);
+static int mxser_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int);

/*
* The MOXA C168/C104 serial driver boot-time initialization code!
@@ -491,6 +491,8 @@
.stop = mxser_stop,
.start = mxser_start,
.hangup = mxser_hangup,
+ .tiocmget = mxser_tiocmget,
+ .tiocmset = mxser_tiocmset,
};

static int __init mxser_module_init(void)
@@ -1009,12 +1011,6 @@
tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
return (0);
- case TIOCMGET:
- return (mxser_get_modem_info(info, (unsigned int *) arg));
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return (mxser_set_modem_info(info, cmd, (unsigned int *) arg));
case TIOCGSERIAL:
return (mxser_get_serial_info(info, (struct serial_struct *) arg));
case TIOCSSERIAL:
@@ -2150,13 +2146,18 @@
restore_flags(flags);
}

-static int mxser_get_modem_info(struct mxser_struct *info,
- unsigned int *value)
+static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
unsigned char control, status;
unsigned int result;
unsigned long flags;

+ if (PORTNO(tty) == MXSER_PORTS)
+ return (-ENOIOCTLCMD);
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return (-EIO);
+
control = info->MCR;
save_flags(flags);
cli();
@@ -2164,46 +2165,38 @@
if (status & UART_MSR_ANY_DELTA)
mxser_check_modem_status(info, status);
restore_flags(flags);
- result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
+ return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
- return put_user(result, value);
}

-static int mxser_set_modem_info(struct mxser_struct *info, unsigned int cmd,
- unsigned int *value)
+static int mxser_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
unsigned int arg;
unsigned long flags;

- if(get_user(arg, value))
- return -EFAULT;
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- info->MCR |= UART_MCR_RTS;
- if (arg & TIOCM_DTR)
- info->MCR |= UART_MCR_DTR;
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- info->MCR &= ~UART_MCR_RTS;
- if (arg & TIOCM_DTR)
- info->MCR &= ~UART_MCR_DTR;
- break;
- case TIOCMSET:
- info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) |
- ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) |
- ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
- break;
- default:
- return (-EINVAL);
- }
+ if (PORTNO(tty) == MXSER_PORTS)
+ return (-ENOIOCTLCMD);
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return (-EIO);
+
save_flags(flags);
cli();
+ if (set & TIOCM_RTS)
+ info->MCR |= UART_MCR_RTS;
+ if (set & TIOCM_DTR)
+ info->MCR |= UART_MCR_DTR;
+
+ if (clear & TIOCM_RTS)
+ info->MCR &= ~UART_MCR_RTS;
+ if (clear & TIOCM_DTR)
+ info->MCR &= ~UART_MCR_DTR;
+
outb(info->MCR, info->base + UART_MCR);
restore_flags(flags);
return (0);
===== drivers/char/pcxx.c 1.22 vs edited =====
--- 1.22/drivers/char/pcxx.c Tue Sep 30 01:23:52 2003
+++ edited/drivers/char/pcxx.c Tue Jan 13 16:35:47 2004
@@ -173,6 +173,9 @@
static inline void memoff(struct channel *ch);
static inline void assertgwinon(struct channel *ch);
static inline void assertmemoff(struct channel *ch);
+static int pcxe_tiocmget(struct tty_struct *tty, struct file *file);
+static int pcxe_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);

#define TZ_BUFSZ 4096

@@ -1029,6 +1032,8 @@
.stop = pcxe_stop,
.start = pcxe_start,
.hangup = pcxe_hangup,
+ .tiocmget = pcxe_tiocmget,
+ .tiocmset = pcxe_tiocmset,
};

/*
@@ -1983,6 +1988,89 @@
}


+static int pcxe_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct channel *ch = (struct channel *) tty->driver_data;
+ volatile struct board_chan *bc;
+ unsigned long flags;
+ int mflag = 0;
+
+ if(ch)
+ bc = ch->brdchan;
+ else {
+ printk("ch is NULL in %s!\n", __FUNCTION__);
+ return(-EINVAL);
+ }
+
+ save_flags(flags);
+ cli();
+ globalwinon(ch);
+ mstat = bc->mstat;
+ memoff(ch);
+ restore_flags(flags);
+
+ if(mstat & DTR)
+ mflag |= TIOCM_DTR;
+ if(mstat & RTS)
+ mflag |= TIOCM_RTS;
+ if(mstat & CTS)
+ mflag |= TIOCM_CTS;
+ if(mstat & ch->dsr)
+ mflag |= TIOCM_DSR;
+ if(mstat & RI)
+ mflag |= TIOCM_RI;
+ if(mstat & ch->dcd)
+ mflag |= TIOCM_CD;
+
+ return mflag;
+}
+
+
+static int pcxe_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct channel *ch = (struct channel *) tty->driver_data;
+ volatile struct board_chan *bc;
+ unsigned long flags;
+
+ if(ch)
+ bc = ch->brdchan;
+ else {
+ printk("ch is NULL in %s!\n", __FUNCTION__);
+ return(-EINVAL);
+ }
+
+ save_flags(flags);
+ cli();
+ /*
+ * I think this modemfake stuff is broken. It doesn't
+ * correctly reflect the behaviour desired by the TIOCM*
+ * ioctls. Therefore this is probably broken.
+ */
+ if (set & TIOCM_DTR) {
+ ch->modemfake |= DTR;
+ ch->modem |= DTR;
+ }
+ if (set & TIOCM_RTS) {
+ ch->modemfake |= RTS;
+ ch->modem |= RTS;
+ }
+
+ if (clear & TIOCM_DTR) {
+ ch->modemfake |= DTR;
+ ch->modem &= ~DTR;
+ }
+ if (clear & TIOCM_RTS) {
+ ch->modemfake |= RTS;
+ ch->modem &= ~RTS;
+ }
+ globalwinon(ch);
+ pcxxparam(tty,ch);
+ memoff(ch);
+ restore_flags(flags);
+}
+
+
static int pcxe_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
@@ -2036,69 +2124,15 @@
return 0;

case TIOCMODG:
- case TIOCMGET:
- mflag = 0;
-
- cli();
- globalwinon(ch);
- mstat = bc->mstat;
- memoff(ch);
- restore_flags(flags);
-
- if(mstat & DTR)
- mflag |= TIOCM_DTR;
- if(mstat & RTS)
- mflag |= TIOCM_RTS;
- if(mstat & CTS)
- mflag |= TIOCM_CTS;
- if(mstat & ch->dsr)
- mflag |= TIOCM_DSR;
- if(mstat & RI)
- mflag |= TIOCM_RI;
- if(mstat & ch->dcd)
- mflag |= TIOCM_CD;
-
+ mflag = pcxe_tiocmget(tty, file);
if (put_user(mflag, (unsigned int *) arg))
return -EFAULT;
break;

- case TIOCMBIS:
- case TIOCMBIC:
case TIOCMODS:
- case TIOCMSET:
if (get_user(mstat, (unsigned int *) arg))
return -EFAULT;
-
- mflag = 0;
- if(mstat & TIOCM_DTR)
- mflag |= DTR;
- if(mstat & TIOCM_RTS)
- mflag |= RTS;
-
- switch(cmd) {
- case TIOCMODS:
- case TIOCMSET:
- ch->modemfake = DTR|RTS;
- ch->modem = mflag;
- break;
-
- case TIOCMBIS:
- ch->modemfake |= mflag;
- ch->modem |= mflag;
- break;
-
- case TIOCMBIC:
- ch->modemfake &= ~mflag;
- ch->modem &= ~mflag;
- break;
- }
-
- cli();
- globalwinon(ch);
- pcxxparam(tty,ch);
- memoff(ch);
- restore_flags(flags);
- break;
+ return pcxe_tiocmset(tty, file, mstat, ~mstat);

case TIOCSDTR:
cli();
===== drivers/char/riscom8.c 1.23 vs edited =====
--- 1.23/drivers/char/riscom8.c Thu Sep 4 07:39:56 2003
+++ edited/drivers/char/riscom8.c Tue Jan 13 16:27:00 2004
@@ -1306,59 +1306,53 @@
(tty->ldisc.write_wakeup)(tty);
}

-static int rc_get_modem_info(struct riscom_port * port, unsigned int *value)
+static int rc_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
struct riscom_board * bp;
unsigned char status;
- unsigned int result;
unsigned long flags;

+ if (rc_paranoia_check(port, tty->name, __FUNCTION__))
+ return -ENODEV;
+
bp = port_Board(port);
save_flags(flags); cli();
rc_out(bp, CD180_CAR, port_No(port));
status = rc_in(bp, CD180_MSVR);
result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG;
restore_flags(flags);
- result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0)
+ return ((status & MSVR_RTS) ? TIOCM_RTS : 0)
| ((status & MSVR_DTR) ? TIOCM_DTR : 0)
| ((status & MSVR_CD) ? TIOCM_CAR : 0)
| ((status & MSVR_DSR) ? TIOCM_DSR : 0)
| ((status & MSVR_CTS) ? TIOCM_CTS : 0);
- return put_user(result, value);
}

-static int rc_set_modem_info(struct riscom_port * port, unsigned int cmd,
- unsigned int *value)
+static int rc_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
unsigned int arg;
unsigned long flags;
- struct riscom_board *bp = port_Board(port);
+ struct riscom_board *bp;
+
+ if (rc_paranoia_check(port, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ bp = port_Board(port);

- if (get_user(arg, value))
- return -EFAULT;
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- port->MSVR |= MSVR_RTS;
- if (arg & TIOCM_DTR)
- bp->DTR &= ~(1u << port_No(port));
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- port->MSVR &= ~MSVR_RTS;
- if (arg & TIOCM_DTR)
- bp->DTR |= (1u << port_No(port));
- break;
- case TIOCMSET:
- port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | MSVR_RTS) :
- (port->MSVR & ~MSVR_RTS);
- bp->DTR = arg & TIOCM_DTR ? (bp->DTR &= ~(1u << port_No(port))) :
- (bp->DTR |= (1u << port_No(port)));
- break;
- default:
- return -EINVAL;
- }
save_flags(flags); cli();
+ if (set & TIOCM_RTS)
+ port->MSVR |= MSVR_RTS;
+ if (set & TIOCM_DTR)
+ bp->DTR &= ~(1u << port_No(port));
+
+ if (clear & TIOCM_RTS)
+ port->MSVR &= ~MSVR_RTS;
+ if (clear & TIOCM_DTR)
+ bp->DTR |= (1u << port_No(port));
+
rc_out(bp, CD180_CAR, port_No(port));
rc_out(bp, CD180_MSVR, port->MSVR);
rc_out(bp, RC_DTR, bp->DTR);
@@ -1485,12 +1479,6 @@
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
break;
- case TIOCMGET:
- return rc_get_modem_info(port, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return rc_set_modem_info(port, cmd, (unsigned int *) arg);
case TIOCGSERIAL:
return rc_get_serial_info(port, (struct serial_struct *) arg);
case TIOCSSERIAL:
@@ -1677,6 +1665,8 @@
.stop = rc_stop,
.start = rc_start,
.hangup = rc_hangup,
+ .tiocmget = rc_tiocmget,
+ .tiocmset = rx_tiocmset,
};

static inline int rc_init_drivers(void)
===== drivers/char/serial167.c 1.31 vs edited =====
--- 1.31/drivers/char/serial167.c Tue Sep 30 01:23:52 2003
+++ edited/drivers/char/serial167.c Tue Jan 13 15:22:11 2004
@@ -1492,8 +1492,9 @@
} /* set_serial_info */

static int
-get_modem_info(struct cyclades_port * info, unsigned int *value)
+cy_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
int channel;
volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
unsigned long flags;
@@ -1507,36 +1508,32 @@
status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
local_irq_restore(flags);

- result = ((status & CyRTS) ? TIOCM_RTS : 0)
+ return ((status & CyRTS) ? TIOCM_RTS : 0)
| ((status & CyDTR) ? TIOCM_DTR : 0)
| ((status & CyDCD) ? TIOCM_CAR : 0)
| ((status & CyDSR) ? TIOCM_DSR : 0)
| ((status & CyCTS) ? TIOCM_CTS : 0);
- return put_user(result,(unsigned int *) value);
-} /* get_modem_info */
+} /* cy_tiocmget */

static int
-set_modem_info(struct cyclades_port * info, unsigned int cmd,
- unsigned int *value)
+cy_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
int channel;
volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
unsigned long flags;
unsigned int arg;

- if (get_user(arg, (unsigned long *) value))
- return -EFAULT;
channel = info->line;

- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS){
+ if (set & TIOCM_RTS){
local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
base_addr[CyMSVR1] = CyRTS;
local_irq_restore(flags);
}
- if (arg & TIOCM_DTR){
+ if (set & TIOCM_DTR){
local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
/* CP('S');CP('2'); */
@@ -1547,15 +1544,14 @@
#endif
local_irq_restore(flags);
}
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS){
+
+ if (clear & TIOCM_RTS){
local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
base_addr[CyMSVR1] = 0;
local_irq_restore(flags);
}
- if (arg & TIOCM_DTR){
+ if (clear & TIOCM_DTR){
local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
/* CP('C');CP('2'); */
@@ -1566,44 +1562,7 @@
#endif
local_irq_restore(flags);
}
- break;
- case TIOCMSET:
- if (arg & TIOCM_RTS){
- local_irq_save(flags);
- base_addr[CyCAR] = (u_char)channel;
- base_addr[CyMSVR1] = CyRTS;
- local_irq_restore(flags);
- }else{
- local_irq_save(flags);
- base_addr[CyCAR] = (u_char)channel;
- base_addr[CyMSVR1] = 0;
- local_irq_restore(flags);
- }
- if (arg & TIOCM_DTR){
- local_irq_save(flags);
- base_addr[CyCAR] = (u_char)channel;
-/* CP('S');CP('3'); */
- base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
- printk("cyc: %d: raising DTR\n", __LINE__);
- printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
-#endif
- local_irq_restore(flags);
- }else{
- local_irq_save(flags);
- base_addr[CyCAR] = (u_char)channel;
-/* CP('C');CP('3'); */
- base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
- printk("cyc: %d: dropping DTR\n", __LINE__);
- printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
-#endif
- local_irq_restore(flags);
- }
- break;
- default:
- return -EINVAL;
- }
+
return 0;
} /* set_modem_info */

@@ -1777,11 +1736,6 @@
tty_wait_until_sent(tty,0);
send_break(info, arg ? arg*(HZ/10) : HZ/4);
break;
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- ret_val = set_modem_info(info, cmd, (unsigned int *) arg);
- break;

/* The following commands are incompletely implemented!!! */
case TIOCGSOFTCAR:
@@ -1794,9 +1748,6 @@
tty->termios->c_cflag =
((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));
break;
- case TIOCMGET:
- ret_val = get_modem_info(info, (unsigned int *) arg);
- break;
case TIOCGSERIAL:
ret_val = get_serial_info(info, (struct serial_struct *) arg);
break;
@@ -2299,6 +2250,8 @@
.stop = cy_stop,
.start = cy_start,
.hangup = cy_hangup,
+ .tiocmget = cy_tiocmget,
+ .tiocmset = cy_tiocmset,
};
/* The serial driver boot-time initialization code!
Hardware I/O ports are mapped to character special devices on a
===== drivers/char/specialix.c 1.26 vs edited =====
--- 1.26/drivers/char/specialix.c Wed Sep 24 07:15:15 2003
+++ edited/drivers/char/specialix.c Tue Jan 13 15:14:59 2004
@@ -1652,13 +1652,17 @@
}


-static int sx_get_modem_info(struct specialix_port * port, unsigned int *value)
+static int sx_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board * bp;
unsigned char status;
unsigned int result;
unsigned long flags;

+ if (sx_paranoia_check(port, tty->name, __FUNCTION__))
+ return -ENODEV;
+
bp = port_Board(port);
save_flags(flags); cli();
sx_out(bp, CD186x_CAR, port_No(port));
@@ -1682,71 +1686,51 @@
|/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
| ((status & MSVR_CTS) ? TIOCM_CTS : 0);
}
- put_user(result,(unsigned int *) value);
- return 0;
+
+ return result;
}


-static int sx_set_modem_info(struct specialix_port * port, unsigned int cmd,
- unsigned int *value)
+static int sx_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct specialix_port *port = (struct specialix_port *)tty->driver_data;
int error;
unsigned int arg;
unsigned long flags;
- struct specialix_board *bp = port_Board(port);
+ struct specialix_board *bp;

- error = verify_area(VERIFY_READ, value, sizeof(int));
- if (error)
- return error;
+ if (sx_paranoia_check(port, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ bp = port_Board(port);

- get_user(arg, (unsigned long *) value);
- switch (cmd) {
- case TIOCMBIS:
- /* if (arg & TIOCM_RTS)
- port->MSVR |= MSVR_RTS; */
- /* if (arg & TIOCM_DTR)
- port->MSVR |= MSVR_DTR; */
-
- if (SX_CRTSCTS(port->tty)) {
- if (arg & TIOCM_RTS)
- port->MSVR |= MSVR_DTR;
- } else {
- if (arg & TIOCM_DTR)
- port->MSVR |= MSVR_DTR;
- }
- break;
- case TIOCMBIC:
- /* if (arg & TIOCM_RTS)
- port->MSVR &= ~MSVR_RTS; */
- /* if (arg & TIOCM_DTR)
- port->MSVR &= ~MSVR_DTR; */
- if (SX_CRTSCTS(port->tty)) {
- if (arg & TIOCM_RTS)
- port->MSVR &= ~MSVR_DTR;
- } else {
- if (arg & TIOCM_DTR)
- port->MSVR &= ~MSVR_DTR;
- }
- break;
- case TIOCMSET:
- /* port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | MSVR_RTS) :
- (port->MSVR & ~MSVR_RTS); */
- /* port->MSVR = (arg & TIOCM_DTR) ? (port->MSVR | MSVR_DTR) :
- (port->MSVR & ~MSVR_DTR); */
- if (SX_CRTSCTS(port->tty)) {
- port->MSVR = (arg & TIOCM_RTS) ?
- (port->MSVR | MSVR_DTR) :
- (port->MSVR & ~MSVR_DTR);
- } else {
- port->MSVR = (arg & TIOCM_DTR) ?
- (port->MSVR | MSVR_DTR):
- (port->MSVR & ~MSVR_DTR);
- }
- break;
- default:
- return -EINVAL;
- }
save_flags(flags); cli();
+ /* if (set & TIOCM_RTS)
+ port->MSVR |= MSVR_RTS; */
+ /* if (set & TIOCM_DTR)
+ port->MSVR |= MSVR_DTR; */
+
+ if (SX_CRTSCTS(port->tty)) {
+ if (set & TIOCM_RTS)
+ port->MSVR |= MSVR_DTR;
+ } else {
+ if (set & TIOCM_DTR)
+ port->MSVR |= MSVR_DTR;
+ }
+
+ /* if (clear & TIOCM_RTS)
+ port->MSVR &= ~MSVR_RTS; */
+ /* if (clear & TIOCM_DTR)
+ port->MSVR &= ~MSVR_DTR; */
+ if (SX_CRTSCTS(port->tty)) {
+ if (clear & TIOCM_RTS)
+ port->MSVR &= ~MSVR_DTR;
+ } else {
+ if (clear & TIOCM_DTR)
+ port->MSVR &= ~MSVR_DTR;
+ }
+
sx_out(bp, CD186x_CAR, port_No(port));
sx_out(bp, CD186x_MSVR, port->MSVR);
restore_flags(flags);
@@ -1896,16 +1880,6 @@
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
return 0;
- case TIOCMGET:
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int));
- if (error)
- return error;
- return sx_get_modem_info(port, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return sx_set_modem_info(port, cmd, (unsigned int *) arg);
case TIOCGSERIAL:
return sx_get_serial_info(port, (struct serial_struct *) arg);
case TIOCSSERIAL:
@@ -2115,6 +2089,8 @@
.stop = sx_stop,
.start = sx_start,
.hangup = sx_hangup,
+ .tiocmget = sx_tiocmget,
+ .tiocmset = sx_tiocmset,
};

static int sx_init_drivers(void)
===== drivers/isdn/i4l/isdn_tty.c 1.55 vs edited =====
--- 1.55/drivers/isdn/i4l/isdn_tty.c Sun Sep 21 22:49:52 2003
+++ edited/drivers/isdn/i4l/isdn_tty.c Tue Jan 13 13:07:41 2004
@@ -1436,93 +1436,73 @@


static int
-isdn_tty_get_modem_info(modem_info * info, uint * value)
+isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
{
+ modem_info *info = (modem_info *) tty->driver_data;
u_char control,
status;
uint result;
ulong flags;

+ if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+#ifdef ISDN_DEBUG_MODEM_IOCTL
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
+#endif
+
control = info->mcr;
save_flags(flags);
cli();
status = info->msr;
restore_flags(flags);
- result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+ return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
| ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
| ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
| ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
| ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
- return put_user(result, (uint *) value);
}

static int
-isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
+isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ modem_info *info = (modem_info *) tty->driver_data;
uint arg;
int pre_dtr;

- if (get_user(arg, (uint *) value))
- return -EFAULT;
- switch (cmd) {
- case TIOCMBIS:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIS\n", info->line);
-#endif
- if (arg & TIOCM_RTS) {
- info->mcr |= UART_MCR_RTS;
- }
- if (arg & TIOCM_DTR) {
- info->mcr |= UART_MCR_DTR;
- isdn_tty_modem_ncarrier(info);
- }
- break;
- case TIOCMBIC:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIC\n", info->line);
-#endif
- if (arg & TIOCM_RTS) {
- info->mcr &= ~UART_MCR_RTS;
- }
- if (arg & TIOCM_DTR) {
- info->mcr &= ~UART_MCR_DTR;
- if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
- isdn_tty_modem_reset_regs(info, 0);
-#ifdef ISDN_DEBUG_MODEM_HUP
- printk(KERN_DEBUG "Mhup in TIOCMBIC\n");
-#endif
- if (info->online)
- info->ncarrier = 1;
- isdn_tty_modem_hup(info, 1);
- }
- }
- break;
- case TIOCMSET:
+ if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCMSET\n", info->line);
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
#endif
- pre_dtr = (info->mcr & UART_MCR_DTR);
- info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR))
- | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
- | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
- if (pre_dtr |= (info->mcr & UART_MCR_DTR)) {
- if (!(info->mcr & UART_MCR_DTR)) {
- if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
- isdn_tty_modem_reset_regs(info, 0);
+
+ if (set & TIOCM_RTS)
+ info->mcr |= UART_MCR_RTS;
+ if (set & TIOCM_DTR) {
+ info->mcr |= UART_MCR_DTR;
+ isdn_tty_modem_ncarrier(info);
+ }
+
+ if (clear & TIOCM_RTS)
+ info->mcr &= ~UART_MCR_RTS;
+ if (clear & TIOCM_DTR) {
+ info->mcr &= ~UART_MCR_DTR;
+ if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
+ isdn_tty_modem_reset_regs(info, 0);
#ifdef ISDN_DEBUG_MODEM_HUP
- printk(KERN_DEBUG "Mhup in TIOCMSET\n");
+ printk(KERN_DEBUG "Mhup in TIOCMBIC\n");
#endif
- if (info->online)
- info->ncarrier = 1;
- isdn_tty_modem_hup(info, 1);
- }
- } else
- isdn_tty_modem_ncarrier(info);
- }
- break;
- default:
- return -EINVAL;
+ if (info->online)
+ info->ncarrier = 1;
+ isdn_tty_modem_hup(info, 1);
+ }
}
return 0;
}
@@ -1572,15 +1552,6 @@
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
return 0;
- case TIOCMGET:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
-#endif
- return isdn_tty_get_modem_info(info, (uint *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
case TIOCSERGETLSR: /* Get line status register */
#ifdef ISDN_DEBUG_MODEM_IOCTL
printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
@@ -2006,6 +1977,8 @@
.unthrottle = isdn_tty_unthrottle,
.set_termios = isdn_tty_set_termios,
.hangup = isdn_tty_hangup,
+ .tiocmget = isdn_tty_tiocmget,
+ .tiocmset = isdn_tty_tiocmset,
};

int
===== drivers/net/wan/pc300_tty.c 1.14 vs edited =====
--- 1.14/drivers/net/wan/pc300_tty.c Thu Sep 11 18:40:53 2003
+++ edited/drivers/net/wan/pc300_tty.c Tue Jan 13 14:42:34 2004
@@ -583,6 +583,14 @@
CPC_TTY_DBG("%s: IOCTL cmd %x\n",cpc_tty->name,cmd);

switch (cmd) {
+#error This is broken. See comments.
+/*
+ * TIOCMBIS/TIOCMBIC do not control only the DTR signal, but also
+ * the RTS, OUT1 and OUT2 signals, or even maybe nothing at all.
+ * Plus, these IOCTLs are no longer passed down to the driver.
+ * Instead, drivers should implement tiocmget and tiocmset driver
+ * methods.
+ */
case TIOCMBIS : /* set DTR */
cpc_tty_dtr_on(cpc_tty->pc300dev);
break;
===== drivers/sbus/char/aurora.c 1.30 vs edited =====
--- 1.30/drivers/sbus/char/aurora.c Wed Jun 11 20:32:35 2003
+++ edited/drivers/sbus/char/aurora.c Tue Jan 13 14:47:09 2004
@@ -1752,8 +1752,9 @@
#endif
}

-static int aurora_get_modem_info(struct Aurora_port * port, unsigned int *value)
+static int aurora_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
struct Aurora_board * bp;
unsigned char status,chip;
unsigned int result;
@@ -1762,6 +1763,9 @@
#ifdef AURORA_DEBUG
printk("aurora_get_modem_info: start\n");
#endif
+ if ((aurora_paranoia_check(port, tty->name, __FUNCTION__))
+ return -ENODEV;
+
chip = AURORA_CD180(port_No(port));

bp = port_Board(port);
@@ -1782,16 +1786,16 @@
| ((status & MSVR_DSR) ? TIOCM_DSR : 0)
| ((status & MSVR_CTS) ? TIOCM_CTS : 0);

- put_user(result,(unsigned long *) value);
#ifdef AURORA_DEBUG
printk("aurora_get_modem_info: end\n");
#endif
- return 0;
+ return result;
}

-static int aurora_set_modem_info(struct Aurora_port * port, unsigned int cmd,
- unsigned int *value)
+static int aurora_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
unsigned int arg;
unsigned long flags;
struct Aurora_board *bp = port_Board(port);
@@ -1800,33 +1804,20 @@
#ifdef AURORA_DEBUG
printk("aurora_set_modem_info: start\n");
#endif
- if (get_user(arg, value))
- return -EFAULT;
+ if ((aurora_paranoia_check(port, tty->name, __FUNCTION__))
+ return -ENODEV;
+
chip = AURORA_CD180(port_No(port));
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- port->MSVR |= bp->RTS;
- if (arg & TIOCM_DTR)
- port->MSVR |= bp->DTR;
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- port->MSVR &= ~bp->RTS;
- if (arg & TIOCM_DTR)
- port->MSVR &= ~bp->DTR;
- break;
- case TIOCMSET:
- port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | bp->RTS) :
- (port->MSVR & ~bp->RTS);
- port->MSVR = (arg & TIOCM_DTR) ? (port->MSVR | bp->RTS) :
- (port->MSVR & ~bp->RTS);
- break;
- default:
- return -EINVAL;
- };

save_flags(flags); cli();
+ if (set & TIOCM_RTS)
+ port->MSVR |= bp->RTS;
+ if (set & TIOCM_DTR)
+ port->MSVR |= bp->DTR;
+ if (clear & TIOCM_RTS)
+ port->MSVR &= ~bp->RTS;
+ if (clear & TIOCM_DTR)
+ port->MSVR &= ~bp->DTR;

sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]);
udelay(1);
@@ -1993,16 +1984,6 @@
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
return 0;
- case TIOCMGET:
- retval = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int));
- if (retval)
- return retval;
- return aurora_get_modem_info(port, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return aurora_set_modem_info(port, cmd, (unsigned int *) arg);
case TIOCGSERIAL:
return aurora_get_serial_info(port, (struct serial_struct *) arg);
case TIOCSSERIAL:
@@ -2268,6 +2249,8 @@
.stop = aurora_stop,
.start = aurora_start,
.hangup = aurora_hangup,
+ .tiocmget = aurora_tiocmget,
+ .tiocmset = aurora_tiocmset,
};

static int aurora_init_drivers(void)
===== drivers/serial/68360serial.c 1.17 vs edited =====
--- 1.17/drivers/serial/68360serial.c Wed Jun 11 20:32:34 2003
+++ edited/drivers/serial/68360serial.c Tue Jan 13 13:06:44 2004
@@ -1282,12 +1282,19 @@
}
#endif

-static int get_modem_info(ser_info_t *info, unsigned int *value)
+static int rs_360_tiocmget(struct tty_struct *tty, struct file *file)
{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
unsigned int result = 0;
#ifdef modem_control
unsigned char control, status;

+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
control = info->MCR;
local_irq_disable();
status = serial_in(info, UART_MSR);
@@ -1303,63 +1310,42 @@
| ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
| ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
#endif
- /* return put_user(result,value); */
- put_user(result,value);
- return (0);
+ return result;
}

-static int set_modem_info(ser_info_t *info, unsigned int cmd,
- unsigned int *value)
+static int rs_360_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
- int error;
- unsigned int arg;
-
- error = get_user(arg,value);
- if (error)
- return error;
#ifdef modem_control
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- info->MCR |= UART_MCR_RTS;
- if (arg & TIOCM_DTR)
- info->MCR |= UART_MCR_DTR;
-#ifdef TIOCM_OUT1
- if (arg & TIOCM_OUT1)
- info->MCR |= UART_MCR_OUT1;
- if (arg & TIOCM_OUT2)
- info->MCR |= UART_MCR_OUT2;
-#endif
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- info->MCR &= ~UART_MCR_RTS;
- if (arg & TIOCM_DTR)
- info->MCR &= ~UART_MCR_DTR;
-#ifdef TIOCM_OUT1
- if (arg & TIOCM_OUT1)
- info->MCR &= ~UART_MCR_OUT1;
- if (arg & TIOCM_OUT2)
- info->MCR &= ~UART_MCR_OUT2;
-#endif
- break;
- case TIOCMSET:
- info->MCR = ((info->MCR & ~(UART_MCR_RTS |
-#ifdef TIOCM_OUT1
- UART_MCR_OUT1 |
- UART_MCR_OUT2 |
-#endif
- UART_MCR_DTR))
- | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ unsigned int arg;
+
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+ if (set & TIOCM_RTS)
+ info->mcr |= UART_MCR_RTS;
+ if (set & TIOCM_DTR)
+ info->mcr |= UART_MCR_DTR;
+ if (clear & TIOCM_RTS)
+ info->MCR &= ~UART_MCR_RTS;
+ if (clear & TIOCM_DTR)
+ info->MCR &= ~UART_MCR_DTR;
+
#ifdef TIOCM_OUT1
- | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
- | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
+ if (set & TIOCM_OUT1)
+ info->MCR |= UART_MCR_OUT1;
+ if (set & TIOCM_OUT2)
+ info->MCR |= UART_MCR_OUT2;
+ if (clear & TIOCM_OUT1)
+ info->MCR &= ~UART_MCR_OUT1;
+ if (clear & TIOCM_OUT2)
+ info->MCR &= ~UART_MCR_OUT2;
#endif
- | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
- break;
- default:
- return -EINVAL;
- }
+
local_irq_disable();
serial_out(info, UART_MCR, info->MCR);
local_irq_enable();
@@ -1506,12 +1492,6 @@
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
return 0;
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
#ifdef maybe
case TIOCSERGETLSR: /* Get line status register */
return get_lsr_info(info, (unsigned int *) arg);
@@ -2513,6 +2493,8 @@
.hangup = rs_360_hangup,
/* .wait_until_sent = rs_360_wait_until_sent, */
/* .read_proc = rs_360_read_proc, */
+ .tiocmget = rs_360_tiocmget,
+ .tiocmset = rs_360_tiocmset,
};

/* int __init rs_360_init(void) */
===== drivers/tc/zs.c 1.24 vs edited =====
--- 1.24/drivers/tc/zs.c Fri Sep 26 00:38:44 2003
+++ edited/drivers/tc/zs.c Tue Jan 13 14:25:30 2004
@@ -1176,11 +1176,21 @@
return 0;
}

-static int get_modem_info(struct dec_serial *info, unsigned int *value)
+static int rs_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct dec_serial * info = (struct dec_serial *)tty->driver_data;
unsigned char control, status_a, status_b;
unsigned int result;

+ if (info->hook)
+ return -ENODEV;
+
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
if (info->zs_channel == info->zs_chan_a)
result = 0;
else {
@@ -1196,41 +1206,37 @@
| ((status_a & SYNC_HUNT) ? TIOCM_DSR: 0)
| ((status_b & CTS) ? TIOCM_CTS: 0);
}
- put_user(result, value);
- return 0;
+ return result;
}

-static int set_modem_info(struct dec_serial *info, unsigned int cmd,
- unsigned int *value)
+static int rs_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct dec_serial * info = (struct dec_serial *)tty->driver_data;
int error;
unsigned int arg, bits;

- error = verify_area(VERIFY_READ, value, sizeof(int));
- if (error)
- return error;
+ if (info->hook)
+ return -ENODEV;
+
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;

if (info->zs_channel == info->zs_chan_a)
return 0;

- get_user(arg, value);
- bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0);
cli();
- switch (cmd) {
- case TIOCMBIS:
- info->zs_chan_a->curregs[5] |= bits;
- break;
- case TIOCMBIC:
- info->zs_chan_a->curregs[5] &= ~bits;
- break;
- case TIOCMSET:
- info->zs_chan_a->curregs[5] =
- (info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits;
- break;
- default:
- sti();
- return -EINVAL;
- }
+ if (set & TIOCM_RTS)
+ info->zs_chan_a->curregs[5] |= RTS;
+ if (set & TIOCM_DTR)
+ info->zs_chan_a->curregs[5] |= DTR;
+ if (clear & TIOCM_RTS)
+ info->zs_chan_a->curregs[5] &= ~RTS;
+ if (clear & TIOCM_DTR)
+ info->zs_chan_a->curregs[5] &= ~DTR;
write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
sti();
return 0;
@@ -1278,16 +1284,6 @@
}

switch (cmd) {
- case TIOCMGET:
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int));
- if (error)
- return error;
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
case TIOCGSERIAL:
error = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(struct serial_struct));
@@ -1816,6 +1812,8 @@
.hangup = rs_hangup,
.break_ctl = rs_break,
.wait_until_sent = rs_wait_until_sent,
+ .tiocmget = rs_tiocmget,
+ .tiocmset = rs_tiocmset,
};

/* zs_init inits the driver */


--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-13 18:10:41

by Jean Tourrilhes

[permalink] [raw]
Subject: Re: Re: [PROBLEM] ircomm ioctls

Russell King wrote :
>
> On Tue, Jan 13, 2004 at 12:00:15PM +0100, Jozef Vesely wrote:
> > I am gettig this error (while connecting to my mobile phone):
> > ------
> > # gsmctl -d /dev/ircomm0 ALL
> > gsmctl[ERROR]: clearing DTR failed (errno: 22/Invalid argument)
> > ------
>
> ircomm needs updating to use the tiocmset/tiocmget driver calls. Could
> you see if the following patch solves your problem please?

Good catch. Is there any other API changes worth looking into ?

By the way, I would rather keep the function
ircomm_tty_tiocmget() and ircomm_tty_tiocmset() in ircomm_tty_ioctl.c,
because ircomm_tty.c is already big and messy.
Check the patch below (quickly tested).

Thanks !

Jean

---------------------------------------------------------------------

diff -u -p linux/include/net/irda/ircomm_tty.d5.h linux/include/net/irda/ircomm_tty.h
--- linux/include/net/irda/ircomm_tty.d5.h Tue Jan 13 09:51:52 2004
+++ linux/include/net/irda/ircomm_tty.h Tue Jan 13 10:01:11 2004
@@ -122,6 +122,9 @@ void ircomm_tty_stop(struct tty_struct *
void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self);

extern void ircomm_tty_change_speed(struct ircomm_tty_cb *self);
+extern int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file);
+extern int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
extern void ircomm_tty_set_termios(struct tty_struct *tty,
diff -u -p linux/net/irda/ircomm/ircomm_tty.d5.c linux/net/irda/ircomm/ircomm_tty.c
--- linux/net/irda/ircomm/ircomm_tty.d5.c Tue Jan 13 09:55:04 2004
+++ linux/net/irda/ircomm/ircomm_tty.c Tue Jan 13 10:02:52 2004
@@ -86,7 +86,9 @@ static struct tty_operations ops = {
.write_room = ircomm_tty_write_room,
.chars_in_buffer = ircomm_tty_chars_in_buffer,
.flush_buffer = ircomm_tty_flush_buffer,
- .ioctl = ircomm_tty_ioctl,
+ .ioctl = ircomm_tty_ioctl, /* ircomm_tty_ioctl.c */
+ .tiocmget = ircomm_tty_tiocmget, /* ircomm_tty_ioctl.c */
+ .tiocmset = ircomm_tty_tiocmset, /* ircomm_tty_ioctl.c */
.throttle = ircomm_tty_throttle,
.unthrottle = ircomm_tty_unthrottle,
.send_xchar = ircomm_tty_send_xchar,
diff -u -p linux/net/irda/ircomm/ircomm_tty_ioctl.d5.c linux/net/irda/ircomm/ircomm_tty_ioctl.c
--- linux/net/irda/ircomm/ircomm_tty_ioctl.d5.c Tue Jan 13 09:54:53 2004
+++ linux/net/irda/ircomm/ircomm_tty_ioctl.c Tue Jan 13 10:00:52 2004
@@ -190,14 +190,14 @@ void ircomm_tty_set_termios(struct tty_s
}

/*
- * Function ircomm_tty_get_modem_info (self, value)
+ * Function ircomm_tty_tiocmget (tty, file)
*
*
*
*/
-static int ircomm_tty_get_modem_info(struct ircomm_tty_cb *self,
- unsigned int *value)
+int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
unsigned int result;

IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
@@ -209,62 +209,38 @@ static int ircomm_tty_get_modem_info(str
| ((self->settings.dce & IRCOMM_DSR) ? TIOCM_DSR : 0)
| ((self->settings.dce & IRCOMM_CTS) ? TIOCM_CTS : 0);

- return put_user(result, value);
+ return result;
}

/*
- * Function set_modem_info (driver, cmd, value)
+ * Function ircomm_tty_tiocmset (tty, file, set, clear)
*
*
*
*/
-static int ircomm_tty_set_modem_info(struct ircomm_tty_cb *self,
- unsigned int cmd, unsigned int *value)
+int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
- unsigned int arg;
- __u8 old_rts, old_dtr;
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;

IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );

ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);

- if (get_user(arg, value))
- return -EFAULT;
-
- old_rts = self->settings.dte & IRCOMM_RTS;
- old_dtr = self->settings.dte & IRCOMM_DTR;
+ if (set & TIOCM_RTS)
+ self->settings.dte |= IRCOMM_RTS;
+ if (set & TIOCM_DTR)
+ self->settings.dte |= IRCOMM_DTR;
+
+ if (clear & TIOCM_RTS)
+ self->settings.dte &= ~IRCOMM_RTS;
+ if (clear & TIOCM_DTR)
+ self->settings.dte &= ~IRCOMM_DTR;

- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- self->settings.dte |= IRCOMM_RTS;
- if (arg & TIOCM_DTR)
- self->settings.dte |= IRCOMM_DTR;
- break;
-
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- self->settings.dte &= ~IRCOMM_RTS;
- if (arg & TIOCM_DTR)
- self->settings.dte &= ~IRCOMM_DTR;
- break;
-
- case TIOCMSET:
- self->settings.dte =
- ((self->settings.dte & ~(IRCOMM_RTS | IRCOMM_DTR))
- | ((arg & TIOCM_RTS) ? IRCOMM_RTS : 0)
- | ((arg & TIOCM_DTR) ? IRCOMM_DTR : 0));
- break;
-
- default:
- return -EINVAL;
- }
-
- if ((self->settings.dte & IRCOMM_RTS) != old_rts)
+ if ((set|clear) & TIOCM_RTS)
self->settings.dte |= IRCOMM_DELTA_RTS;
-
- if ((self->settings.dte & IRCOMM_DTR) != old_dtr)
+ if ((set|clear) & TIOCM_DTR)
self->settings.dte |= IRCOMM_DELTA_DTR;

ircomm_param_request(self, IRCOMM_DTE, TRUE);
@@ -406,14 +382,6 @@ int ircomm_tty_ioctl(struct tty_struct *
}

switch (cmd) {
- case TIOCMGET:
- ret = ircomm_tty_get_modem_info(self, (unsigned int *) arg);
- break;
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- ret = ircomm_tty_set_modem_info(self, cmd, (unsigned int *) arg);
- break;
case TIOCGSERIAL:
ret = ircomm_tty_get_serial_info(self, (struct serial_struct *) arg);
break;

2004-01-13 18:36:21

by Henrique Oliveira

[permalink] [raw]
Subject: Re: [2/3]

Hi,

I am no longer the maintainer of the Cyclades driver (char/cyclades.c).
Could you please remove my name from that driver and include Daniela as
the official maintainer <[email protected]> ?

Thanks a lot
Henrique

Russell King wrote:

> Here are patches to drivers in the 2.6 kernel which have not been tested
> to correct the tiocmset/tiocmget problem.
>
> You can find the full thread at the following URL:
>
> http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=1dvnl-5Pr-1%40gated-at.bofh.it&rnum=1&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DISO-8859-1%26q%3DOutstanding%2Bfixups%26btnG%3DGoogle%2BSearch%26meta%3Dgroup%253Dlinux.kernel
>
> ===== drivers/char/cyclades.c 1.32 vs edited =====
> --- 1.32/drivers/char/cyclades.c Tue Sep 30 01:34:28 2003
> +++ edited/drivers/char/cyclades.c Tue Jan 13 14:01:24 2004
> @@ -3632,8 +3632,9 @@
> }
>
> static int
> -get_modem_info(struct cyclades_port * info, unsigned int *value)
> +cy_tiocmget(struct tty_struct *tty, struct file *file)
> {
> + struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
> int card,chip,channel,index;
> unsigned char *base_addr;
> unsigned long flags;
> @@ -3645,6 +3646,9 @@
> struct BOARD_CTRL *board_ctrl;
> struct CH_CTRL *ch_ctrl;
>
> + if (serial_paranoia_check(info, tty->name, __FUNCTION__))
> + return -ENODEV;
> +
> card = info->card;
> channel = (info->line) - (cy_card[card].first_line);
> if (!IS_CYC_Z(cy_card[card])) {
> @@ -3700,14 +3704,15 @@
> }
>
> }
> - return cy_put_user(result, value);
> -} /* get_modem_info */
> + return result;
> +} /* cy_tiomget */
>
>
> static int
> -set_modem_info(struct cyclades_port * info, unsigned int cmd,
> - unsigned int *value)
> +cy_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear)
> {
> + struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
> int card,chip,channel,index;
> unsigned char *base_addr;
> unsigned long flags;
> @@ -3718,6 +3723,9 @@
> struct CH_CTRL *ch_ctrl;
> int retval;
>
> + if (serial_paranoia_check(info, tty->name, __FUNCTION__))
> + return -ENODEV;
> +
> card = info->card;
> channel = (info->line) - (cy_card[card].first_line);
> if (!IS_CYC_Z(cy_card[card])) {
> @@ -3728,66 +3736,7 @@
> (cy_card[card].base_addr
> + (cy_chip_offset[chip]<<index));
>
> - switch (cmd) {
> - case TIOCMBIS:
> - if (arg & TIOCM_RTS){
> - CY_LOCK(info, flags);
> - cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
> - if (info->rtsdtr_inv) {
> - cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
> - } else {
> - cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
> - }
> - CY_UNLOCK(info, flags);
> - }
> - if (arg & TIOCM_DTR){
> - CY_LOCK(info, flags);
> - cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
> - if (info->rtsdtr_inv) {
> - cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
> - } else {
> - cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
> - }
> -#ifdef CY_DEBUG_DTR
> - printk("cyc:set_modem_info raising DTR\n");
> - printk(" status: 0x%x, 0x%x\n",
> - cy_readb(base_addr+(CyMSVR1<<index)),
> - cy_readb(base_addr+(CyMSVR2<<index)));
> -#endif
> - CY_UNLOCK(info, flags);
> - }
> - break;
> - case TIOCMBIC:
> - if (arg & TIOCM_RTS){
> - CY_LOCK(info, flags);
> - cy_writeb((u_long)base_addr+(CyCAR<<index),
> - (u_char)channel);
> - if (info->rtsdtr_inv) {
> - cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
> - } else {
> - cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
> - }
> - CY_UNLOCK(info, flags);
> - }
> - if (arg & TIOCM_DTR){
> - CY_LOCK(info, flags);
> - cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
> - if (info->rtsdtr_inv) {
> - cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
> - } else {
> - cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
> - }
> -#ifdef CY_DEBUG_DTR
> - printk("cyc:set_modem_info dropping DTR\n");
> - printk(" status: 0x%x, 0x%x\n",
> - cy_readb(base_addr+(CyMSVR1<<index)),
> - cy_readb(base_addr+(CyMSVR2<<index)));
> -#endif
> - CY_UNLOCK(info, flags);
> - }
> - break;
> - case TIOCMSET:
> - if (arg & TIOCM_RTS){
> + if (set & TIOCM_RTS){
> CY_LOCK(info, flags);
> cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
> if (info->rtsdtr_inv) {
> @@ -3796,7 +3745,8 @@
> cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
> }
> CY_UNLOCK(info, flags);
> - }else{
> + }
> + if (clear & TIOCM_RTS) {
> CY_LOCK(info, flags);
> cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
> if (info->rtsdtr_inv) {
> @@ -3805,8 +3755,8 @@
> cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
> }
> CY_UNLOCK(info, flags);
> - }
> - if (arg & TIOCM_DTR){
> + }
> + if (set & TIOCM_DTR){
> CY_LOCK(info, flags);
> cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
> if (info->rtsdtr_inv) {
> @@ -3821,7 +3771,8 @@
> cy_readb(base_addr+(CyMSVR2<<index)));
> #endif
> CY_UNLOCK(info, flags);
> - }else{
> + }
> + if (clear & TIOCM_DTR) {
> CY_LOCK(info, flags);
> cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
> if (info->rtsdtr_inv) {
> @@ -3837,10 +3788,6 @@
> cy_readb(base_addr+(CyMSVR2<<index)));
> #endif
> CY_UNLOCK(info, flags);
> - }
> - break;
> - default:
> - return -EINVAL;
> }
> } else {
> base_addr = (unsigned char*) (cy_card[card].base_addr);
> @@ -3854,54 +3801,19 @@
> board_ctrl = &zfw_ctrl->board_ctrl;
> ch_ctrl = zfw_ctrl->ch_ctrl;
>
> - switch (cmd) {
> - case TIOCMBIS:
> - if (arg & TIOCM_RTS){
> - CY_LOCK(info, flags);
> - cy_writel(&ch_ctrl[channel].rs_control,
> - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS);
> - CY_UNLOCK(info, flags);
> - }
> - if (arg & TIOCM_DTR){
> - CY_LOCK(info, flags);
> - cy_writel(&ch_ctrl[channel].rs_control,
> - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
> -#ifdef CY_DEBUG_DTR
> - printk("cyc:set_modem_info raising Z DTR\n");
> -#endif
> - CY_UNLOCK(info, flags);
> - }
> - break;
> - case TIOCMBIC:
> - if (arg & TIOCM_RTS){
> - CY_LOCK(info, flags);
> - cy_writel(&ch_ctrl[channel].rs_control,
> - cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS);
> - CY_UNLOCK(info, flags);
> - }
> - if (arg & TIOCM_DTR){
> - CY_LOCK(info, flags);
> - cy_writel(&ch_ctrl[channel].rs_control,
> - cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
> -#ifdef CY_DEBUG_DTR
> - printk("cyc:set_modem_info clearing Z DTR\n");
> -#endif
> - CY_UNLOCK(info, flags);
> - }
> - break;
> - case TIOCMSET:
> - if (arg & TIOCM_RTS){
> + if (set & TIOCM_RTS){
> CY_LOCK(info, flags);
> cy_writel(&ch_ctrl[channel].rs_control,
> cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS);
> CY_UNLOCK(info, flags);
> - }else{
> + }
> + if (clear & TIOCM_RTS) {
> CY_LOCK(info, flags);
> cy_writel(&ch_ctrl[channel].rs_control,
> cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS);
> CY_UNLOCK(info, flags);
> - }
> - if (arg & TIOCM_DTR){
> + }
> + if (set & TIOCM_DTR){
> CY_LOCK(info, flags);
> cy_writel(&ch_ctrl[channel].rs_control,
> cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
> @@ -3909,7 +3821,8 @@
> printk("cyc:set_modem_info raising Z DTR\n");
> #endif
> CY_UNLOCK(info, flags);
> - }else{
> + }
> + if (clear & TIOCM_DTR) {
> CY_LOCK(info, flags);
> cy_writel(&ch_ctrl[channel].rs_control,
> cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
> @@ -3917,10 +3830,6 @@
> printk("cyc:set_modem_info clearing Z DTR\n");
> #endif
> CY_UNLOCK(info, flags);
> - }
> - break;
> - default:
> - return -EINVAL;
> }
> }else{
> return -ENODEV;
> @@ -3935,7 +3844,7 @@
> CY_UNLOCK(info, flags);
> }
> return 0;
> -} /* set_modem_info */
> +} /* cy_tiocmset */
>
> /*
> * cy_break() --- routine which turns the break handling on or off
> @@ -4242,14 +4151,6 @@
> case CYGETWAIT:
> ret_val = info->closing_wait / (HZ/100);
> break;
> - case TIOCMGET:
> - ret_val = get_modem_info(info, (unsigned int *) arg);
> - break;
> - case TIOCMBIS:
> - case TIOCMBIC:
> - case TIOCMSET:
> - ret_val = set_modem_info(info, cmd, (unsigned int *) arg);
> - break;
> case TIOCGSERIAL:
> ret_val = get_serial_info(info, (struct serial_struct *) arg);
> break;
> @@ -5429,6 +5330,8 @@
> .break_ctl = cy_break,
> .wait_until_sent = cy_wait_until_sent,
> .read_proc = cyclades_get_proc_info,
> + .tiocmget = cy_tiocmget,
> + .tiocmset = cy_tiocmset,
> };
>
> static int __init
> ===== drivers/char/ip2main.c 1.42 vs edited =====
> --- 1.42/drivers/char/ip2main.c Tue Sep 30 01:23:52 2003
> +++ edited/drivers/char/ip2main.c Tue Jan 13 16:06:56 2004
> @@ -186,6 +186,9 @@
> static void ip2_stop(PTTY);
> static void ip2_start(PTTY);
> static void ip2_hangup(PTTY);
> +static int ip2_tiocmget(struct tty_struct *tty, struct file *file);
> +static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear);
>
> static void set_irq(int, int);
> static void ip2_interrupt_bh(i2eBordStrPtr pB);
> @@ -466,6 +469,8 @@
> .start = ip2_start,
> .hangup = ip2_hangup,
> .read_proc = ip2_read_proc,
> + .tiocmget = ip2_tiocmget,
> + .tiocmset = ip2_tiocmset,
> };
>
> /******************************************************************************/
> @@ -1951,6 +1956,80 @@
> /* Device Ioctl Section */
> /******************************************************************************/
>
> +static int ip2_tiocmget(struct tty_struct *tty, struct file *file)
> +{
> + i2ChanStrPtr pCh = DevTable[tty->index];
> + wait_queue_t wait;
> +
> + if (pCh == NULL)
> + return -ENODEV;
> +
> +/*
> + FIXME - the following code is causing a NULL pointer dereference in
> + 2.3.51 in an interrupt handler. It's suppose to prompt the board
> + to return the DSS signal status immediately. Why doesn't it do
> + the same thing in 2.2.14?
> +*/
> +
> +/* This thing is still busted in the 1.2.12 driver on 2.4.x
> + and even hoses the serial console so the oops can be trapped.
> + /\/\|=mhw=|\/\/ */
> +
> +#ifdef ENABLE_DSSNOW
> + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
> +
> + init_waitqueue_entry(&wait, current);
> + add_wait_queue(&pCh->dss_now_wait, &wait);
> + set_current_state( TASK_INTERRUPTIBLE );
> +
> + serviceOutgoingFifo( pCh->pMyBord );
> +
> + schedule();
> +
> + set_current_state( TASK_RUNNING );
> + remove_wait_queue(&pCh->dss_now_wait, &wait);
> +
> + if (signal_pending(current)) {
> + return -EINTR;
> + }
> +#endif
> + return ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
> + | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
> + | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0)
> + | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0)
> + | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0)
> + | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0);
> +}
> +
> +static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear)
> +{
> + i2ChanStrPtr pCh = DevTable[tty->index];
> +
> + if (pCh == NULL)
> + return -ENODEV;
> +
> + if (set & TIOCM_RTS) {
> + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
> + pCh->dataSetOut |= I2_RTS;
> + }
> + if (set & TIOCM_DTR) {
> + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
> + pCh->dataSetOut |= I2_DTR;
> + }
> +
> + if (clear & TIOCM_RTS) {
> + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
> + pCh->dataSetOut &= ~I2_RTS;
> + }
> + if (clear & TIOCM_DTR) {
> + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
> + pCh->dataSetOut &= ~I2_DTR;
> + }
> + serviceOutgoingFifo( pCh->pMyBord );
> + return 0;
> +}
> +
> /******************************************************************************/
> /* Function: ip2_ioctl() */
> /* Parameters: Pointer to tty structure */
> @@ -2078,57 +2157,6 @@
>
> break;
>
> - case TIOCMGET:
> -
> - ip2trace (CHANN, ITRC_IOCTL, 8, 1, rc );
> -
> -/*
> - FIXME - the following code is causing a NULL pointer dereference in
> - 2.3.51 in an interrupt handler. It's suppose to prompt the board
> - to return the DSS signal status immediately. Why doesn't it do
> - the same thing in 2.2.14?
> -*/
> -
> -/* This thing is still busted in the 1.2.12 driver on 2.4.x
> - and even hoses the serial console so the oops can be trapped.
> - /\/\|=mhw=|\/\/ */
> -
> -#ifdef ENABLE_DSSNOW
> - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
> -
> - init_waitqueue_entry(&wait, current);
> - add_wait_queue(&pCh->dss_now_wait, &wait);
> - set_current_state( TASK_INTERRUPTIBLE );
> -
> - serviceOutgoingFifo( pCh->pMyBord );
> -
> - schedule();
> -
> - set_current_state( TASK_RUNNING );
> - remove_wait_queue(&pCh->dss_now_wait, &wait);
> -
> - if (signal_pending(current)) {
> - return -EINTR;
> - }
> -#endif
> - rc = put_user(
> - ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
> - | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
> - | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0)
> - | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0)
> - | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0)
> - | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0),
> - (unsigned int *) arg);
> - break;
> -
> - case TIOCMBIS:
> - case TIOCMBIC:
> - case TIOCMSET:
> - ip2trace (CHANN, ITRC_IOCTL, 9, 0 );
> -
> - rc = set_modem_info(pCh, cmd, (unsigned int *) arg);
> - break;
> -
> /*
> * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
> * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
> @@ -2239,70 +2267,6 @@
> }
>
> /******************************************************************************/
> -/* Function: set_modem_info() */
> -/* Parameters: Pointer to channel structure */
> -/* Specific ioctl command */
> -/* Pointer to source for new settings */
> -/* Returns: Nothing */
> -/* */
> -/* Description: */
> -/* This returns the current settings of the dataset signal inputs to the user */
> -/* program. */
> -/******************************************************************************/
> -static int
> -set_modem_info(i2ChanStrPtr pCh, unsigned cmd, unsigned int *value)
> -{
> - int rc;
> - unsigned int arg;
> -
> - rc = get_user(arg,value);
> - if (rc)
> - return rc;
> - switch(cmd) {
> - case TIOCMBIS:
> - if (arg & TIOCM_RTS) {
> - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
> - pCh->dataSetOut |= I2_RTS;
> - }
> - if (arg & TIOCM_DTR) {
> - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
> - pCh->dataSetOut |= I2_DTR;
> - }
> - break;
> - case TIOCMBIC:
> - if (arg & TIOCM_RTS) {
> - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
> - pCh->dataSetOut &= ~I2_RTS;
> - }
> - if (arg & TIOCM_DTR) {
> - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
> - pCh->dataSetOut &= ~I2_DTR;
> - }
> - break;
> - case TIOCMSET:
> - if ( (arg & TIOCM_RTS) && !(pCh->dataSetOut & I2_RTS) ) {
> - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
> - pCh->dataSetOut |= I2_RTS;
> - } else if ( !(arg & TIOCM_RTS) && (pCh->dataSetOut & I2_RTS) ) {
> - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
> - pCh->dataSetOut &= ~I2_RTS;
> - }
> - if ( (arg & TIOCM_DTR) && !(pCh->dataSetOut & I2_DTR) ) {
> - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
> - pCh->dataSetOut |= I2_DTR;
> - } else if ( !(arg & TIOCM_DTR) && (pCh->dataSetOut & I2_DTR) ) {
> - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
> - pCh->dataSetOut &= ~I2_DTR;
> - }
> - break;
> - default:
> - return -EINVAL;
> - }
> - serviceOutgoingFifo( pCh->pMyBord );
> - return 0;
> -}
> -
> -/******************************************************************************/
> /* Function: GetSerialInfo() */
> /* Parameters: Pointer to channel structure */
> /* Pointer to old termios structure */
> @@ -2964,7 +2928,7 @@
> rc = put_user(ip2_throttle, pIndex++ );
> rc = put_user(ip2_unthrottle, pIndex++ );
> rc = put_user(ip2_ioctl, pIndex++ );
> - rc = put_user(set_modem_info, pIndex++ );
> + rc = put_user(0, pIndex++ );
> rc = put_user(get_serial_info, pIndex++ );
> rc = put_user(set_serial_info, pIndex++ );
> rc = put_user(ip2_set_termios, pIndex++ );
> ===== drivers/char/istallion.c 1.34 vs edited =====
> --- 1.34/drivers/char/istallion.c Tue Sep 30 01:34:28 2003
> +++ edited/drivers/char/istallion.c Tue Jan 13 16:12:50 2004
> @@ -1990,6 +1990,61 @@
>
> /*****************************************************************************/
>
> +static int stli_tiocmget(struct tty_struct *tty, struct file *file)
> +{
> + stliport_t *portp = tty->driver_data;
> + stlibrd_t *brdp;
> + int rc;
> +
> + if (portp == (stliport_t *) NULL)
> + return(-ENODEV);
> + if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
> + return(0);
> + brdp = stli_brds[portp->brdnr];
> + if (brdp == (stlibrd_t *) NULL)
> + return(0);
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return(-EIO);
> +
> + if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
> + &portp->asig, sizeof(asysigs_t), 1)) < 0)
> + return(rc);
> +
> + return stli_mktiocm(portp->asig.sigvalue);
> +}
> +
> +static int stli_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear)
> +{
> + stliport_t *portp = tty->driver_data;
> + stlibrd_t *brdp;
> + int rts = -1, dtr = -1;
> +
> + if (portp == (stliport_t *) NULL)
> + return(-ENODEV);
> + if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
> + return(0);
> + brdp = stli_brds[portp->brdnr];
> + if (brdp == (stlibrd_t *) NULL)
> + return(0);
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return(-EIO);
> +
> + if (set & TIOCM_RTS)
> + rts = 1;
> + if (set & TIOCM_DTR)
> + dtr = 1;
> + if (clear & TIOCM_RTS)
> + rts = 0;
> + if (clear & TIOCM_DTR)
> + dtr = 0;
> +
> + stli_mkasysigs(&portp->asig, dtr, rts);
> +
> + return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
> + sizeof(asysigs_t), 0);
> +}
> +
> static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
> {
> stliport_t *portp;
> @@ -2033,43 +2088,6 @@
> (tty->termios->c_cflag & ~CLOCAL) |
> (ival ? CLOCAL : 0);
> break;
> - case TIOCMGET:
> - if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))) == 0) {
> - if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
> - &portp->asig, sizeof(asysigs_t), 1)) < 0)
> - return(rc);
> - lval = stli_mktiocm(portp->asig.sigvalue);
> - put_user(lval, (unsigned int *) arg);
> - }
> - break;
> - case TIOCMBIS:
> - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
> - stli_mkasysigs(&portp->asig,
> - ((ival & TIOCM_DTR) ? 1 : -1),
> - ((ival & TIOCM_RTS) ? 1 : -1));
> - rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
> - &portp->asig, sizeof(asysigs_t), 0);
> - }
> - break;
> - case TIOCMBIC:
> - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
> - stli_mkasysigs(&portp->asig,
> - ((ival & TIOCM_DTR) ? 0 : -1),
> - ((ival & TIOCM_RTS) ? 0 : -1));
> - rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
> - &portp->asig, sizeof(asysigs_t), 0);
> - }
> - break;
> - case TIOCMSET:
> - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
> - stli_mkasysigs(&portp->asig,
> - ((ival & TIOCM_DTR) ? 1 : 0),
> - ((ival & TIOCM_RTS) ? 1 : 0));
> - rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
> - &portp->asig, sizeof(asysigs_t), 0);
> - }
> - break;
> case TIOCGSERIAL:
> if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
> sizeof(struct serial_struct))) == 0)
> @@ -5254,6 +5272,8 @@
> .wait_until_sent = stli_waituntilsent,
> .send_xchar = stli_sendxchar,
> .read_proc = stli_readproc,
> + .tiocmget = stli_tiocmget,
> + .tiocmset = stli_tiocmset,
> };
>
> /*****************************************************************************/
> ===== drivers/char/rio/rio_linux.c 1.32 vs edited =====
> --- 1.32/drivers/char/rio/rio_linux.c Tue Sep 30 01:34:28 2003
> +++ edited/drivers/char/rio/rio_linux.c Tue Jan 13 15:01:40 2004
> @@ -728,6 +728,11 @@
> rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
> break;
> #if 0
> + /*
> + * note: these IOCTLs no longer reach here. Use
> + * tiocmset/tiocmget driver methods instead. The
> + * #if 0 disablement predates this comment.
> + */
> case TIOCMGET:
> if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
> sizeof(unsigned int))) == 0) {
> ===== drivers/char/rocket.c 1.36 vs edited =====
> --- 1.36/drivers/char/rocket.c Thu Oct 9 23:13:53 2003
> +++ edited/drivers/char/rocket.c Tue Jan 13 16:28:49 2004
> @@ -1216,59 +1216,6 @@
> /********************************************************************************************/
> /* Here are the routines used by rp_ioctl. These are all called from exception handlers. */
>
> -static int get_modem_info(struct r_port *info, unsigned int *value)
> -{
> - unsigned int control, result, ChanStatus;
> -
> - ChanStatus = sGetChanStatusLo(&info->channel);
> -
> - control = info->channel.TxControl[3];
> - result = ((control & SET_RTS) ? TIOCM_RTS : 0) |
> - ((control & SET_DTR) ? TIOCM_DTR : 0) |
> - ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
> - (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
> - ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
> - ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
> -
> - if (copy_to_user(value, &result, sizeof (int)))
> - return -EFAULT;
> - return 0;
> -}
> -
> -static int set_modem_info(struct r_port *info, unsigned int cmd,
> - unsigned int *value)
> -{
> - unsigned int arg;
> -
> - if (copy_from_user(&arg, value, sizeof (int)))
> - return -EFAULT;
> -
> - switch (cmd) {
> - case TIOCMBIS:
> - if (arg & TIOCM_RTS)
> - info->channel.TxControl[3] |= SET_RTS;
> - if (arg & TIOCM_DTR)
> - info->channel.TxControl[3] |= SET_DTR;
> - break;
> - case TIOCMBIC:
> - if (arg & TIOCM_RTS)
> - info->channel.TxControl[3] &= ~SET_RTS;
> - if (arg & TIOCM_DTR)
> - info->channel.TxControl[3] &= ~SET_DTR;
> - break;
> - case TIOCMSET:
> - info->channel.TxControl[3] = ((info->channel.TxControl[3] & ~(SET_RTS | SET_DTR)) |
> - ((arg & TIOCM_RTS) ? SET_RTS : 0) |
> - ((arg & TIOCM_DTR) ? SET_DTR : 0));
> - break;
> - default:
> - return -EINVAL;
> - }
> -
> - sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0]));
> - return 0;
> -}
> -
> /*
> * Returns the state of the serial modem control lines. These next 2 functions
> * are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
> @@ -1432,12 +1379,6 @@
> return -ENXIO;
>
> switch (cmd) {
> - case TIOCMGET:
> - return get_modem_info(info, (unsigned int *) arg);
> - case TIOCMBIS:
> - case TIOCMBIC:
> - case TIOCMSET:
> - return set_modem_info(info, cmd, (unsigned int *) arg);
> case RCKP_GET_STRUCT:
> if (copy_to_user((void *) arg, info, sizeof (struct r_port)))
> return -EFAULT;
> ===== drivers/char/sh-sci.c 1.25 vs edited =====
> --- 1.25/drivers/char/sh-sci.c Wed Jun 11 20:32:39 2003
> +++ edited/drivers/char/sh-sci.c Tue Jan 13 15:17:23 2004
> @@ -859,6 +859,31 @@
> return retval;
> }
>
> +static int sci_tiocmget(struct tty_struct *tty, struct file *file)
> +{
> + struct sci_port *port = tty->driver_data;
> + return sci_getsignals(port);
> +}
> +
> +static int sci_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear)
> +{
> + struct sci_port *port = tty->driver_data;
> + int rts = -1, dtr = -1;
> +
> + if (set & TIOCM_RTS)
> + rts = 1;
> + if (set & TIOCM_DTR)
> + dtr = 1;
> + if (clear & TIOCM_RTS)
> + rts = 0;
> + if (clear & TIOCM_DTR)
> + dtr = 0;
> +
> + sci_setsignals(port, dtr, rts);
> + return 0;
> +}
> +
> static int sci_ioctl(struct tty_struct * tty, struct file * filp,
> unsigned int cmd, unsigned long arg)
> {
> @@ -889,25 +914,6 @@
> rc = gs_setserial(&port->gs,
> (struct serial_struct *) arg);
> break;
> - case TIOCMGET:
> - ival = sci_getsignals(port);
> - rc = put_user(ival, (unsigned int *) arg);
> - break;
> - case TIOCMBIS:
> - if ((rc = get_user(ival, (unsigned int *) arg)) == 0)
> - sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
> - ((ival & TIOCM_RTS) ? 1 : -1));
> - break;
> - case TIOCMBIC:
> - if ((rc = get_user(ival, (unsigned int *) arg)) == 0)
> - sci_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
> - ((ival & TIOCM_RTS) ? 0 : -1));
> - break;
> - case TIOCMSET:
> - if ((rc = get_user(ival, (unsigned int *)arg)) == 0)
> - sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
> - ((ival & TIOCM_RTS) ? 1 : 0));
> - break;
>
> default:
> rc = -ENOIOCTLCMD;
> @@ -991,6 +997,8 @@
> #ifdef CONFIG_PROC_FS
> .read_proc = sci_read_proc,
> #endif
> + .tiocmget = sci_tiocmget,
> + .tiocmset = sci_tiocmset,
> };
>
> /* ********************************************************************** *
> ===== drivers/char/stallion.c 1.37 vs edited =====
> --- 1.37/drivers/char/stallion.c Tue Sep 30 01:34:28 2003
> +++ edited/drivers/char/stallion.c Tue Jan 13 15:10:39 2004
> @@ -1514,6 +1514,48 @@
>
> /*****************************************************************************/
>
> +static int stl_tiocmget(struct tty_struct *tty, struct file *file)
> +{
> + stlport_t *portp;
> +
> + if (tty == (struct tty_struct *) NULL)
> + return(-ENODEV);
> + portp = tty->driver_data;
> + if (portp == (stlport_t *) NULL)
> + return(-ENODEV);
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return(-EIO);
> +
> + return stl_getsignals(portp);
> +}
> +
> +static int stl_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear)
> +{
> + stlport_t *portp;
> + int rts = -1, dtr = -1;
> +
> + if (tty == (struct tty_struct *) NULL)
> + return(-ENODEV);
> + portp = tty->driver_data;
> + if (portp == (stlport_t *) NULL)
> + return(-ENODEV);
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return(-EIO);
> +
> + if (set & TIOCM_RTS)
> + rts = 1;
> + if (set & TIOCM_DTR)
> + dtr = 1;
> + if (clear & TIOCM_RTS)
> + rts = 0;
> + if (clear & TIOCM_DTR)
> + dtr = 0;
> +
> + stl_setsignals(portp, dtr, rts);
> + return 0;
> +}
> +
> static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
> {
> stlport_t *portp;
> @@ -1553,37 +1595,6 @@
> (ival ? CLOCAL : 0);
> }
> break;
> - case TIOCMGET:
> - if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))) == 0) {
> - ival = stl_getsignals(portp);
> - put_user(ival, (unsigned int *) arg);
> - }
> - break;
> - case TIOCMBIS:
> - if ((rc = verify_area(VERIFY_READ, (void *) arg,
> - sizeof(unsigned int))) == 0) {
> - get_user(ival, (unsigned int *) arg);
> - stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : -1),
> - ((ival & TIOCM_RTS) ? 1 : -1));
> - }
> - break;
> - case TIOCMBIC:
> - if ((rc = verify_area(VERIFY_READ, (void *) arg,
> - sizeof(unsigned int))) == 0) {
> - get_user(ival, (unsigned int *) arg);
> - stl_setsignals(portp, ((ival & TIOCM_DTR) ? 0 : -1),
> - ((ival & TIOCM_RTS) ? 0 : -1));
> - }
> - break;
> - case TIOCMSET:
> - if ((rc = verify_area(VERIFY_READ, (void *) arg,
> - sizeof(unsigned int))) == 0) {
> - get_user(ival, (unsigned int *) arg);
> - stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : 0),
> - ((ival & TIOCM_RTS) ? 1 : 0));
> - }
> - break;
> case TIOCGSERIAL:
> if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
> sizeof(struct serial_struct))) == 0)
> @@ -3137,6 +3148,8 @@
> .wait_until_sent = stl_waituntilsent,
> .send_xchar = stl_sendxchar,
> .read_proc = stl_readproc,
> + .tiocmget = stl_tiocmget,
> + .tiocmset = stl_tiocmset,
> };
>
> /*****************************************************************************/
> ===== drivers/char/sx.c 1.42 vs edited =====
> --- 1.42/drivers/char/sx.c Tue Dec 30 08:41:41 2003
> +++ edited/drivers/char/sx.c Tue Jan 13 14:59:30 2004
> @@ -1743,6 +1743,32 @@
> }
>
>
> +static int sx_tiocmget(struct tty_struct *tty, struct file *file)
> +{
> + struct sx_port *port = tty->driver_data;
> + return sx_getsignals(port);
> +}
> +
> +static int sx_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear)
> +{
> + struct sx_port *port = tty->driver_data;
> + int rts = -1, cts = -1;
> +
> + if (set & TIOCM_RTS)
> + rts = 1;
> + if (set & TIOCM_DTR)
> + dtr = 1;
> + if (clear & TIOCM_RTS)
> + rts = 0;
> + if (clear & TIOCM_DTR)
> + dtr = 0;
> +
> + sx_setsignals(port, dtr, rts);
> + sx_reconfigure_port(port);
> + return 0;
> +}
> +
> static int sx_ioctl (struct tty_struct * tty, struct file * filp,
> unsigned int cmd, unsigned long arg)
> {
> @@ -1775,34 +1801,6 @@
> sizeof(struct serial_struct))) == 0)
> rc = gs_setserial(&port->gs, (struct serial_struct *) arg);
> break;
> - case TIOCMGET:
> - if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))) == 0) {
> - ival = sx_getsignals(port);
> - put_user(ival, (unsigned int *) arg);
> - }
> - break;
> - case TIOCMBIS:
> - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
> - sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
> - ((ival & TIOCM_RTS) ? 1 : -1));
> - sx_reconfigure_port(port);
> - }
> - break;
> - case TIOCMBIC:
> - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
> - sx_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
> - ((ival & TIOCM_RTS) ? 0 : -1));
> - sx_reconfigure_port(port);
> - }
> - break;
> - case TIOCMSET:
> - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
> - sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
> - ((ival & TIOCM_RTS) ? 1 : 0));
> - sx_reconfigure_port(port);
> - }
> - break;
> default:
> rc = -ENOIOCTLCMD;
> break;
> @@ -2217,6 +2215,8 @@
> .stop = gs_stop,
> .start = gs_start,
> .hangup = gs_hangup,
> + .tiocmget = sx_tiocmget,
> + .tiocmset = sx_tiocmset,
> };
>
> static int sx_init_drivers(void)
> ===== drivers/macintosh/macserial.c 1.30 vs edited =====
> --- 1.30/drivers/macintosh/macserial.c Wed Sep 24 07:15:15 2003
> +++ edited/drivers/macintosh/macserial.c Tue Jan 13 14:55:37 2004
> @@ -1777,47 +1777,65 @@
> return put_user(status,value);
> }
>
> -static int get_modem_info(struct mac_serial *info, unsigned int *value)
> +static int rs_tiocmget(struct tty_struct *tty, struct file *file)
> {
> + struct mac_serial * info = (struct mac_serial *)tty->driver_data;
> unsigned char control, status;
> - unsigned int result;
> unsigned long flags;
>
> +#ifdef CONFIG_KGDB
> + if (info->kgdb_channel)
> + return -ENODEV;
> +#endif
> + if (serial_paranoia_check(info, tty->name, __FUNCTION__))
> + return -ENODEV;
> +
> + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
> + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) {
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return -EIO;
> + }
> +
> spin_lock_irqsave(&info->lock, flags);
> control = info->curregs[5];
> status = read_zsreg(info->zs_channel, 0);
> spin_unlock_irqrestore(&info->lock, flags);
> - result = ((control & RTS) ? TIOCM_RTS: 0)
> + return ((control & RTS) ? TIOCM_RTS: 0)
> | ((control & DTR) ? TIOCM_DTR: 0)
> | ((status & DCD) ? TIOCM_CAR: 0)
> | ((status & CTS) ? 0: TIOCM_CTS);
> - return put_user(result,value);
> }
>
> -static int set_modem_info(struct mac_serial *info, unsigned int cmd,
> - unsigned int *value)
> +static int rs_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear)
> {
> + struct mac_serial * info = (struct mac_serial *)tty->driver_data;
> unsigned int arg, bits;
> unsigned long flags;
>
> - if (get_user(arg, value))
> - return -EFAULT;
> - bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0);
> - spin_lock_irqsave(&info->lock, flags);
> - switch (cmd) {
> - case TIOCMBIS:
> - info->curregs[5] |= bits;
> - break;
> - case TIOCMBIC:
> - info->curregs[5] &= ~bits;
> - break;
> - case TIOCMSET:
> - info->curregs[5] = (info->curregs[5] & ~(DTR | RTS)) | bits;
> - break;
> - default:
> - spin_unlock_irqrestore(&info->lock, flags);
> - return -EINVAL;
> +#ifdef CONFIG_KGDB
> + if (info->kgdb_channel)
> + return -ENODEV;
> +#endif
> + if (serial_paranoia_check(info, tty->name, __FUNCTION__))
> + return -ENODEV;
> +
> + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
> + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) {
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return -EIO;
> }
> +
> + spin_lock_irqsave(&info->lock, flags);
> + if (set & TIOCM_RTS)
> + info->curregs[5] |= RTS;
> + if (set & TIOCM_DTR)
> + info->curregs[5] |= DTR;
> + if (clear & TIOCM_RTS)
> + info->curregs[5] &= ~RTS;
> + if (clear & TIOCM_DTR)
> + info->curregs[5] &= ~DTR;
> +
> info->pendregs[5] = info->curregs[5];
> write_zsreg(info->zs_channel, 5, info->curregs[5]);
> spin_unlock_irqrestore(&info->lock, flags);
> @@ -1863,12 +1881,6 @@
> }
>
> switch (cmd) {
> - case TIOCMGET:
> - return get_modem_info(info, (unsigned int *) arg);
> - case TIOCMBIS:
> - case TIOCMBIC:
> - case TIOCMSET:
> - return set_modem_info(info, cmd, (unsigned int *) arg);
> case TIOCGSERIAL:
> return get_serial_info(info,
> (struct serial_struct __user *) arg);
> @@ -2488,6 +2500,8 @@
> .break_ctl = rs_break,
> .wait_until_sent = rs_wait_until_sent,
> .read_proc = macserial_read_proc,
> + .tiocmget = rs_tiocmget,
> + .tiocmset = rs_tiocmset,
> };
>
> static int macserial_init(void)
> ===== drivers/s390/net/ctctty.c 1.20 vs edited =====
> --- 1.20/drivers/s390/net/ctctty.c Mon Oct 6 11:59:26 2003
> +++ edited/drivers/s390/net/ctctty.c Tue Jan 13 14:51:50 2004
> @@ -655,14 +655,19 @@
> }
>
>
> -static int
> -ctc_tty_get_ctc_tty_info(ctc_tty_info * info, uint * value)
> +static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file)
> {
> + ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
> u_char control,
> status;
> uint result;
> ulong flags;
>
> + if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
> + return -ENODEV;
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return -EIO;
> +
> control = info->mcr;
> spin_lock_irqsave(&ctc_tty_lock, flags);
> status = info->msr;
> @@ -673,51 +678,31 @@
> | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
> | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
> | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
> - put_user(result, (uint *) value);
> - return 0;
> + return result;
> }
>
> static int
> -ctc_tty_set_ctc_tty_info(ctc_tty_info * info, uint cmd, uint * value)
> +ctc_tty_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear)
> {
> - uint arg;
> - int old_mcr = info->mcr & (UART_MCR_RTS | UART_MCR_DTR);
> + ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
>
> - get_user(arg, (uint *) value);
> - switch (cmd) {
> - case TIOCMBIS:
> -#ifdef CTC_DEBUG_MODEM_IOCTL
> - printk(KERN_DEBUG "%s%d ioctl TIOCMBIS\n", CTC_TTY_NAME,
> - info->line);
> -#endif
> - if (arg & TIOCM_RTS)
> - info->mcr |= UART_MCR_RTS;
> - if (arg & TIOCM_DTR)
> - info->mcr |= UART_MCR_DTR;
> - break;
> - case TIOCMBIC:
> -#ifdef CTC_DEBUG_MODEM_IOCTL
> - printk(KERN_DEBUG "%s%d ioctl TIOCMBIC\n", CTC_TTY_NAME,
> - info->line);
> -#endif
> - if (arg & TIOCM_RTS)
> - info->mcr &= ~UART_MCR_RTS;
> - if (arg & TIOCM_DTR)
> - info->mcr &= ~UART_MCR_DTR;
> - break;
> - case TIOCMSET:
> -#ifdef CTC_DEBUG_MODEM_IOCTL
> - printk(KERN_DEBUG "%s%d ioctl TIOCMSET\n", CTC_TTY_NAME,
> - info->line);
> -#endif
> - info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR))
> - | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
> - | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
> - break;
> - default:
> - return -EINVAL;
> - }
> - if ((info->mcr & (UART_MCR_RTS | UART_MCR_DTR)) != old_mcr)
> + if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
> + return -ENODEV;
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return -EIO;
> +
> + if (set & TIOCM_RTS)
> + info->mcr |= UART_MCR_RTS;
> + if (set & TIOCM_DTR)
> + info->mcr |= UART_MCR_DTR;
> +
> + if (clear & TIOCM_RTS)
> + info->mcr &= ~UART_MCR_RTS;
> + if (clear & TIOCM_DTR)
> + info->mcr &= ~UART_MCR_DTR;
> +
> + if ((set | clear) & (TIOCM_RTS|TIOCM_DTR))
> ctc_tty_transmit_status(info);
> return 0;
> }
> @@ -775,22 +760,6 @@
> ((tty->termios->c_cflag & ~CLOCAL) |
> (arg ? CLOCAL : 0));
> return 0;
> - case TIOCMGET:
> -#ifdef CTC_DEBUG_MODEM_IOCTL
> - printk(KERN_DEBUG "%s%d ioctl TIOCMGET\n", CTC_TTY_NAME,
> - info->line);
> -#endif
> - error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
> - if (error)
> - return error;
> - return ctc_tty_get_ctc_tty_info(info, (uint *) arg);
> - case TIOCMBIS:
> - case TIOCMBIC:
> - case TIOCMSET:
> - error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint));
> - if (error)
> - return error;
> - return ctc_tty_set_ctc_tty_info(info, cmd, (uint *) arg);
> case TIOCSERGETLSR: /* Get line status register */
> #ifdef CTC_DEBUG_MODEM_IOCTL
> printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME,
> @@ -1142,6 +1111,8 @@
> .unthrottle = ctc_tty_unthrottle,
> .set_termios = ctc_tty_set_termios,
> .hangup = ctc_tty_hangup,
> + .tiocmget = ctc_tty_tiocmget,
> + .tiocmset = ctc_tty_tiocmset,
> };
>
> int
> ===== drivers/serial/mcfserial.c 1.17 vs edited =====
> --- 1.17/drivers/serial/mcfserial.c Thu Jul 3 02:18:07 2003
> +++ edited/drivers/serial/mcfserial.c Tue Jan 13 13:22:09 2004
> @@ -985,6 +985,43 @@
> local_irq_restore(flags);
> }
>
> +static int mcfrs_tiocmget(struct tty_struct *tty, struct file *file)
> +{
> + struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
> +
> + if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
> + return -ENODEV;
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return -EIO;
> +
> + return mcfrs_getsignals(info);
> +}
> +
> +static int mcfrs_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear)
> +{
> + struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
> + int rts = -1, dtr = -1;
> +
> + if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
> + return -ENODEV;
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return -EIO;
> +
> + if (set & TIOCM_RTS)
> + rts = 1;
> + if (set & TIOCM_DTR)
> + dtr = 1;
> + if (clear & TIOCM_RTS)
> + rts = 0;
> + if (clear & TIOCM_DTR)
> + dtr = 0;
> +
> + mcfrs_setsignals(info, dtr, rts);
> +
> + return 0;
> +}
> +
> static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
> unsigned int cmd, unsigned long arg)
> {
> @@ -1059,45 +1096,6 @@
> info, sizeof(struct mcf_serial));
> return 0;
>
> - case TIOCMGET:
> - if ((error = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))))
> - return(error);
> - val = mcfrs_getsignals(info);
> - put_user(val, (unsigned int *) arg);
> - break;
> -
> - case TIOCMBIS:
> - if ((error = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))))
> - return(error);
> -
> - get_user(val, (unsigned int *) arg);
> - rts = (val & TIOCM_RTS) ? 1 : -1;
> - dtr = (val & TIOCM_DTR) ? 1 : -1;
> - mcfrs_setsignals(info, dtr, rts);
> - break;
> -
> - case TIOCMBIC:
> - if ((error = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))))
> - return(error);
> - get_user(val, (unsigned int *) arg);
> - rts = (val & TIOCM_RTS) ? 0 : -1;
> - dtr = (val & TIOCM_DTR) ? 0 : -1;
> - mcfrs_setsignals(info, dtr, rts);
> - break;
> -
> - case TIOCMSET:
> - if ((error = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))))
> - return(error);
> - get_user(val, (unsigned int *) arg);
> - rts = (val & TIOCM_RTS) ? 1 : 0;
> - dtr = (val & TIOCM_DTR) ? 1 : 0;
> - mcfrs_setsignals(info, dtr, rts);
> - break;
> -
> #ifdef TIOCSET422
> case TIOCSET422:
> get_user(val, (unsigned int *) arg);
> @@ -1563,6 +1561,8 @@
> .start = mcfrs_start,
> .hangup = mcfrs_hangup,
> .read_proc = mcfrs_readproc,
> + .tiocmget = mcfrs_tiocmget,
> + .tiocmset = mcfrs_tiocmset,
> };
>
> /* mcfrs_init inits the driver */
> ===== drivers/usb/serial/ftdi_sio.c 1.55 vs edited =====
> --- 1.55/drivers/usb/serial/ftdi_sio.c Tue Oct 28 13:44:01 2003
> +++ edited/drivers/usb/serial/ftdi_sio.c Tue Jan 13 14:16:51 2004
> @@ -580,6 +580,8 @@
> static void ftdi_break_ctl (struct usb_serial_port *port, int break_state );
> static void ftdi_throttle (struct usb_serial_port *port);
> static void ftdi_unthrottle (struct usb_serial_port *port);
> +static int ftdi_tiocmget (struct usb_serial_port *port, struct file * file);
> +static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
>
> static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base);
> static unsigned short int ftdi_232am_baud_to_divisor (int baud);
> @@ -608,6 +610,8 @@
> .break_ctl = ftdi_break_ctl,
> .attach = ftdi_SIO_startup,
> .shutdown = ftdi_shutdown,
> + .tiocmget = ftdi_tiocmget,
> + .tiocmset = ftdi_tiocmset,
> };
>
> static struct usb_serial_device_type ftdi_8U232AM_device = {
> @@ -632,6 +636,8 @@
> .break_ctl = ftdi_break_ctl,
> .attach = ftdi_8U232AM_startup,
> .shutdown = ftdi_shutdown,
> + .tiocmget = ftdi_tiocmget,
> + .tiocmset = ftdi_tiocmset,
> };
>
> static struct usb_serial_device_type ftdi_FT232BM_device = {
> @@ -656,6 +662,8 @@
> .break_ctl = ftdi_break_ctl,
> .attach = ftdi_FT232BM_startup,
> .shutdown = ftdi_shutdown,
> + .tiocmget = ftdi_tiocmget,
> + .tiocmset = ftdi_tiocmset,
> };
>
> static struct usb_serial_device_type ftdi_USB_UIRT_device = {
> @@ -680,6 +688,8 @@
> .break_ctl = ftdi_break_ctl,
> .attach = ftdi_USB_UIRT_startup,
> .shutdown = ftdi_shutdown,
> + .tiocmget = ftdi_tiocmget,
> + .tiocmset = ftdi_tiocmset,
> };
>
> /* The TIRA1 is based on a FT232BM which requires a fixed baud rate of 100000
> @@ -706,6 +716,8 @@
> .break_ctl = ftdi_break_ctl,
> .attach = ftdi_HE_TIRA1_startup,
> .shutdown = ftdi_shutdown,
> + .tiocmget = ftdi_tiocmget,
> + .tiocmset = ftdi_tiocmset,
> };
>
>
> @@ -1808,119 +1820,94 @@
> } /* ftdi_termios */
>
>
> -static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
> +static int ftdi_tiocmget (struct usb_serial_port *port, struct file * file)
> {
> struct usb_serial *serial = port->serial;
> struct ftdi_private *priv = usb_get_serial_port_data(port);
> -
> - __u16 urb_value=0; /* Will hold the new flags */
> char buf[2];
> - int ret, mask;
> -
> - dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
> -
> - /* Based on code from acm.c and others */
> - switch (cmd) {
> + int ret;
>
> - case TIOCMGET:
> - dbg("%s TIOCMGET", __FUNCTION__);
> - switch (priv->chip_type) {
> - case SIO:
> - /* Request the status from the device */
> - if ((ret = usb_control_msg(serial->dev,
> - usb_rcvctrlpipe(serial->dev, 0),
> - FTDI_SIO_GET_MODEM_STATUS_REQUEST,
> - FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
> - 0, 0,
> - buf, 1, WDR_TIMEOUT)) < 0 ) {
> - err("%s Could not get modem status of device - err: %d", __FUNCTION__,
> - ret);
> - return(ret);
> - }
> - break;
> - case FT8U232AM:
> - case FT232BM:
> - /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
> - format as the data returned from the in point */
> - if ((ret = usb_control_msg(serial->dev,
> - usb_rcvctrlpipe(serial->dev, 0),
> - FTDI_SIO_GET_MODEM_STATUS_REQUEST,
> - FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
> - 0, 0,
> - buf, 2, WDR_TIMEOUT)) < 0 ) {
> - err("%s Could not get modem status of device - err: %d", __FUNCTION__,
> - ret);
> - return(ret);
> - }
> - break;
> - default:
> - return -EFAULT;
> - break;
> + dbg("%s TIOCMGET", __FUNCTION__);
> + switch (priv->chip_type) {
> + case SIO:
> + /* Request the status from the device */
> + if ((ret = usb_control_msg(serial->dev,
> + usb_rcvctrlpipe(serial->dev, 0),
> + FTDI_SIO_GET_MODEM_STATUS_REQUEST,
> + FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
> + 0, 0,
> + buf, 1, WDR_TIMEOUT)) < 0 ) {
> + err("%s Could not get modem status of device - err: %d", __FUNCTION__,
> + ret);
> + return(ret);
> }
> -
> - return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
> - (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
> - (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
> - (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
> - priv->last_dtr_rts,
> - (unsigned long *) arg);
> break;
> + case FT8U232AM:
> + case FT232BM:
> + /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
> + format as the data returned from the in point */
> + if ((ret = usb_control_msg(serial->dev,
> + usb_rcvctrlpipe(serial->dev, 0),
> + FTDI_SIO_GET_MODEM_STATUS_REQUEST,
> + FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
> + 0, 0,
> + buf, 2, WDR_TIMEOUT)) < 0 ) {
> + err("%s Could not get modem status of device - err: %d", __FUNCTION__,
> + ret);
> + return(ret);
> + }
> + break;
> + default:
> + return -EFAULT;
> + break;
> + }
> +
> + return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
> + (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
> + (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
> + (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
> + priv->last_dtr_rts;
> +}
> +
> +static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
> +{
> + struct usb_serial *serial = port->serial;
> + struct ftdi_private *priv = usb_get_serial_port_data(port);
> + __u16 urb_value;
> + int ret;
> +
> + dbg("%s TIOCMSET/BIC/BIS", __FUNCTION__);
>
> - case TIOCMSET: /* Turns on and off the lines as specified by the mask */
> - dbg("%s TIOCMSET", __FUNCTION__);
> - if (get_user(mask, (unsigned long *) arg))
> - return -EFAULT;
> - urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
> + if ((set | clear) & TIOCM_DTR) {
> + urb_value = (set & TIOCM_DTR) ? HIGH : LOW;
> if ((ret = set_dtr(port, urb_value)) < 0){
> - err("Error from DTR set urb (TIOCMSET)");
> + err("Error from DTR set urb (TIOCM)");
> return(ret);
> }
> - urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW);
> + }
> + if ((set | clear) & TIOCM_RTS) {
> + urb_value = (set & TIOCM_RTS) ? HIGH : LOW;
> if ((ret = set_rts(port, urb_value)) < 0){
> - err("Error from RTS set urb (TIOCMSET)");
> + err("Error from RTS set urb (TIOCM)");
> return(ret);
> }
> - return(0);
> - break;
> -
> - case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
> - dbg("%s TIOCMBIS", __FUNCTION__);
> - if (get_user(mask, (unsigned long *) arg))
> - return -EFAULT;
> - if (mask & TIOCM_DTR){
> - if ((ret = set_dtr(port, HIGH)) < 0) {
> - err("Urb to set DTR failed");
> - return(ret);
> - }
> - }
> - if (mask & TIOCM_RTS) {
> - if ((ret = set_rts(port, HIGH)) < 0){
> - err("Urb to set RTS failed");
> - return(ret);
> - }
> - }
> - return(0);
> - break;
> + }
> + return(0);
> +}
>
> - case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
> - dbg("%s TIOCMBIC", __FUNCTION__);
> - if (get_user(mask, (unsigned long *) arg))
> - return -EFAULT;
> - if (mask & TIOCM_DTR){
> - if ((ret = set_dtr(port, LOW)) < 0){
> - err("Urb to unset DTR failed");
> - return(ret);
> - }
> - }
> - if (mask & TIOCM_RTS) {
> - if ((ret = set_rts(port, LOW)) < 0){
> - err("Urb to unset RTS failed");
> - return(ret);
> - }
> - }
> - return(0);
> - break;
> +static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
> +{
> + struct usb_serial *serial = port->serial;
> + struct ftdi_private *priv = usb_get_serial_port_data(port);
>
> + __u16 urb_value=0; /* Will hold the new flags */
> + char buf[2];
> + int ret, mask;
> +
> + dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
> +
> + /* Based on code from acm.c and others */
> + switch (cmd) {
> /*
> * I had originally implemented TCSET{A,S}{,F,W} and
> * TCGET{A,S} here separately, however when testing I
>

--
Henrique Oliveira
Product Marketing Specialist
Cyclades Corporation
http://www.cyclades.com
Phone: 510.771.6205
Fax: 510.771.6200
email: [email protected]

2004-01-13 18:30:01

by Russell King

[permalink] [raw]
Subject: Re: Re: [PROBLEM] ircomm ioctls

On Tue, Jan 13, 2004 at 10:10:34AM -0800, Jean Tourrilhes wrote:
> Russell King wrote :
> > On Tue, Jan 13, 2004 at 12:00:15PM +0100, Jozef Vesely wrote:
> > > I am gettig this error (while connecting to my mobile phone):
> > > ------
> > > # gsmctl -d /dev/ircomm0 ALL
> > > gsmctl[ERROR]: clearing DTR failed (errno: 22/Invalid argument)
> > > ------
> >
> > ircomm needs updating to use the tiocmset/tiocmget driver calls. Could
> > you see if the following patch solves your problem please?
>
> Good catch. Is there any other API changes worth looking into ?
>
> By the way, I would rather keep the function
> ircomm_tty_tiocmget() and ircomm_tty_tiocmset() in ircomm_tty_ioctl.c,
> because ircomm_tty.c is already big and messy.
> Check the patch below (quickly tested).

I think this patch is missing some of the error checking (TTY_IO_ERROR)
which I included in my later patch.

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-13 19:09:56

by Jean Tourrilhes

[permalink] [raw]
Subject: Re: Re: [PROBLEM] ircomm ioctls

On Tue, Jan 13, 2004 at 06:29:55PM +0000, Russell King wrote:
> On Tue, Jan 13, 2004 at 10:10:34AM -0800, Jean Tourrilhes wrote:
> >
> > By the way, I would rather keep the function
> > ircomm_tty_tiocmget() and ircomm_tty_tiocmset() in ircomm_tty_ioctl.c,
> > because ircomm_tty.c is already big and messy.
> > Check the patch below (quickly tested).
>
> I think this patch is missing some of the error checking (TTY_IO_ERROR)
> which I included in my later patch.

Oh well... I probably missed your subsequent patch. Sorry
about that.
I used this patch of yours :
http://marc.theaimsgroup.com/?l=linux-kernel&m=107399412221312&w=2

> Russell King

Thanks, and have fun...

Jean

2004-01-13 20:20:15

by Andrew Morton

[permalink] [raw]
Subject: Re: [3/3] 2.6 broken serial drivers

Russell King <[email protected]> wrote:
>
> --- 1.14/drivers/net/wan/pc300_tty.c Thu Sep 11 18:40:53 2003
> +++ edited/drivers/net/wan/pc300_tty.c Tue Jan 13 14:42:34 2004
> @@ -583,6 +583,14 @@
> CPC_TTY_DBG("%s: IOCTL cmd %x\n",cpc_tty->name,cmd);
>
> switch (cmd) {
> +#error This is broken. See comments.

Grumble. This breaks allmodconfig. #warning, please.


2004-01-13 20:59:37

by John Stoffel

[permalink] [raw]
Subject: Re: [2/3]


Henrique> I am no longer the maintainer of the Cyclades driver
Henrique> (char/cyclades.c). Could you please remove my name from
Henrique> that driver and include Daniela as the official maintainer
Henrique> <[email protected]> ?

Wouldn't it make more sense for you people at Cyclades to setup an
email alias like '[email protected]' so we can update the
kernel sources once, and then you can update your internal email alias
as things change?

Seems like the better way to go...

John

2004-01-13 21:12:01

by Russell King

[permalink] [raw]
Subject: Re: [3/3] 2.6 broken serial drivers

On Tue, Jan 13, 2004 at 12:21:15PM -0800, Andrew Morton wrote:
> Russell King <[email protected]> wrote:
> >
> > --- 1.14/drivers/net/wan/pc300_tty.c Thu Sep 11 18:40:53 2003
> > +++ edited/drivers/net/wan/pc300_tty.c Tue Jan 13 14:42:34 2004
> > @@ -583,6 +583,14 @@
> > CPC_TTY_DBG("%s: IOCTL cmd %x\n",cpc_tty->name,cmd);
> >
> > switch (cmd) {
> > +#error This is broken. See comments.
>
> Grumble. This breaks allmodconfig. #warning, please.

Probably far better to make all these drivers depend on BROKEN unless
one of the authors speaks up.

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-14 06:21:24

by Paul Mackerras

[permalink] [raw]
Subject: Re: [2/3]

Russell King writes:

> Here are patches to drivers in the 2.6 kernel which have not been tested
> to correct the tiocmset/tiocmget problem.

Note that drivers/macintosh/macserial.c is now deprecated, people
should use drivers/serial/pmac_zilog.c.

Ben, is it time to get rid of macserial.c yet?

Paul.

2004-01-14 07:07:56

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [2/3]

On Wed, 2004-01-14 at 09:15, Paul Mackerras wrote:
> Russell King writes:
>
> > Here are patches to drivers in the 2.6 kernel which have not been tested
> > to correct the tiocmset/tiocmget problem.
>
> Note that drivers/macintosh/macserial.c is now deprecated, people
> should use drivers/serial/pmac_zilog.c.
>
> Ben, is it time to get rid of macserial.c yet?

In 2.6 ? well, probably yes, I didn't find any problem with it so
far... On another hand, it wasn't much tested yet.

I still have a big bunch of driver updates I have to send to Andrew,
I'll eventually kill macserial at this point

Ben.


2004-01-14 12:42:53

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: [3/3] 2.6 broken serial drivers

On Tue, 13 Jan 2004, Russell King wrote:

> Here is a patch which updates various serial drivers in the kernel to
> make them less broken than they were before. Nevertheless, they are
> still broken.
[...]
> ===== drivers/tc/zs.c 1.24 vs edited =====
> --- 1.24/drivers/tc/zs.c Fri Sep 26 00:38:44 2003
> +++ edited/drivers/tc/zs.c Tue Jan 13 14:25:30 2004

Thanks for the patch. Due to other priorities I have to defer run-time
testing of the driver with 2.6, but I'll have a look at the changes and
make adjustments if they happen to clash with a recent port of fixes from
2.4.

Maciej

--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: [email protected], PGP key available +

2004-01-14 19:39:39

by Jean Tourrilhes

[permalink] [raw]
Subject: Re: Re: [PROBLEM] ircomm ioctls

On Tue, Jan 13, 2004 at 06:29:55PM +0000, Russell King wrote:
> On Tue, Jan 13, 2004 at 10:10:34AM -0800, Jean Tourrilhes wrote:
> > Russell King wrote :
> > > On Tue, Jan 13, 2004 at 12:00:15PM +0100, Jozef Vesely wrote:
> > > > I am gettig this error (while connecting to my mobile phone):
> > > > ------
> > > > # gsmctl -d /dev/ircomm0 ALL
> > > > gsmctl[ERROR]: clearing DTR failed (errno: 22/Invalid argument)
> > > > ------
> > >
> > > ircomm needs updating to use the tiocmset/tiocmget driver calls. Could
> > > you see if the following patch solves your problem please?
> >
> > Good catch. Is there any other API changes worth looking into ?
> >
> > By the way, I would rather keep the function
> > ircomm_tty_tiocmget() and ircomm_tty_tiocmset() in ircomm_tty_ioctl.c,
> > because ircomm_tty.c is already big and messy.
> > Check the patch below (quickly tested).
>
> I think this patch is missing some of the error checking (TTY_IO_ERROR)
> which I included in my later patch.

Gotcha. Thanks. The patch would look like attached.

By the way, are you sending this patch as part of your mega
patch or do you want me to send it ? I just want to avoid patch
collision ;-)
Thanks...

Jean

--------------------------------------------------------------

diff -u -p linux/include/net/irda/ircomm_tty.d5.h linux/include/net/irda/ircomm_tty.h
--- linux/include/net/irda/ircomm_tty.d5.h Tue Jan 13 09:51:52 2004
+++ linux/include/net/irda/ircomm_tty.h Tue Jan 13 10:01:11 2004
@@ -122,6 +122,9 @@ void ircomm_tty_stop(struct tty_struct *
void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self);

extern void ircomm_tty_change_speed(struct ircomm_tty_cb *self);
+extern int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file);
+extern int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
extern void ircomm_tty_set_termios(struct tty_struct *tty,
diff -u -p linux/net/irda/ircomm/ircomm_tty.d5.c linux/net/irda/ircomm/ircomm_tty.c
--- linux/net/irda/ircomm/ircomm_tty.d5.c Tue Jan 13 09:55:04 2004
+++ linux/net/irda/ircomm/ircomm_tty.c Tue Jan 13 10:02:52 2004
@@ -86,7 +86,9 @@ static struct tty_operations ops = {
.write_room = ircomm_tty_write_room,
.chars_in_buffer = ircomm_tty_chars_in_buffer,
.flush_buffer = ircomm_tty_flush_buffer,
- .ioctl = ircomm_tty_ioctl,
+ .ioctl = ircomm_tty_ioctl, /* ircomm_tty_ioctl.c */
+ .tiocmget = ircomm_tty_tiocmget, /* ircomm_tty_ioctl.c */
+ .tiocmset = ircomm_tty_tiocmset, /* ircomm_tty_ioctl.c */
.throttle = ircomm_tty_throttle,
.unthrottle = ircomm_tty_unthrottle,
.send_xchar = ircomm_tty_send_xchar,
diff -u -p linux/net/irda/ircomm/ircomm_tty_ioctl.d5.c linux/net/irda/ircomm/ircomm_tty_ioctl.c
--- linux/net/irda/ircomm/ircomm_tty_ioctl.d5.c Tue Jan 13 09:54:53 2004
+++ linux/net/irda/ircomm/ircomm_tty_ioctl.c Wed Jan 14 11:27:56 2004
@@ -190,81 +190,62 @@ void ircomm_tty_set_termios(struct tty_s
}

/*
- * Function ircomm_tty_get_modem_info (self, value)
+ * Function ircomm_tty_tiocmget (tty, file)
*
*
*
*/
-static int ircomm_tty_get_modem_info(struct ircomm_tty_cb *self,
- unsigned int *value)
+int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
unsigned int result;

IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );

+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
result = ((self->settings.dte & IRCOMM_RTS) ? TIOCM_RTS : 0)
| ((self->settings.dte & IRCOMM_DTR) ? TIOCM_DTR : 0)
| ((self->settings.dce & IRCOMM_CD) ? TIOCM_CAR : 0)
| ((self->settings.dce & IRCOMM_RI) ? TIOCM_RNG : 0)
| ((self->settings.dce & IRCOMM_DSR) ? TIOCM_DSR : 0)
| ((self->settings.dce & IRCOMM_CTS) ? TIOCM_CTS : 0);
-
- return put_user(result, value);
+ return result;
}

/*
- * Function set_modem_info (driver, cmd, value)
+ * Function ircomm_tty_tiocmset (tty, file, set, clear)
*
*
*
*/
-static int ircomm_tty_set_modem_info(struct ircomm_tty_cb *self,
- unsigned int cmd, unsigned int *value)
+int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
- unsigned int arg;
- __u8 old_rts, old_dtr;
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;

IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );

+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);

- if (get_user(arg, value))
- return -EFAULT;
+ if (set & TIOCM_RTS)
+ self->settings.dte |= IRCOMM_RTS;
+ if (set & TIOCM_DTR)
+ self->settings.dte |= IRCOMM_DTR;
+
+ if (clear & TIOCM_RTS)
+ self->settings.dte &= ~IRCOMM_RTS;
+ if (clear & TIOCM_DTR)
+ self->settings.dte &= ~IRCOMM_DTR;

- old_rts = self->settings.dte & IRCOMM_RTS;
- old_dtr = self->settings.dte & IRCOMM_DTR;
-
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- self->settings.dte |= IRCOMM_RTS;
- if (arg & TIOCM_DTR)
- self->settings.dte |= IRCOMM_DTR;
- break;
-
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- self->settings.dte &= ~IRCOMM_RTS;
- if (arg & TIOCM_DTR)
- self->settings.dte &= ~IRCOMM_DTR;
- break;
-
- case TIOCMSET:
- self->settings.dte =
- ((self->settings.dte & ~(IRCOMM_RTS | IRCOMM_DTR))
- | ((arg & TIOCM_RTS) ? IRCOMM_RTS : 0)
- | ((arg & TIOCM_DTR) ? IRCOMM_DTR : 0));
- break;
-
- default:
- return -EINVAL;
- }
-
- if ((self->settings.dte & IRCOMM_RTS) != old_rts)
+ if ((set|clear) & TIOCM_RTS)
self->settings.dte |= IRCOMM_DELTA_RTS;
-
- if ((self->settings.dte & IRCOMM_DTR) != old_dtr)
+ if ((set|clear) & TIOCM_DTR)
self->settings.dte |= IRCOMM_DELTA_DTR;

ircomm_param_request(self, IRCOMM_DTE, TRUE);
@@ -406,14 +387,6 @@ int ircomm_tty_ioctl(struct tty_struct *
}

switch (cmd) {
- case TIOCMGET:
- ret = ircomm_tty_get_modem_info(self, (unsigned int *) arg);
- break;
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- ret = ircomm_tty_set_modem_info(self, cmd, (unsigned int *) arg);
- break;
case TIOCGSERIAL:
ret = ircomm_tty_get_serial_info(self, (struct serial_struct *) arg);
break;

2004-01-14 20:24:58

by Russell King

[permalink] [raw]
Subject: Re: Re: [PROBLEM] ircomm ioctls

On Wed, Jan 14, 2004 at 11:38:04AM -0800, Jean Tourrilhes wrote:
> By the way, are you sending this patch as part of your mega
> patch or do you want me to send it ? I just want to avoid patch
> collision ;-)

I'd prefer these patches to go via the maintainers themselves.
Also, the patch looks fine from my perspective.

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-16 01:20:30

by Greg KH

[permalink] [raw]
Subject: Re: [2/3]

On Tue, Jan 13, 2004 at 05:33:52PM +0000, Russell King wrote:
> ===== drivers/usb/serial/ftdi_sio.c 1.55 vs edited =====
> --- 1.55/drivers/usb/serial/ftdi_sio.c Tue Oct 28 13:44:01 2003
> +++ edited/drivers/usb/serial/ftdi_sio.c Tue Jan 13 14:16:51 2004

Yeah, this ended up here due to a bad merge a few kernel releases ago.
I have the fix for this driver in my queue of USB patches to send off to
Linus soon.

Sorry about this.

Nice job in fixing up all of the other drivers, that was a big effort.

greg k-h

2004-01-16 11:35:42

by Matthias Urlichs

[permalink] [raw]
Subject: Re: [2/3]

Hi, Benjamin Herrenschmidt wrote:

> I still have a big bunch of driver updates I have to send to Andrew,

Any idea when you'll get around to that?

The reason I'm asking is that my kernel, based on a too-long-ago and
often-haphazardly-updated merge between -benh and -mm, crashes on suspend
(Powerbook). I'd rather debug this based on some sort of semi-official
kernel...

--
Matthias Urlichs | {M:U} IT Design @ m-u-it.de | [email protected]
Disclaimer: The quote was selected randomly. Really. | http://smurf.noris.de
- -
The first requisite for immortality is death.

2004-01-18 12:43:25

by Greg Ungerer

[permalink] [raw]
Subject: Re: [2/3]

Hi Russel,

Russell King wrote:
> Here are patches to drivers in the 2.6 kernel which have not been tested
> to correct the tiocmset/tiocmget problem.
>
> You can find the full thread at the following URL:
>
> http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=1dvnl-5Pr-1%40gated-at.bofh.it&rnum=1&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DISO-8859-1%26q%3DOutstanding%2Bfixups%26btnG%3DGoogle%2BSearch%26meta%3Dgroup%253Dlinux.kernel

Looks good for mcfserial.c. The only additional change I would
make is to remove the "rts", "dtr", and "val" variables from the
ioctl function - removing the TIOCM* cases means these variables
are no longer used.

Regards
Greg


------------------------------------------------------------------------
Greg Ungerer -- Chief Software Dude EMAIL: [email protected]
SnapGear -- a CyberGuard Company PHONE: +61 7 3435 2888
825 Stanley St, FAX: +61 7 3891 3630
Woolloongabba, QLD, 4102, Australia WEB: http://www.SnapGear.com

2004-01-18 15:42:31

by Russell King

[permalink] [raw]
Subject: Re: [2/3]

On Sun, Jan 18, 2004 at 10:43:01PM +1000, Greg Ungerer wrote:
> Hi Russel,
>
> Russell King wrote:
> > Here are patches to drivers in the 2.6 kernel which have not been tested
> > to correct the tiocmset/tiocmget problem.
> >
> > You can find the full thread at the following URL:
> >
> > http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=1dvnl-5Pr-1%40gated-at.bofh.it&rnum=1&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DISO-8859-1%26q%3DOutstanding%2Bfixups%26btnG%3DGoogle%2BSearch%26meta%3Dgroup%253Dlinux.kernel
>
> Looks good for mcfserial.c. The only additional change I would
> make is to remove the "rts", "dtr", and "val" variables from the
> ioctl function - removing the TIOCM* cases means these variables
> are no longer used.

I agree for "rts" and "dtr", however "val" is still used - in
TIOC[SG]ET422. Here's a new patch for mcfserial.c

===== drivers/serial/mcfserial.c 1.17 vs edited =====
--- 1.17/drivers/serial/mcfserial.c Thu Jul 3 02:18:07 2003
+++ edited/drivers/serial/mcfserial.c Sun Jan 18 15:40:39 2004
@@ -985,13 +985,49 @@
local_irq_restore(flags);
}

+static int mcfrs_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+ return mcfrs_getsignals(info);
+}
+
+static int mcfrs_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
+ int rts = -1, dtr = -1;
+
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+ if (set & TIOCM_RTS)
+ rts = 1;
+ if (set & TIOCM_DTR)
+ dtr = 1;
+ if (clear & TIOCM_RTS)
+ rts = 0;
+ if (clear & TIOCM_DTR)
+ dtr = 0;
+
+ mcfrs_setsignals(info, dtr, rts);
+
+ return 0;
+}
+
static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
unsigned int val;
int retval, error;
- int dtr, rts;

if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
return -ENODEV;
@@ -1059,45 +1095,6 @@
info, sizeof(struct mcf_serial));
return 0;

- case TIOCMGET:
- if ((error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))))
- return(error);
- val = mcfrs_getsignals(info);
- put_user(val, (unsigned int *) arg);
- break;
-
- case TIOCMBIS:
- if ((error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))))
- return(error);
-
- get_user(val, (unsigned int *) arg);
- rts = (val & TIOCM_RTS) ? 1 : -1;
- dtr = (val & TIOCM_DTR) ? 1 : -1;
- mcfrs_setsignals(info, dtr, rts);
- break;
-
- case TIOCMBIC:
- if ((error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))))
- return(error);
- get_user(val, (unsigned int *) arg);
- rts = (val & TIOCM_RTS) ? 0 : -1;
- dtr = (val & TIOCM_DTR) ? 0 : -1;
- mcfrs_setsignals(info, dtr, rts);
- break;
-
- case TIOCMSET:
- if ((error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))))
- return(error);
- get_user(val, (unsigned int *) arg);
- rts = (val & TIOCM_RTS) ? 1 : 0;
- dtr = (val & TIOCM_DTR) ? 1 : 0;
- mcfrs_setsignals(info, dtr, rts);
- break;
-
#ifdef TIOCSET422
case TIOCSET422:
get_user(val, (unsigned int *) arg);
@@ -1563,6 +1560,8 @@
.start = mcfrs_start,
.hangup = mcfrs_hangup,
.read_proc = mcfrs_readproc,
+ .tiocmget = mcfrs_tiocmget,
+ .tiocmset = mcfrs_tiocmset,
};

/* mcfrs_init inits the driver */


--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-18 16:16:45

by Russell King

[permalink] [raw]
Subject: Re: [3/3] 2.6 broken serial drivers

On Tue, Jan 13, 2004 at 09:10:23PM +0000, Russell King wrote:
> On Tue, Jan 13, 2004 at 12:21:15PM -0800, Andrew Morton wrote:
> > Russell King <[email protected]> wrote:
> > >
> > > --- 1.14/drivers/net/wan/pc300_tty.c Thu Sep 11 18:40:53 2003
> > > +++ edited/drivers/net/wan/pc300_tty.c Tue Jan 13 14:42:34 2004
> > > @@ -583,6 +583,14 @@
> > > CPC_TTY_DBG("%s: IOCTL cmd %x\n",cpc_tty->name,cmd);
> > >
> > > switch (cmd) {
> > > +#error This is broken. See comments.
> >
> > Grumble. This breaks allmodconfig. #warning, please.
>
> Probably far better to make all these drivers depend on BROKEN unless
> one of the authors speaks up.

Ok, no one spoke, so here's the patch to mark this driver broken:

===== drivers/net/wan/Kconfig 1.16 vs edited =====
--- 1.16/drivers/net/wan/Kconfig Tue Dec 30 08:45:02 2003
+++ edited/drivers/net/wan/Kconfig Sun Jan 18 16:15:19 2004
@@ -367,7 +367,7 @@

config PC300_MLPPP
bool "Cyclades-PC300 MLPPP support"
- depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP
+ depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP && BROKEN
help
Say 'Y' to this option if you are planning to use Multilink PPP over the
PC300 synchronous communication boards.


--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-01-18 23:23:57

by Greg Ungerer

[permalink] [raw]
Subject: Re: [2/3]

Hi Russel,

Russell King wrote:
> On Sun, Jan 18, 2004 at 10:43:01PM +1000, Greg Ungerer wrote:
>>Looks good for mcfserial.c. The only additional change I would
>>make is to remove the "rts", "dtr", and "val" variables from the
>>ioctl function - removing the TIOCM* cases means these variables
>>are no longer used.
>
>
> I agree for "rts" and "dtr", however "val" is still used - in
> TIOC[SG]ET422. Here's a new patch for mcfserial.c

Oops, your right. This new patch looks good.

Regards
Greg



> ===== drivers/serial/mcfserial.c 1.17 vs edited =====
> --- 1.17/drivers/serial/mcfserial.c Thu Jul 3 02:18:07 2003
> +++ edited/drivers/serial/mcfserial.c Sun Jan 18 15:40:39 2004
> @@ -985,13 +985,49 @@
> local_irq_restore(flags);
> }
>
> +static int mcfrs_tiocmget(struct tty_struct *tty, struct file *file)
> +{
> + struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
> +
> + if (serial_paranoia_check(info, tty->name, __FUNCTION__))
> + return -ENODEV;
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return -EIO;
> +
> + return mcfrs_getsignals(info);
> +}
> +
> +static int mcfrs_tiocmset(struct tty_struct *tty, struct file *file,
> + unsigned int set, unsigned int clear)
> +{
> + struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
> + int rts = -1, dtr = -1;
> +
> + if (serial_paranoia_check(info, tty->name, __FUNCTION__))
> + return -ENODEV;
> + if (tty->flags & (1 << TTY_IO_ERROR))
> + return -EIO;
> +
> + if (set & TIOCM_RTS)
> + rts = 1;
> + if (set & TIOCM_DTR)
> + dtr = 1;
> + if (clear & TIOCM_RTS)
> + rts = 0;
> + if (clear & TIOCM_DTR)
> + dtr = 0;
> +
> + mcfrs_setsignals(info, dtr, rts);
> +
> + return 0;
> +}
> +
> static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
> unsigned int cmd, unsigned long arg)
> {
> struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
> unsigned int val;
> int retval, error;
> - int dtr, rts;
>
> if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
> return -ENODEV;
> @@ -1059,45 +1095,6 @@
> info, sizeof(struct mcf_serial));
> return 0;
>
> - case TIOCMGET:
> - if ((error = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))))
> - return(error);
> - val = mcfrs_getsignals(info);
> - put_user(val, (unsigned int *) arg);
> - break;
> -
> - case TIOCMBIS:
> - if ((error = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))))
> - return(error);
> -
> - get_user(val, (unsigned int *) arg);
> - rts = (val & TIOCM_RTS) ? 1 : -1;
> - dtr = (val & TIOCM_DTR) ? 1 : -1;
> - mcfrs_setsignals(info, dtr, rts);
> - break;
> -
> - case TIOCMBIC:
> - if ((error = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))))
> - return(error);
> - get_user(val, (unsigned int *) arg);
> - rts = (val & TIOCM_RTS) ? 0 : -1;
> - dtr = (val & TIOCM_DTR) ? 0 : -1;
> - mcfrs_setsignals(info, dtr, rts);
> - break;
> -
> - case TIOCMSET:
> - if ((error = verify_area(VERIFY_WRITE, (void *) arg,
> - sizeof(unsigned int))))
> - return(error);
> - get_user(val, (unsigned int *) arg);
> - rts = (val & TIOCM_RTS) ? 1 : 0;
> - dtr = (val & TIOCM_DTR) ? 1 : 0;
> - mcfrs_setsignals(info, dtr, rts);
> - break;
> -
> #ifdef TIOCSET422
> case TIOCSET422:
> get_user(val, (unsigned int *) arg);
> @@ -1563,6 +1560,8 @@
> .start = mcfrs_start,
> .hangup = mcfrs_hangup,
> .read_proc = mcfrs_readproc,
> + .tiocmget = mcfrs_tiocmget,
> + .tiocmset = mcfrs_tiocmset,
> };
>
> /* mcfrs_init inits the driver */
>
>

--
------------------------------------------------------------------------
Greg Ungerer -- Chief Software Dude EMAIL: [email protected]
SnapGear -- a CyberGuard Company PHONE: +61 7 3435 2888
825 Stanley St, FAX: +61 7 3891 3630
Woolloongabba, QLD, 4102, Australia WEB: http://www.SnapGear.com

2004-01-24 06:13:28

by Karl Tatgenhorst

[permalink] [raw]
Subject: [lkml] pseudo tty / kernel compile question

Hi,

I have read the FAQ and have searched heartily for anything which I
could understand about this, but have come up empty. I am replacing a
Unixware 7.1.1 server (not a unixware question) with RH ES3. The server
hosts a BASIC application so users log in via ssh sessions. The problem
is I am getting to around 120 users and then getting a no pseudo ttys
available. RH support had me bump up the number of instances in
xinetd.conf which did nothing. Then a person we use for Unix support
said that the type of pseudo ttys that we use is wrong. His example:

when I log in over ssh I get /dev/pts/0 when I type tty. But he says it
should be of type /dev/ptsp* I know (suspect strongly) that this is
configured in the kernel but not where. Can anyone please post a little
information for me regarding this.

I heartily welcome your assistance in smiting this unixware servers job.

Karl Tatgenhorst

PS if it is not too much further trouble, please CC any responses to
[email protected]

Thanks one and all

2004-01-25 21:57:08

by David Woodhouse

[permalink] [raw]
Subject: Re: [lkml] pseudo tty / kernel compile question

This has nothing to do with the patch fixing serial drivers, to which
you seem to have replied. Please don't reply to random messages -- if
you mean to starting a new thread then do so properly.

On Sat, 2004-01-24 at 00:16 -0600, Karl Tatgenhorst wrote:
> when I log in over ssh I get /dev/pts/0 when I type tty. But he says it
> should be of type /dev/ptsp* I know (suspect strongly) that this is
> configured in the kernel but not where.

Whether you use the new type of pseudo-ttys /dev/pts/XX or whether you
use the old ones is dependent on your user space programs. You should be
using /dev/pts/XX. If you _are_, then the number of available
pseudo-ttys is indeed part of the kernel configuration. It's
CONFIG_UNIX98_PTY_COUNT.

--
dwmw2