Commit 258b92e8 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] serial fixups

From: Russell King <rmk@arm.linux.org.uk>

Convert a bunch of serial drivers to new-style ioctl handling.
parent 84557b40
......@@ -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]<<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 +3744,8 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
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 +3754,8 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
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 +3770,8 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
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 +3787,6 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
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 +3800,19 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
board_ctrl = &zfw_ctrl->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
......
......@@ -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++ );
......
......@@ -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,
};
/*****************************************************************************/
......
......@@ -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) {
......
......@@ -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;
......
......@@ -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,
};
/* ********************************************************************** *
......
......@@ -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,
};
/*****************************************************************************/
......
......@@ -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)
......
......@@ -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)
......
......@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment