Commit fcc8ac18 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

tty: Add carrier processing on close to the tty_port core

Some drivers implement this internally, others miss it out. Push the
behaviour into the core code as that way everyone will do it consistently.

Update the dtr rts method to raise or lower depending upon flags. Having a
single method in this style fits most of the implementations more cleanly than
two funtions.

We need this in place before we tackle the USB side
Signed-off-by: default avatarAlan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 65a29f60
...@@ -745,7 +745,7 @@ static int epca_carrier_raised(struct tty_port *port) ...@@ -745,7 +745,7 @@ static int epca_carrier_raised(struct tty_port *port)
return 0; return 0;
} }
static void epca_raise_dtr_rts(struct tty_port *port) static void epca_dtr_rts(struct tty_port *port, int onoff)
{ {
} }
...@@ -925,7 +925,7 @@ static const struct tty_operations pc_ops = { ...@@ -925,7 +925,7 @@ static const struct tty_operations pc_ops = {
static const struct tty_port_operations epca_port_ops = { static const struct tty_port_operations epca_port_ops = {
.carrier_raised = epca_carrier_raised, .carrier_raised = epca_carrier_raised,
.raise_dtr_rts = epca_raise_dtr_rts, .dtr_rts = epca_dtr_rts,
}; };
static int info_open(struct tty_struct *tty, struct file *filp) static int info_open(struct tty_struct *tty, struct file *filp)
......
...@@ -329,7 +329,7 @@ static inline void drop_rts(struct isi_port *port) ...@@ -329,7 +329,7 @@ static inline void drop_rts(struct isi_port *port)
/* card->lock MUST NOT be held */ /* card->lock MUST NOT be held */
static void isicom_raise_dtr_rts(struct tty_port *port) static void isicom_dtr_rts(struct tty_port *port, int on)
{ {
struct isi_port *ip = container_of(port, struct isi_port, port); struct isi_port *ip = container_of(port, struct isi_port, port);
struct isi_board *card = ip->card; struct isi_board *card = ip->card;
...@@ -339,10 +339,17 @@ static void isicom_raise_dtr_rts(struct tty_port *port) ...@@ -339,10 +339,17 @@ static void isicom_raise_dtr_rts(struct tty_port *port)
if (!lock_card(card)) if (!lock_card(card))
return; return;
outw(0x8000 | (channel << card->shift_count) | 0x02, base); if (on) {
outw(0x0f04, base); outw(0x8000 | (channel << card->shift_count) | 0x02, base);
InterruptTheCard(base); outw(0x0f04, base);
ip->status |= (ISI_DTR | ISI_RTS); InterruptTheCard(base);
ip->status |= (ISI_DTR | ISI_RTS);
} else {
outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0C04, base);
InterruptTheCard(base);
ip->status &= ~(ISI_DTR | ISI_RTS);
}
unlock_card(card); unlock_card(card);
} }
...@@ -1339,7 +1346,7 @@ static const struct tty_operations isicom_ops = { ...@@ -1339,7 +1346,7 @@ static const struct tty_operations isicom_ops = {
static const struct tty_port_operations isicom_port_ops = { static const struct tty_port_operations isicom_port_ops = {
.carrier_raised = isicom_carrier_raised, .carrier_raised = isicom_carrier_raised,
.raise_dtr_rts = isicom_raise_dtr_rts, .dtr_rts = isicom_dtr_rts,
}; };
static int __devinit reset_card(struct pci_dev *pdev, static int __devinit reset_card(struct pci_dev *pdev,
......
...@@ -1140,14 +1140,14 @@ static int stli_carrier_raised(struct tty_port *port) ...@@ -1140,14 +1140,14 @@ static int stli_carrier_raised(struct tty_port *port)
return (portp->sigs & TIOCM_CD) ? 1 : 0; return (portp->sigs & TIOCM_CD) ? 1 : 0;
} }
static void stli_raise_dtr_rts(struct tty_port *port) static void stli_dtr_rts(struct tty_port *port, int on)
{ {
struct stliport *portp = container_of(port, struct stliport, port); struct stliport *portp = container_of(port, struct stliport, port);
struct stlibrd *brdp = stli_brds[portp->brdnr]; struct stlibrd *brdp = stli_brds[portp->brdnr];
stli_mkasysigs(&portp->asig, 1, 1); stli_mkasysigs(&portp->asig, on, on);
if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
sizeof(asysigs_t), 0) < 0) sizeof(asysigs_t), 0) < 0)
printk(KERN_WARNING "istallion: dtr raise failed.\n"); printk(KERN_WARNING "istallion: dtr set failed.\n");
} }
...@@ -4417,7 +4417,7 @@ static const struct tty_operations stli_ops = { ...@@ -4417,7 +4417,7 @@ static const struct tty_operations stli_ops = {
static const struct tty_port_operations stli_port_ops = { static const struct tty_port_operations stli_port_ops = {
.carrier_raised = stli_carrier_raised, .carrier_raised = stli_carrier_raised,
.raise_dtr_rts = stli_raise_dtr_rts, .dtr_rts = stli_dtr_rts,
}; };
/*****************************************************************************/ /*****************************************************************************/
......
...@@ -547,14 +547,18 @@ static int mxser_carrier_raised(struct tty_port *port) ...@@ -547,14 +547,18 @@ static int mxser_carrier_raised(struct tty_port *port)
return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0; return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
} }
static void mxser_raise_dtr_rts(struct tty_port *port) static void mxser_dtr_rts(struct tty_port *port, int on)
{ {
struct mxser_port *mp = container_of(port, struct mxser_port, port); struct mxser_port *mp = container_of(port, struct mxser_port, port);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&mp->slock, flags); spin_lock_irqsave(&mp->slock, flags);
outb(inb(mp->ioaddr + UART_MCR) | if (on)
UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR); outb(inb(mp->ioaddr + UART_MCR) |
UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
else
outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS),
mp->ioaddr + UART_MCR);
spin_unlock_irqrestore(&mp->slock, flags); spin_unlock_irqrestore(&mp->slock, flags);
} }
...@@ -2356,7 +2360,7 @@ static const struct tty_operations mxser_ops = { ...@@ -2356,7 +2360,7 @@ static const struct tty_operations mxser_ops = {
struct tty_port_operations mxser_port_ops = { struct tty_port_operations mxser_port_ops = {
.carrier_raised = mxser_carrier_raised, .carrier_raised = mxser_carrier_raised,
.raise_dtr_rts = mxser_raise_dtr_rts, .dtr_rts = mxser_dtr_rts,
}; };
/* /*
......
...@@ -383,7 +383,7 @@ static void async_mode(MGSLPC_INFO *info); ...@@ -383,7 +383,7 @@ static void async_mode(MGSLPC_INFO *info);
static void tx_timeout(unsigned long context); static void tx_timeout(unsigned long context);
static int carrier_raised(struct tty_port *port); static int carrier_raised(struct tty_port *port);
static void raise_dtr_rts(struct tty_port *port); static void dtr_rts(struct tty_port *port, int onoff);
#if SYNCLINK_GENERIC_HDLC #if SYNCLINK_GENERIC_HDLC
#define dev_to_port(D) (dev_to_hdlc(D)->priv) #define dev_to_port(D) (dev_to_hdlc(D)->priv)
...@@ -513,7 +513,7 @@ static void ldisc_receive_buf(struct tty_struct *tty, ...@@ -513,7 +513,7 @@ static void ldisc_receive_buf(struct tty_struct *tty,
static const struct tty_port_operations mgslpc_port_ops = { static const struct tty_port_operations mgslpc_port_ops = {
.carrier_raised = carrier_raised, .carrier_raised = carrier_raised,
.raise_dtr_rts = raise_dtr_rts .dtr_rts = dtr_rts
}; };
static int mgslpc_probe(struct pcmcia_device *link) static int mgslpc_probe(struct pcmcia_device *link)
...@@ -2528,13 +2528,16 @@ static int carrier_raised(struct tty_port *port) ...@@ -2528,13 +2528,16 @@ static int carrier_raised(struct tty_port *port)
return 0; return 0;
} }
static void raise_dtr_rts(struct tty_port *port) static void dtr_rts(struct tty_port *port, int onoff)
{ {
MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&info->lock,flags); spin_lock_irqsave(&info->lock,flags);
info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; if (onoff)
info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
else
info->serial_signals &= ~SerialSignal_RTS + SerialSignal_DTR;
set_signals(info); set_signals(info);
spin_unlock_irqrestore(&info->lock,flags); spin_unlock_irqrestore(&info->lock,flags);
} }
......
...@@ -872,11 +872,16 @@ static int carrier_raised(struct tty_port *port) ...@@ -872,11 +872,16 @@ static int carrier_raised(struct tty_port *port)
return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0; return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0;
} }
static void raise_dtr_rts(struct tty_port *port) static void dtr_rts(struct tty_port *port, int on)
{ {
struct r_port *info = container_of(port, struct r_port, port); struct r_port *info = container_of(port, struct r_port, port);
sSetDTR(&info->channel); if (on) {
sSetRTS(&info->channel); sSetDTR(&info->channel);
sSetRTS(&info->channel);
} else {
sClrDTR(&info->channel);
sClrRTS(&info->channel);
}
} }
/* /*
...@@ -2250,7 +2255,7 @@ static const struct tty_operations rocket_ops = { ...@@ -2250,7 +2255,7 @@ static const struct tty_operations rocket_ops = {
static const struct tty_port_operations rocket_port_ops = { static const struct tty_port_operations rocket_port_ops = {
.carrier_raised = carrier_raised, .carrier_raised = carrier_raised,
.raise_dtr_rts = raise_dtr_rts, .dtr_rts = dtr_rts,
}; };
/* /*
......
...@@ -772,11 +772,11 @@ static int stl_carrier_raised(struct tty_port *port) ...@@ -772,11 +772,11 @@ static int stl_carrier_raised(struct tty_port *port)
return (portp->sigs & TIOCM_CD) ? 1 : 0; return (portp->sigs & TIOCM_CD) ? 1 : 0;
} }
static void stl_raise_dtr_rts(struct tty_port *port) static void stl_dtr_rts(struct tty_port *port, int on)
{ {
struct stlport *portp = container_of(port, struct stlport, port); struct stlport *portp = container_of(port, struct stlport, port);
/* Takes brd_lock internally */ /* Takes brd_lock internally */
stl_setsignals(portp, 1, 1); stl_setsignals(portp, on, on);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -2547,7 +2547,7 @@ static const struct tty_operations stl_ops = { ...@@ -2547,7 +2547,7 @@ static const struct tty_operations stl_ops = {
static const struct tty_port_operations stl_port_ops = { static const struct tty_port_operations stl_port_ops = {
.carrier_raised = stl_carrier_raised, .carrier_raised = stl_carrier_raised,
.raise_dtr_rts = stl_raise_dtr_rts, .dtr_rts = stl_dtr_rts,
}; };
/*****************************************************************************/ /*****************************************************************************/
......
...@@ -3247,13 +3247,16 @@ static int carrier_raised(struct tty_port *port) ...@@ -3247,13 +3247,16 @@ static int carrier_raised(struct tty_port *port)
return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
} }
static void raise_dtr_rts(struct tty_port *port) static void dtr_rts(struct tty_port *port, int on)
{ {
struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&info->irq_spinlock,flags); spin_lock_irqsave(&info->irq_spinlock,flags);
info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; if (on)
info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
else
info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
usc_set_serial_signals(info); usc_set_serial_signals(info);
spin_unlock_irqrestore(&info->irq_spinlock,flags); spin_unlock_irqrestore(&info->irq_spinlock,flags);
} }
...@@ -4258,7 +4261,7 @@ static void mgsl_add_device( struct mgsl_struct *info ) ...@@ -4258,7 +4261,7 @@ static void mgsl_add_device( struct mgsl_struct *info )
static const struct tty_port_operations mgsl_port_ops = { static const struct tty_port_operations mgsl_port_ops = {
.carrier_raised = carrier_raised, .carrier_raised = carrier_raised,
.raise_dtr_rts = raise_dtr_rts, .dtr_rts = dtr_rts,
}; };
......
...@@ -3099,13 +3099,16 @@ static int carrier_raised(struct tty_port *port) ...@@ -3099,13 +3099,16 @@ static int carrier_raised(struct tty_port *port)
return (info->signals & SerialSignal_DCD) ? 1 : 0; return (info->signals & SerialSignal_DCD) ? 1 : 0;
} }
static void raise_dtr_rts(struct tty_port *port) static void dtr_rts(struct tty_port *port, int on)
{ {
unsigned long flags; unsigned long flags;
struct slgt_info *info = container_of(port, struct slgt_info, port); struct slgt_info *info = container_of(port, struct slgt_info, port);
spin_lock_irqsave(&info->lock,flags); spin_lock_irqsave(&info->lock,flags);
info->signals |= SerialSignal_RTS + SerialSignal_DTR; if (on)
info->signals |= SerialSignal_RTS + SerialSignal_DTR;
else
info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
set_signals(info); set_signals(info);
spin_unlock_irqrestore(&info->lock,flags); spin_unlock_irqrestore(&info->lock,flags);
} }
...@@ -3419,7 +3422,7 @@ static void add_device(struct slgt_info *info) ...@@ -3419,7 +3422,7 @@ static void add_device(struct slgt_info *info)
static const struct tty_port_operations slgt_port_ops = { static const struct tty_port_operations slgt_port_ops = {
.carrier_raised = carrier_raised, .carrier_raised = carrier_raised,
.raise_dtr_rts = raise_dtr_rts, .dtr_rts = dtr_rts,
}; };
/* /*
......
...@@ -3277,13 +3277,16 @@ static int carrier_raised(struct tty_port *port) ...@@ -3277,13 +3277,16 @@ static int carrier_raised(struct tty_port *port)
return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
} }
static void raise_dtr_rts(struct tty_port *port) static void dtr_rts(struct tty_port *port, int on)
{ {
SLMP_INFO *info = container_of(port, SLMP_INFO, port); SLMP_INFO *info = container_of(port, SLMP_INFO, port);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&info->lock,flags); spin_lock_irqsave(&info->lock,flags);
info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; if (on)
info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
else
info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
set_signals(info); set_signals(info);
spin_unlock_irqrestore(&info->lock,flags); spin_unlock_irqrestore(&info->lock,flags);
} }
...@@ -3746,7 +3749,7 @@ static void add_device(SLMP_INFO *info) ...@@ -3746,7 +3749,7 @@ static void add_device(SLMP_INFO *info)
static const struct tty_port_operations port_ops = { static const struct tty_port_operations port_ops = {
.carrier_raised = carrier_raised, .carrier_raised = carrier_raised,
.raise_dtr_rts = raise_dtr_rts, .dtr_rts = dtr_rts,
}; };
/* Allocate and initialize a device instance structure /* Allocate and initialize a device instance structure
......
...@@ -137,7 +137,7 @@ int tty_port_carrier_raised(struct tty_port *port) ...@@ -137,7 +137,7 @@ int tty_port_carrier_raised(struct tty_port *port)
EXPORT_SYMBOL(tty_port_carrier_raised); EXPORT_SYMBOL(tty_port_carrier_raised);
/** /**
* tty_port_raise_dtr_rts - Riase DTR/RTS * tty_port_raise_dtr_rts - Raise DTR/RTS
* @port: tty port * @port: tty port
* *
* Wrapper for the DTR/RTS raise logic. For the moment this is used * Wrapper for the DTR/RTS raise logic. For the moment this is used
...@@ -147,11 +147,27 @@ EXPORT_SYMBOL(tty_port_carrier_raised); ...@@ -147,11 +147,27 @@ EXPORT_SYMBOL(tty_port_carrier_raised);
void tty_port_raise_dtr_rts(struct tty_port *port) void tty_port_raise_dtr_rts(struct tty_port *port)
{ {
if (port->ops->raise_dtr_rts) if (port->ops->dtr_rts)
port->ops->raise_dtr_rts(port); port->ops->dtr_rts(port, 1);
} }
EXPORT_SYMBOL(tty_port_raise_dtr_rts); EXPORT_SYMBOL(tty_port_raise_dtr_rts);
/**
* tty_port_lower_dtr_rts - Lower DTR/RTS
* @port: tty port
*
* Wrapper for the DTR/RTS raise logic. For the moment this is used
* to hide some internal details. This will eventually become entirely
* internal to the tty port.
*/
void tty_port_lower_dtr_rts(struct tty_port *port)
{
if (port->ops->dtr_rts)
port->ops->dtr_rts(port, 0);
}
EXPORT_SYMBOL(tty_port_lower_dtr_rts);
/** /**
* tty_port_block_til_ready - Waiting logic for tty open * tty_port_block_til_ready - Waiting logic for tty open
* @port: the tty port being opened * @port: the tty port being opened
...@@ -167,7 +183,7 @@ EXPORT_SYMBOL(tty_port_raise_dtr_rts); ...@@ -167,7 +183,7 @@ EXPORT_SYMBOL(tty_port_raise_dtr_rts);
* - port flags and counts * - port flags and counts
* *
* The passed tty_port must implement the carrier_raised method if it can * The passed tty_port must implement the carrier_raised method if it can
* do carrier detect and the raise_dtr_rts method if it supports software * do carrier detect and the dtr_rts method if it supports software
* management of these lines. Note that the dtr/rts raise is done each * management of these lines. Note that the dtr/rts raise is done each
* iteration as a hangup may have previously dropped them while we wait. * iteration as a hangup may have previously dropped them while we wait.
*/ */
...@@ -302,6 +318,9 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) ...@@ -302,6 +318,9 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
tty_ldisc_flush(tty); tty_ldisc_flush(tty);
if (tty->termios->c_cflag & HUPCL)
tty_port_lower_dtr_rts(port);
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
tty->closing = 0; tty->closing = 0;
......
...@@ -185,7 +185,7 @@ struct tty_port; ...@@ -185,7 +185,7 @@ struct tty_port;
struct tty_port_operations { struct tty_port_operations {
/* Return 1 if the carrier is raised */ /* Return 1 if the carrier is raised */
int (*carrier_raised)(struct tty_port *port); int (*carrier_raised)(struct tty_port *port);
void (*raise_dtr_rts)(struct tty_port *port); void (*dtr_rts)(struct tty_port *port, int raise);
}; };
struct tty_port { struct tty_port {
...@@ -438,6 +438,7 @@ extern struct tty_struct *tty_port_tty_get(struct tty_port *port); ...@@ -438,6 +438,7 @@ extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
extern int tty_port_carrier_raised(struct tty_port *port); extern int tty_port_carrier_raised(struct tty_port *port);
extern void tty_port_raise_dtr_rts(struct tty_port *port); extern void tty_port_raise_dtr_rts(struct tty_port *port);
extern void tty_port_lower_dtr_rts(struct tty_port *port);
extern void tty_port_hangup(struct tty_port *port); extern void tty_port_hangup(struct tty_port *port);
extern int tty_port_block_til_ready(struct tty_port *port, extern int tty_port_block_til_ready(struct tty_port *port,
struct tty_struct *tty, struct file *filp); struct tty_struct *tty, struct file *filp);
......
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