public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Russell King <rmk+lkml@arm.linux.org.uk>
To: linux-kernel@vger.kernel.org, henrique.gobbi@cyclades.com,
	support@stallion.oz.au, R.E.Wolff@BitWizard.nl, paulus@samba.org,
	elfert@de.ibm.com, felfert@millenux.com, gerg@snapgear.com,
	kuba@mareimbrium.org
Subject: [2/3]
Date: Tue, 13 Jan 2004 17:33:52 +0000	[thread overview]
Message-ID: <20040113173352.D7256@flint.arm.linux.org.uk> (raw)
In-Reply-To: <20040113171544.B7256@flint.arm.linux.org.uk>; from rmk+lkml@arm.linux.org.uk on Tue, Jan 13, 2004 at 05:15:45PM +0000

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

  parent reply	other threads:[~2004-01-13 17:36 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-01-13 11:00 [PROBLEM] ircomm ioctls Jozef Vesely
2004-01-13 11:36 ` Russell King
2004-01-13 11:49   ` Outstanding fixups (was: Re: [PROBLEM] ircomm ioctls) Russell King
2004-01-13 17:15     ` Russell King
2004-01-13 17:24       ` [1/3] Serial fixups (mostly tested) Russell King
2004-01-24  6:16         ` [lkml] pseudo tty / kernel compile question Karl Tatgenhorst
2004-01-25 21:53           ` David Woodhouse
2004-01-13 17:33       ` Russell King [this message]
2004-01-13 17:55         ` [2/3] Henrique Oliveira
2004-01-13 18:53           ` [2/3] John Stoffel
2004-01-13 22:15         ` [2/3] Paul Mackerras
2004-01-14  7:01           ` [2/3] Benjamin Herrenschmidt
2004-01-16 11:34             ` [2/3] Matthias Urlichs
2004-01-16  0:54         ` [2/3] Greg KH
2004-01-18 12:43         ` [2/3] Greg Ungerer
2004-01-18 15:42           ` [2/3] Russell King
2004-01-18 23:23             ` [2/3] Greg Ungerer
2004-01-13 17:42       ` [3/3] 2.6 broken serial drivers Russell King
2004-01-13 20:21         ` Andrew Morton
2004-01-13 21:10           ` Russell King
2004-01-18 16:16             ` Russell King
2004-01-14 12:42         ` Maciej W. Rozycki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040113173352.D7256@flint.arm.linux.org.uk \
    --to=rmk+lkml@arm.linux.org.uk \
    --cc=R.E.Wolff@BitWizard.nl \
    --cc=elfert@de.ibm.com \
    --cc=felfert@millenux.com \
    --cc=gerg@snapgear.com \
    --cc=henrique.gobbi@cyclades.com \
    --cc=kuba@mareimbrium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=paulus@samba.org \
    --cc=support@stallion.oz.au \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox