From 258b92e84db6285fc83d6fef3af8fc93f7c0a916 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 22 Feb 2004 07:00:27 -0800 Subject: [PATCH] [PATCH] serial fixups From: Russell King Convert a bunch of serial drivers to new-style ioctl handling. --- drivers/char/cyclades.c | 158 ++++++--------------------- drivers/char/ip2main.c | 196 ++++++++++++++-------------------- drivers/char/istallion.c | 94 +++++++++------- drivers/char/rio/rio_linux.c | 5 + drivers/char/rocket.c | 59 ---------- drivers/char/sh-sci.c | 47 ++++---- drivers/char/stallion.c | 75 +++++++------ drivers/char/sx.c | 56 +++++----- drivers/macintosh/macserial.c | 72 ++++++++----- drivers/serial/mcfserial.c | 81 +++++++------- 10 files changed, 355 insertions(+), 488 deletions(-) diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 6dcdf81dba8eb..1bb2458e5fcc6 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -3632,8 +3632,9 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int *value) } 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 @@ get_modem_info(struct cyclades_port * info, unsigned int *value) 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,24 +3704,27 @@ get_modem_info(struct cyclades_port * info, unsigned int *value) } } - 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; - unsigned int arg = cy_get_user((unsigned long *) value); struct FIRM_ID *firm_id; struct ZFW_CTRL *zfw_ctrl; struct BOARD_CTRL *board_ctrl; 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 +3735,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd, (cy_card[card].base_addr + (cy_chip_offset[chip]<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { @@ -3796,7 +3744,8 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd, cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { @@ -3805,8 +3754,8 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd, cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { @@ -3821,7 +3770,8 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd, cy_readb(base_addr+(CyMSVR2<rtsdtr_inv) { @@ -3837,10 +3787,6 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd, cy_readb(base_addr+(CyMSVR2<board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; - switch (cmd) { - case TIOCMBIS: - 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); - } - 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){ - 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 +3820,8 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd, 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 +3829,6 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd, printk("cyc:set_modem_info clearing Z DTR\n"); #endif CY_UNLOCK(info, flags); - } - break; - default: - return -EINVAL; } }else{ return -ENODEV; @@ -3935,7 +3843,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd, CY_UNLOCK(info, flags); } return 0; -} /* set_modem_info */ +} /* cy_tiocmset */ /* * cy_break() --- routine which turns the break handling on or off @@ -4242,14 +4150,6 @@ cy_ioctl(struct tty_struct *tty, struct file * file, 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 +5329,8 @@ static struct tty_operations cy_ops = { .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 diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c index 9008a4bfe72f4..043cff46fb74a 100644 --- a/drivers/char/ip2main.c +++ b/drivers/char/ip2main.c @@ -186,6 +186,9 @@ static void ip2_unthrottle(PTTY); 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 @@ static struct tty_operations ip2_ops = { .start = ip2_start, .hangup = ip2_hangup, .read_proc = ip2_read_proc, + .tiocmget = ip2_tiocmget, + .tiocmset = ip2_tiocmset, }; /******************************************************************************/ @@ -1951,6 +1956,80 @@ ip2_stop ( PTTY tty ) /* 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 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) 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 @@ -2238,70 +2266,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) return rc; } -/******************************************************************************/ -/* 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 */ @@ -2964,7 +2928,7 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) 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++ ); diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 36866d2e6f782..a876f6d150907 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -1991,6 +1991,61 @@ static int stli_setserial(stliport_t *portp, struct serial_struct *sp) /*****************************************************************************/ +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; @@ -2034,43 +2089,6 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm (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) @@ -5255,6 +5273,8 @@ static struct tty_operations stli_ops = { .wait_until_sent = stli_waituntilsent, .send_xchar = stli_sendxchar, .read_proc = stli_readproc, + .tiocmget = stli_tiocmget, + .tiocmset = stli_tiocmset, }; /*****************************************************************************/ diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 4cab601b962f1..a11fafbab820f 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -728,6 +728,11 @@ static int rio_ioctl (struct tty_struct * tty, struct file * filp, 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) { diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 843c4b5f8bd8f..38544de9fbd9f 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1216,59 +1216,6 @@ static int sGetChanRI(CHANNEL_T * ChP) /********************************************************************************************/ /* 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 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, 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; diff --git a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c index 378e3d53d3b76..d3894a6f9cd68 100644 --- a/drivers/char/sh-sci.c +++ b/drivers/char/sh-sci.c @@ -1109,6 +1109,31 @@ static void sci_close(void *ptr) return; } +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) { @@ -1139,26 +1164,6 @@ static int sci_ioctl(struct tty_struct * tty, struct file * filp, rc = gs_setserial(&port->gs, (struct serial_struct *) arg); break; - case TIOCMGET: - ival = sci_getsignals(port); - rc = put_user(ival, (unsigned int __user *) arg); - break; - case TIOCMBIS: - if ((rc = get_user(ival, (unsigned int __user *) 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 __user *) 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 __user *)arg)) == 0) - sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), - ((ival & TIOCM_RTS) ? 1 : 0)); - break; - default: rc = -ENOIOCTLCMD; break; @@ -1272,6 +1277,8 @@ static struct tty_operations sci_ops = { #ifdef CONFIG_PROC_FS .read_proc = sci_read_proc, #endif + .tiocmget = sci_tiocmget, + .tiocmset = sci_tiocmset, }; /* ********************************************************************** * diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index a1f6f069064a3..c0095a67bf5b1 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -1514,6 +1514,48 @@ static int stl_setserial(stlport_t *portp, struct serial_struct *sp) /*****************************************************************************/ +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 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd (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 @@ static struct tty_operations stl_ops = { .wait_until_sent = stl_waituntilsent, .send_xchar = stl_sendxchar, .read_proc = stl_readproc, + .tiocmget = stl_tiocmget, + .tiocmset = stl_tiocmset, }; /*****************************************************************************/ diff --git a/drivers/char/sx.c b/drivers/char/sx.c index f414def6b93ea..25c95fbc65d3a 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -1743,6 +1743,32 @@ static void sx_break (struct tty_struct * tty, int flag) } +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, 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; + + 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 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp, 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 @@ static struct tty_operations sx_ops = { .stop = gs_stop, .start = gs_start, .hangup = gs_hangup, + .tiocmget = sx_tiocmget, + .tiocmset = sx_tiocmset, }; static int sx_init_drivers(void) diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c index 9d6eb9890b620..d5dd056d3196f 100644 --- a/drivers/macintosh/macserial.c +++ b/drivers/macintosh/macserial.c @@ -1777,47 +1777,65 @@ static int get_lsr_info(struct mac_serial * info, unsigned int *value) 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 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, } 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 @@ static struct tty_operations serial_ops = { .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) diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index c6b7caa224dff..866976b585e50 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -985,13 +985,51 @@ static void send_break( struct mcf_serial * info, int duration) 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) { struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; +#ifdef TIOCSET422 unsigned int val; +#endif int retval, error; - int dtr, rts; if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) return -ENODEV; @@ -1059,45 +1097,6 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file, 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 +1562,8 @@ static struct tty_operations mcfrs_ops = { .start = mcfrs_start, .hangup = mcfrs_hangup, .read_proc = mcfrs_readproc, + .tiocmget = mcfrs_tiocmget, + .tiocmset = mcfrs_tiocmset, }; /* mcfrs_init inits the driver */ -- 2.53.0