提交 31f35939 编写于 作者: A Alan Cox 提交者: Linus Torvalds

tty_port: Add a port level carrier detect operation

This is the first step to generalising the various pieces of waiting logic
duplicated in all sorts of serial drivers.
Signed-off-by: NAlan Cox <alan@redhat.com>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 c9b3976e
...@@ -2054,6 +2054,15 @@ static void esp_hangup(struct tty_struct *tty) ...@@ -2054,6 +2054,15 @@ static void esp_hangup(struct tty_struct *tty)
wake_up_interruptible(&info->port.open_wait); wake_up_interruptible(&info->port.open_wait);
} }
static int esp_carrier_raised(struct tty_port *port)
{
struct esp_struct *info = container_of(port, struct esp_struct, port);
serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD)
return 1;
return 0;
}
/* /*
* ------------------------------------------------------------ * ------------------------------------------------------------
* esp_open() and friends * esp_open() and friends
...@@ -2066,17 +2075,19 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -2066,17 +2075,19 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
int retval; int retval;
int do_clocal = 0; int do_clocal = 0;
unsigned long flags; unsigned long flags;
int cd;
struct tty_port *port = &info->port;
/* /*
* If the device is in the middle of being closed, then block * If the device is in the middle of being closed, then block
* until it's done, and then try again. * until it's done, and then try again.
*/ */
if (tty_hung_up_p(filp) || if (tty_hung_up_p(filp) ||
(info->port.flags & ASYNC_CLOSING)) { (port->flags & ASYNC_CLOSING)) {
if (info->port.flags & ASYNC_CLOSING) if (port->flags & ASYNC_CLOSING)
interruptible_sleep_on(&info->port.close_wait); interruptible_sleep_on(&port->close_wait);
#ifdef SERIAL_DO_RESTART #ifdef SERIAL_DO_RESTART
if (info->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN; return -EAGAIN;
else else
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -2091,7 +2102,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -2091,7 +2102,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
*/ */
if ((filp->f_flags & O_NONBLOCK) || if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) { (tty->flags & (1 << TTY_IO_ERROR))) {
info->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -2101,20 +2112,20 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -2101,20 +2112,20 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
/* /*
* Block waiting for the carrier detect and the line to become * Block waiting for the carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in * free (i.e., not in use by the callout). While we are in
* this loop, info->port.count is dropped by one, so that * this loop, port->count is dropped by one, so that
* rs_close() knows when to free things. We restore it upon * rs_close() knows when to free things. We restore it upon
* exit, either normal or abnormal. * exit, either normal or abnormal.
*/ */
retval = 0; retval = 0;
add_wait_queue(&info->port.open_wait, &wait); add_wait_queue(&port->open_wait, &wait);
#ifdef SERIAL_DEBUG_OPEN #ifdef SERIAL_DEBUG_OPEN
printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n", printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n",
info->line, info->port.count); info->line, port->count);
#endif #endif
spin_lock_irqsave(&info->lock, flags); spin_lock_irqsave(&info->lock, flags);
if (!tty_hung_up_p(filp)) if (!tty_hung_up_p(filp))
info->port.count--; port->count--;
info->port.blocked_open++; port->blocked_open++;
while (1) { while (1) {
if ((tty->termios->c_cflag & CBAUD)) { if ((tty->termios->c_cflag & CBAUD)) {
unsigned int scratch; unsigned int scratch;
...@@ -2129,9 +2140,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -2129,9 +2140,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
} }
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || if (tty_hung_up_p(filp) ||
!(info->port.flags & ASYNC_INITIALIZED)) { !(port->flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART #ifdef SERIAL_DO_RESTART
if (info->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN; retval = -EAGAIN;
else else
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
...@@ -2141,11 +2152,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -2141,11 +2152,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
break; break;
} }
serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); cd = tty_port_carrier_raised(port);
if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD)
do_clocal = 1;
if (!(info->port.flags & ASYNC_CLOSING) && if (!(port->flags & ASYNC_CLOSING) &&
(do_clocal)) (do_clocal))
break; break;
if (signal_pending(current)) { if (signal_pending(current)) {
...@@ -2154,25 +2163,25 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -2154,25 +2163,25 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
} }
#ifdef SERIAL_DEBUG_OPEN #ifdef SERIAL_DEBUG_OPEN
printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n", printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n",
info->line, info->port.count); info->line, port->count);
#endif #endif
spin_unlock_irqrestore(&info->lock, flags); spin_unlock_irqrestore(&info->lock, flags);
schedule(); schedule();
spin_lock_irqsave(&info->lock, flags); spin_lock_irqsave(&info->lock, flags);
} }
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&info->port.open_wait, &wait); remove_wait_queue(&port->open_wait, &wait);
if (!tty_hung_up_p(filp)) if (!tty_hung_up_p(filp))
info->port.count++; port->count++;
info->port.blocked_open--; port->blocked_open--;
spin_unlock_irqrestore(&info->lock, flags); spin_unlock_irqrestore(&info->lock, flags);
#ifdef SERIAL_DEBUG_OPEN #ifdef SERIAL_DEBUG_OPEN
printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n", printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n",
info->line, info->port.count); info->line, port->count);
#endif #endif
if (retval) if (retval)
return retval; return retval;
info->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -2329,6 +2338,10 @@ static const struct tty_operations esp_ops = { ...@@ -2329,6 +2338,10 @@ static const struct tty_operations esp_ops = {
.tiocmset = esp_tiocmset, .tiocmset = esp_tiocmset,
}; };
static const struct tty_port_operations esp_port_ops = {
.esp_carrier_raised,
};
/* /*
* The serial driver boot-time initialization code! * The serial driver boot-time initialization code!
*/ */
...@@ -2415,6 +2428,8 @@ static int __init espserial_init(void) ...@@ -2415,6 +2428,8 @@ static int __init espserial_init(void)
offset = 0; offset = 0;
do { do {
tty_port_init(&info->port);
info->port.ops = &esp_port_ops;
info->io_port = esp[i] + offset; info->io_port = esp[i] + offset;
info->irq = irq[i]; info->irq = irq[i];
info->line = (i * 8) + (offset / 8); info->line = (i * 8) + (offset / 8);
...@@ -2437,8 +2452,6 @@ static int __init espserial_init(void) ...@@ -2437,8 +2452,6 @@ static int __init espserial_init(void)
info->config.flow_off = flow_off; info->config.flow_off = flow_off;
info->config.pio_threshold = pio_threshold; info->config.pio_threshold = pio_threshold;
info->next_port = ports; info->next_port = ports;
init_waitqueue_head(&info->port.open_wait);
init_waitqueue_head(&info->port.close_wait);
init_waitqueue_head(&info->delta_msr_wait); init_waitqueue_head(&info->delta_msr_wait);
init_waitqueue_head(&info->break_wait); init_waitqueue_head(&info->break_wait);
ports = info; ports = info;
......
...@@ -397,7 +397,8 @@ void gs_hangup(struct tty_struct *tty) ...@@ -397,7 +397,8 @@ void gs_hangup(struct tty_struct *tty)
int gs_block_til_ready(void *port_, struct file * filp) int gs_block_til_ready(void *port_, struct file * filp)
{ {
struct gs_port *port = port_; struct gs_port *gp = port_;
struct tty_port *port = &gp->port;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int retval; int retval;
int do_clocal = 0; int do_clocal = 0;
...@@ -409,16 +410,16 @@ int gs_block_til_ready(void *port_, struct file * filp) ...@@ -409,16 +410,16 @@ int gs_block_til_ready(void *port_, struct file * filp)
if (!port) return 0; if (!port) return 0;
tty = port->port.tty; tty = port->tty;
gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n");
/* /*
* If the device is in the middle of being closed, then block * If the device is in the middle of being closed, then block
* until it's done, and then try again. * until it's done, and then try again.
*/ */
if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
interruptible_sleep_on(&port->port.close_wait); interruptible_sleep_on(&port->close_wait);
if (port->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN; return -EAGAIN;
else else
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -432,7 +433,7 @@ int gs_block_til_ready(void *port_, struct file * filp) ...@@ -432,7 +433,7 @@ int gs_block_til_ready(void *port_, struct file * filp)
*/ */
if ((filp->f_flags & O_NONBLOCK) || if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) { (tty->flags & (1 << TTY_IO_ERROR))) {
port->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -444,34 +445,34 @@ int gs_block_til_ready(void *port_, struct file * filp) ...@@ -444,34 +445,34 @@ int gs_block_til_ready(void *port_, struct file * filp)
/* /*
* Block waiting for the carrier detect and the line to become * Block waiting for the carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in * free (i.e., not in use by the callout). While we are in
* this loop, port->port.count is dropped by one, so that * this loop, port->count is dropped by one, so that
* rs_close() knows when to free things. We restore it upon * rs_close() knows when to free things. We restore it upon
* exit, either normal or abnormal. * exit, either normal or abnormal.
*/ */
retval = 0; retval = 0;
add_wait_queue(&port->port.open_wait, &wait); add_wait_queue(&port->open_wait, &wait);
gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n");
spin_lock_irqsave(&port->driver_lock, flags); spin_lock_irqsave(&gp->driver_lock, flags);
if (!tty_hung_up_p(filp)) { if (!tty_hung_up_p(filp)) {
port->port.count--; port->count--;
} }
spin_unlock_irqrestore(&port->driver_lock, flags); spin_unlock_irqrestore(&gp->driver_lock, flags);
port->port.blocked_open++; port->blocked_open++;
while (1) { while (1) {
CD = port->rd->get_CD (port); CD = tty_port_carrier_raised(port);
gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
set_current_state (TASK_INTERRUPTIBLE); set_current_state (TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || if (tty_hung_up_p(filp) ||
!(port->port.flags & ASYNC_INITIALIZED)) { !(port->flags & ASYNC_INITIALIZED)) {
if (port->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN; retval = -EAGAIN;
else else
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
break; break;
} }
if (!(port->port.flags & ASYNC_CLOSING) && if (!(port->flags & ASYNC_CLOSING) &&
(do_clocal || CD)) (do_clocal || CD))
break; break;
gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n",
...@@ -483,17 +484,17 @@ int gs_block_til_ready(void *port_, struct file * filp) ...@@ -483,17 +484,17 @@ int gs_block_til_ready(void *port_, struct file * filp)
schedule(); schedule();
} }
gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n",
port->port.blocked_open); port->blocked_open);
set_current_state (TASK_RUNNING); set_current_state (TASK_RUNNING);
remove_wait_queue(&port->port.open_wait, &wait); remove_wait_queue(&port->open_wait, &wait);
if (!tty_hung_up_p(filp)) { if (!tty_hung_up_p(filp)) {
port->port.count++; port->count++;
} }
port->port.blocked_open--; port->blocked_open--;
if (retval) if (retval)
return retval; return retval;
port->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
func_exit (); func_exit ();
return 0; return 0;
} }
......
...@@ -830,20 +830,28 @@ static int isicom_setup_port(struct tty_struct *tty) ...@@ -830,20 +830,28 @@ static int isicom_setup_port(struct tty_struct *tty)
return 0; return 0;
} }
static int isicom_carrier_raised(struct tty_port *port)
{
struct isi_port *ip = container_of(port, struct isi_port, port);
return (ip->status & ISI_DCD)?1 : 0;
}
static int block_til_ready(struct tty_struct *tty, struct file *filp, static int block_til_ready(struct tty_struct *tty, struct file *filp,
struct isi_port *port) struct isi_port *ip)
{ {
struct isi_board *card = port->card; struct isi_board *card = ip->card;
struct tty_port *port = &ip->port;
int do_clocal = 0, retval; int do_clocal = 0, retval;
unsigned long flags; unsigned long flags;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int cd;
/* block if port is in the process of being closed */ /* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
pr_dbg("block_til_ready: close in progress.\n"); pr_dbg("block_til_ready: close in progress.\n");
interruptible_sleep_on(&port->port.close_wait); interruptible_sleep_on(&port->close_wait);
if (port->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN; return -EAGAIN;
else else
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -854,7 +862,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -854,7 +862,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
if ((filp->f_flags & O_NONBLOCK) || if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) { (tty->flags & (1 << TTY_IO_ERROR))) {
pr_dbg("block_til_ready: non-block mode.\n"); pr_dbg("block_til_ready: non-block mode.\n");
port->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -864,29 +872,29 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -864,29 +872,29 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
/* block waiting for DCD to be asserted, and while /* block waiting for DCD to be asserted, and while
callout dev is busy */ callout dev is busy */
retval = 0; retval = 0;
add_wait_queue(&port->port.open_wait, &wait); add_wait_queue(&port->open_wait, &wait);
spin_lock_irqsave(&card->card_lock, flags); spin_lock_irqsave(&card->card_lock, flags);
if (!tty_hung_up_p(filp)) if (!tty_hung_up_p(filp))
port->port.count--; port->count--;
port->port.blocked_open++; port->blocked_open++;
spin_unlock_irqrestore(&card->card_lock, flags); spin_unlock_irqrestore(&card->card_lock, flags);
while (1) { while (1) {
raise_dtr_rts(port); raise_dtr_rts(ip);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) { if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
if (port->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN; retval = -EAGAIN;
else else
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
break; break;
} }
if (!(port->port.flags & ASYNC_CLOSING) && cd = tty_port_carrier_raised(port);
(do_clocal || (port->status & ISI_DCD))) { if (!(port->flags & ASYNC_CLOSING) &&
(do_clocal || cd))
break; break;
}
if (signal_pending(current)) { if (signal_pending(current)) {
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
break; break;
...@@ -894,15 +902,15 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -894,15 +902,15 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
schedule(); schedule();
} }
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&port->port.open_wait, &wait); remove_wait_queue(&port->open_wait, &wait);
spin_lock_irqsave(&card->card_lock, flags); spin_lock_irqsave(&card->card_lock, flags);
if (!tty_hung_up_p(filp)) if (!tty_hung_up_p(filp))
port->port.count++; port->count++;
port->port.blocked_open--; port->blocked_open--;
spin_unlock_irqrestore(&card->card_lock, flags); spin_unlock_irqrestore(&card->card_lock, flags);
if (retval) if (retval)
return retval; return retval;
port->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -1452,6 +1460,10 @@ static const struct tty_operations isicom_ops = { ...@@ -1452,6 +1460,10 @@ static const struct tty_operations isicom_ops = {
.break_ctl = isicom_send_break, .break_ctl = isicom_send_break,
}; };
static const struct tty_port_operations isicom_port_ops = {
.carrier_raised = isicom_carrier_raised,
};
static int __devinit reset_card(struct pci_dev *pdev, static int __devinit reset_card(struct pci_dev *pdev,
const unsigned int card, unsigned int *signature) const unsigned int card, unsigned int *signature)
{ {
...@@ -1794,6 +1806,7 @@ static int __init isicom_init(void) ...@@ -1794,6 +1806,7 @@ static int __init isicom_init(void)
spin_lock_init(&isi_card[idx].card_lock); spin_lock_init(&isi_card[idx].card_lock);
for (channel = 0; channel < 16; channel++, port++) { for (channel = 0; channel < 16; channel++, port++) {
tty_port_init(&port->port); tty_port_init(&port->port);
port->port.ops = &isicom_port_ops;
port->magic = ISICOM_MAGIC; port->magic = ISICOM_MAGIC;
port->card = &isi_card[idx]; port->card = &isi_card[idx];
port->channel = channel; port->channel = channel;
......
...@@ -151,7 +151,7 @@ static char *stli_drvversion = "5.6.0"; ...@@ -151,7 +151,7 @@ static char *stli_drvversion = "5.6.0";
static char *stli_serialname = "ttyE"; static char *stli_serialname = "ttyE";
static struct tty_driver *stli_serial; static struct tty_driver *stli_serial;
static const struct tty_port_operations stli_port_ops;
#define STLI_TXBUFSIZE 4096 #define STLI_TXBUFSIZE 4096
...@@ -1183,6 +1183,12 @@ static int stli_setport(struct tty_struct *tty) ...@@ -1183,6 +1183,12 @@ static int stli_setport(struct tty_struct *tty)
/*****************************************************************************/ /*****************************************************************************/
static int stli_carrier_raised(struct tty_port *port)
{
struct stliport *portp = container_of(port, struct stliport, port);
return (portp->sigs & TIOCM_CD) ? 1 : 0;
}
/* /*
* Possibly need to wait for carrier (DCD signal) to come high. Say * Possibly need to wait for carrier (DCD signal) to come high. Say
* maybe because if we are clocal then we don't need to wait... * maybe because if we are clocal then we don't need to wait...
...@@ -1193,6 +1199,7 @@ static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp, ...@@ -1193,6 +1199,7 @@ static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
{ {
unsigned long flags; unsigned long flags;
int rc, doclocal; int rc, doclocal;
struct tty_port *port = &portp->port;
rc = 0; rc = 0;
doclocal = 0; doclocal = 0;
...@@ -1203,7 +1210,7 @@ static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp, ...@@ -1203,7 +1210,7 @@ static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
spin_lock_irqsave(&stli_lock, flags); spin_lock_irqsave(&stli_lock, flags);
portp->openwaitcnt++; portp->openwaitcnt++;
if (! tty_hung_up_p(filp)) if (! tty_hung_up_p(filp))
portp->port.count--; port->count--;
spin_unlock_irqrestore(&stli_lock, flags); spin_unlock_irqrestore(&stli_lock, flags);
for (;;) { for (;;) {
...@@ -1212,27 +1219,27 @@ static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp, ...@@ -1212,27 +1219,27 @@ static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
&portp->asig, sizeof(asysigs_t), 0)) < 0) &portp->asig, sizeof(asysigs_t), 0)) < 0)
break; break;
if (tty_hung_up_p(filp) || if (tty_hung_up_p(filp) ||
((portp->port.flags & ASYNC_INITIALIZED) == 0)) { ((port->flags & ASYNC_INITIALIZED) == 0)) {
if (portp->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
rc = -EBUSY; rc = -EBUSY;
else else
rc = -ERESTARTSYS; rc = -ERESTARTSYS;
break; break;
} }
if (((portp->port.flags & ASYNC_CLOSING) == 0) && if (((port->flags & ASYNC_CLOSING) == 0) &&
(doclocal || (portp->sigs & TIOCM_CD))) { (doclocal || tty_port_carrier_raised(port))) {
break; break;
} }
if (signal_pending(current)) { if (signal_pending(current)) {
rc = -ERESTARTSYS; rc = -ERESTARTSYS;
break; break;
} }
interruptible_sleep_on(&portp->port.open_wait); interruptible_sleep_on(&port->open_wait);
} }
spin_lock_irqsave(&stli_lock, flags); spin_lock_irqsave(&stli_lock, flags);
if (! tty_hung_up_p(filp)) if (! tty_hung_up_p(filp))
portp->port.count++; port->count++;
portp->openwaitcnt--; portp->openwaitcnt--;
spin_unlock_irqrestore(&stli_lock, flags); spin_unlock_irqrestore(&stli_lock, flags);
...@@ -2696,6 +2703,7 @@ static int stli_initports(struct stlibrd *brdp) ...@@ -2696,6 +2703,7 @@ static int stli_initports(struct stlibrd *brdp)
continue; continue;
} }
tty_port_init(&portp->port); tty_port_init(&portp->port);
portp->port.ops = &stli_port_ops;
portp->magic = STLI_PORTMAGIC; portp->magic = STLI_PORTMAGIC;
portp->portnr = i; portp->portnr = i;
portp->brdnr = brdp->brdnr; portp->brdnr = brdp->brdnr;
...@@ -4518,6 +4526,10 @@ static const struct tty_operations stli_ops = { ...@@ -4518,6 +4526,10 @@ static const struct tty_operations stli_ops = {
.tiocmset = stli_tiocmset, .tiocmset = stli_tiocmset,
}; };
static const struct tty_port_operations stli_port_ops = {
.carrier_raised = stli_carrier_raised,
};
/*****************************************************************************/ /*****************************************************************************/
/* /*
* Loadable module initialization stuff. * Loadable module initialization stuff.
......
...@@ -206,6 +206,7 @@ static void moxa_poll(unsigned long); ...@@ -206,6 +206,7 @@ static void moxa_poll(unsigned long);
static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
static void moxa_setup_empty_event(struct tty_struct *); static void moxa_setup_empty_event(struct tty_struct *);
static void moxa_shut_down(struct tty_struct *); static void moxa_shut_down(struct tty_struct *);
static int moxa_carrier_raised(struct tty_port *);
/* /*
* moxa board interface functions: * moxa board interface functions:
*/ */
...@@ -405,6 +406,10 @@ static const struct tty_operations moxa_ops = { ...@@ -405,6 +406,10 @@ static const struct tty_operations moxa_ops = {
.tiocmset = moxa_tiocmset, .tiocmset = moxa_tiocmset,
}; };
static const struct tty_port_operations moxa_port_ops = {
.carrier_raised = moxa_carrier_raised,
};
static struct tty_driver *moxaDriver; static struct tty_driver *moxaDriver;
static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
static DEFINE_SPINLOCK(moxa_lock); static DEFINE_SPINLOCK(moxa_lock);
...@@ -826,6 +831,7 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) ...@@ -826,6 +831,7 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) { for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
tty_port_init(&p->port); tty_port_init(&p->port);
p->port.ops = &moxa_port_ops;
p->type = PORT_16550A; p->type = PORT_16550A;
p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
} }
...@@ -1115,15 +1121,27 @@ static void moxa_close_port(struct tty_struct *tty) ...@@ -1115,15 +1121,27 @@ static void moxa_close_port(struct tty_struct *tty)
tty_port_tty_set(&ch->port, NULL); tty_port_tty_set(&ch->port, NULL);
} }
static int moxa_carrier_raised(struct tty_port *port)
{
struct moxa_port *ch = container_of(port, struct moxa_port, port);
int dcd;
spin_lock_bh(&moxa_lock);
dcd = ch->DCDState;
spin_unlock_bh(&moxa_lock);
return dcd;
}
static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
struct moxa_port *ch) struct moxa_port *ch)
{ {
struct tty_port *port = &ch->port;
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
int retval = 0; int retval = 0;
u8 dcd; u8 dcd;
while (1) { while (1) {
prepare_to_wait(&ch->port.open_wait, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp)) { if (tty_hung_up_p(filp)) {
#ifdef SERIAL_DO_RESTART #ifdef SERIAL_DO_RESTART
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
...@@ -1132,9 +1150,7 @@ static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, ...@@ -1132,9 +1150,7 @@ static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
#endif #endif
break; break;
} }
spin_lock_bh(&moxa_lock); dcd = tty_port_carrier_raised(port);
dcd = ch->DCDState;
spin_unlock_bh(&moxa_lock);
if (dcd) if (dcd)
break; break;
...@@ -1144,7 +1160,7 @@ static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, ...@@ -1144,7 +1160,7 @@ static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
} }
schedule(); schedule();
} }
finish_wait(&ch->port.open_wait, &wait); finish_wait(&port->open_wait, &wait);
return retval; return retval;
} }
......
...@@ -541,13 +541,21 @@ static unsigned char mxser_get_msr(int baseaddr, int mode, int port) ...@@ -541,13 +541,21 @@ static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
return status; return status;
} }
static int mxser_carrier_raised(struct tty_port *port)
{
struct mxser_port *mp = container_of(port, struct mxser_port, port);
return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
}
static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
struct mxser_port *port) struct mxser_port *mp)
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int retval; int retval;
int do_clocal = 0; int do_clocal = 0;
unsigned long flags; unsigned long flags;
int cd;
struct tty_port *port = &mp->port;
/* /*
* If non-blocking mode is set, or the port is not enabled, * If non-blocking mode is set, or the port is not enabled,
...@@ -555,7 +563,7 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -555,7 +563,7 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
*/ */
if ((filp->f_flags & O_NONBLOCK) || if ((filp->f_flags & O_NONBLOCK) ||
test_bit(TTY_IO_ERROR, &tty->flags)) { test_bit(TTY_IO_ERROR, &tty->flags)) {
port->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -565,34 +573,33 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -565,34 +573,33 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
/* /*
* Block waiting for the carrier detect and the line to become * Block waiting for the carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in * free (i.e., not in use by the callout). While we are in
* this loop, port->port.count is dropped by one, so that * this loop, port->count is dropped by one, so that
* mxser_close() knows when to free things. We restore it upon * mxser_close() knows when to free things. We restore it upon
* exit, either normal or abnormal. * exit, either normal or abnormal.
*/ */
retval = 0; retval = 0;
add_wait_queue(&port->port.open_wait, &wait); add_wait_queue(&port->open_wait, &wait);
spin_lock_irqsave(&port->slock, flags); spin_lock_irqsave(&mp->slock, flags);
if (!tty_hung_up_p(filp)) if (!tty_hung_up_p(filp))
port->port.count--; port->count--;
spin_unlock_irqrestore(&port->slock, flags); spin_unlock_irqrestore(&mp->slock, flags);
port->port.blocked_open++; port->blocked_open++;
while (1) { while (1) {
spin_lock_irqsave(&port->slock, flags); spin_lock_irqsave(&mp->slock, flags);
outb(inb(port->ioaddr + UART_MCR) | outb(inb(mp->ioaddr + UART_MCR) |
UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR); UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
spin_unlock_irqrestore(&port->slock, flags); spin_unlock_irqrestore(&mp->slock, flags);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) { if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
if (port->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN; retval = -EAGAIN;
else else
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
break; break;
} }
if (!(port->port.flags & ASYNC_CLOSING) && cd = tty_port_carrier_raised(port);
(do_clocal || if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
(inb(port->ioaddr + UART_MSR) & UART_MSR_DCD)))
break; break;
if (signal_pending(current)) { if (signal_pending(current)) {
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
...@@ -601,13 +608,13 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -601,13 +608,13 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
schedule(); schedule();
} }
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&port->port.open_wait, &wait); remove_wait_queue(&port->open_wait, &wait);
if (!tty_hung_up_p(filp)) if (!tty_hung_up_p(filp))
port->port.count++; port->count++;
port->port.blocked_open--; port->blocked_open--;
if (retval) if (retval)
return retval; return retval;
port->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -2449,6 +2456,10 @@ static const struct tty_operations mxser_ops = { ...@@ -2449,6 +2456,10 @@ static const struct tty_operations mxser_ops = {
.tiocmset = mxser_tiocmset, .tiocmset = mxser_tiocmset,
}; };
struct tty_port_operations mxser_port_ops = {
.carrier_raised = mxser_carrier_raised,
};
/* /*
* The MOXA Smartio/Industio serial driver boot-time initialization code! * The MOXA Smartio/Industio serial driver boot-time initialization code!
*/ */
...@@ -2482,6 +2493,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, ...@@ -2482,6 +2493,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
for (i = 0; i < brd->info->nports; i++) { for (i = 0; i < brd->info->nports; i++) {
info = &brd->ports[i]; info = &brd->ports[i];
tty_port_init(&info->port); tty_port_init(&info->port);
info->port.ops = &mxser_port_ops;
info->board = brd; info->board = brd;
info->stop_rx = 0; info->stop_rx = 0;
info->ldisc_stop_rx = 0; info->ldisc_stop_rx = 0;
......
...@@ -173,7 +173,7 @@ static void rio_disable_tx_interrupts(void *ptr); ...@@ -173,7 +173,7 @@ static void rio_disable_tx_interrupts(void *ptr);
static void rio_enable_tx_interrupts(void *ptr); static void rio_enable_tx_interrupts(void *ptr);
static void rio_disable_rx_interrupts(void *ptr); static void rio_disable_rx_interrupts(void *ptr);
static void rio_enable_rx_interrupts(void *ptr); static void rio_enable_rx_interrupts(void *ptr);
static int rio_get_CD(void *ptr); static int rio_carrier_raised(struct tty_port *port);
static void rio_shutdown_port(void *ptr); static void rio_shutdown_port(void *ptr);
static int rio_set_real_termios(void *ptr); static int rio_set_real_termios(void *ptr);
static void rio_hungup(void *ptr); static void rio_hungup(void *ptr);
...@@ -224,7 +224,6 @@ static struct real_driver rio_real_driver = { ...@@ -224,7 +224,6 @@ static struct real_driver rio_real_driver = {
rio_enable_tx_interrupts, rio_enable_tx_interrupts,
rio_disable_rx_interrupts, rio_disable_rx_interrupts,
rio_enable_rx_interrupts, rio_enable_rx_interrupts,
rio_get_CD,
rio_shutdown_port, rio_shutdown_port,
rio_set_real_termios, rio_set_real_termios,
rio_chars_in_buffer, rio_chars_in_buffer,
...@@ -476,9 +475,9 @@ static void rio_enable_rx_interrupts(void *ptr) ...@@ -476,9 +475,9 @@ static void rio_enable_rx_interrupts(void *ptr)
/* Jeez. Isn't this simple? */ /* Jeez. Isn't this simple? */
static int rio_get_CD(void *ptr) static int rio_carrier_raised(struct tty_port *port)
{ {
struct Port *PortP = ptr; struct Port *PortP = container_of(port, struct Port, gs.port);
int rv; int rv;
func_enter(); func_enter();
...@@ -806,7 +805,9 @@ static void *ckmalloc(int size) ...@@ -806,7 +805,9 @@ static void *ckmalloc(int size)
return p; return p;
} }
static const struct tty_port_operations rio_port_ops = {
.carrier_raised = rio_carrier_raised,
};
static int rio_init_datastructures(void) static int rio_init_datastructures(void)
{ {
...@@ -842,17 +843,14 @@ static int rio_init_datastructures(void) ...@@ -842,17 +843,14 @@ static int rio_init_datastructures(void)
goto free6; goto free6;
} }
rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped); rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
tty_port_init(&port->gs.port);
port->gs.port.ops = &rio_port_ops;
port->PortNum = i; port->PortNum = i;
port->gs.magic = RIO_MAGIC; port->gs.magic = RIO_MAGIC;
port->gs.close_delay = HZ / 2; port->gs.close_delay = HZ / 2;
port->gs.closing_wait = 30 * HZ; port->gs.closing_wait = 30 * HZ;
port->gs.rd = &rio_real_driver; port->gs.rd = &rio_real_driver;
spin_lock_init(&port->portSem); spin_lock_init(&port->portSem);
/*
* Initializing wait queue
*/
init_waitqueue_head(&port->gs.port.open_wait);
init_waitqueue_head(&port->gs.port.close_wait);
} }
#else #else
/* We could postpone initializing them to when they are configured. */ /* We could postpone initializing them to when they are configured. */
......
...@@ -857,23 +857,40 @@ static void rc_shutdown_port(struct tty_struct *tty, ...@@ -857,23 +857,40 @@ static void rc_shutdown_port(struct tty_struct *tty,
rc_shutdown_board(bp); rc_shutdown_board(bp);
} }
static int carrier_raised(struct tty_port *port)
{
struct riscom_port *p = container_of(port, struct riscom_port, port);
struct riscom_board *bp = port_Board(p);
unsigned long flags;
int CD;
spin_lock_irqsave(&riscom_lock, flags);
rc_out(bp, CD180_CAR, port_No(p));
CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
rc_out(bp, CD180_MSVR, MSVR_RTS);
bp->DTR &= ~(1u << port_No(p));
rc_out(bp, RC_DTR, bp->DTR);
spin_unlock_irqrestore(&riscom_lock, flags);
return CD;
}
static int block_til_ready(struct tty_struct *tty, struct file *filp, static int block_til_ready(struct tty_struct *tty, struct file *filp,
struct riscom_port *port) struct riscom_port *rp)
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
struct riscom_board *bp = port_Board(port);
int retval; int retval;
int do_clocal = 0; int do_clocal = 0;
int CD; int CD;
unsigned long flags; unsigned long flags;
struct tty_port *port = &rp->port;
/* /*
* If the device is in the middle of being closed, then block * If the device is in the middle of being closed, then block
* until it's done, and then try again. * until it's done, and then try again.
*/ */
if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
interruptible_sleep_on(&port->port.close_wait); interruptible_sleep_on(&port->close_wait);
if (port->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN; return -EAGAIN;
else else
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -885,7 +902,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -885,7 +902,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
*/ */
if ((filp->f_flags & O_NONBLOCK) || if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) { (tty->flags & (1 << TTY_IO_ERROR))) {
port->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -900,37 +917,29 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -900,37 +917,29 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
* exit, either normal or abnormal. * exit, either normal or abnormal.
*/ */
retval = 0; retval = 0;
add_wait_queue(&port->port.open_wait, &wait); add_wait_queue(&port->open_wait, &wait);
spin_lock_irqsave(&riscom_lock, flags); spin_lock_irqsave(&riscom_lock, flags);
if (!tty_hung_up_p(filp)) if (!tty_hung_up_p(filp))
port->port.count--; port->count--;
spin_unlock_irqrestore(&riscom_lock, flags); spin_unlock_irqrestore(&riscom_lock, flags);
port->port.blocked_open++; port->blocked_open++;
while (1) { while (1) {
spin_lock_irqsave(&riscom_lock, flags);
rc_out(bp, CD180_CAR, port_No(port));
CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
rc_out(bp, CD180_MSVR, MSVR_RTS);
bp->DTR &= ~(1u << port_No(port));
rc_out(bp, RC_DTR, bp->DTR);
spin_unlock_irqrestore(&riscom_lock, flags);
CD = tty_port_carrier_raised(port);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || if (tty_hung_up_p(filp) ||
!(port->port.flags & ASYNC_INITIALIZED)) { !(port->flags & ASYNC_INITIALIZED)) {
if (port->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN; retval = -EAGAIN;
else else
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
break; break;
} }
if (!(port->port.flags & ASYNC_CLOSING) && if (!(port->flags & ASYNC_CLOSING) &&
(do_clocal || CD)) (do_clocal || CD))
break; break;
if (signal_pending(current)) { if (signal_pending(current)) {
...@@ -940,14 +949,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -940,14 +949,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
schedule(); schedule();
} }
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
remove_wait_queue(&port->port.open_wait, &wait); remove_wait_queue(&port->open_wait, &wait);
if (!tty_hung_up_p(filp)) if (!tty_hung_up_p(filp))
port->port.count++; port->count++;
port->port.blocked_open--; port->blocked_open--;
if (retval) if (retval)
return retval; return retval;
port->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -1510,6 +1519,11 @@ static const struct tty_operations riscom_ops = { ...@@ -1510,6 +1519,11 @@ static const struct tty_operations riscom_ops = {
.break_ctl = rc_send_break, .break_ctl = rc_send_break,
}; };
static const struct tty_port_operations riscom_port_ops = {
.carrier_raised = carrier_raised,
};
static int __init rc_init_drivers(void) static int __init rc_init_drivers(void)
{ {
int error; int error;
...@@ -1541,6 +1555,7 @@ static int __init rc_init_drivers(void) ...@@ -1541,6 +1555,7 @@ static int __init rc_init_drivers(void)
memset(rc_port, 0, sizeof(rc_port)); memset(rc_port, 0, sizeof(rc_port));
for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { for (i = 0; i < RC_NPORT * RC_NBOARD; i++) {
tty_port_init(&rc_port[i].port); tty_port_init(&rc_port[i].port);
rc_port[i].port.ops = &riscom_port_ops;
rc_port[i].magic = RISCOM8_MAGIC; rc_port[i].magic = RISCOM8_MAGIC;
} }
return 0; return 0;
......
...@@ -135,6 +135,7 @@ static int rcktpt_type[NUM_BOARDS]; ...@@ -135,6 +135,7 @@ static int rcktpt_type[NUM_BOARDS];
static int is_PCI[NUM_BOARDS]; static int is_PCI[NUM_BOARDS];
static rocketModel_t rocketModel[NUM_BOARDS]; static rocketModel_t rocketModel[NUM_BOARDS];
static int max_board; static int max_board;
static const struct tty_port_operations rocket_port_ops;
/* /*
* The following arrays define the interrupt bits corresponding to each AIOP. * The following arrays define the interrupt bits corresponding to each AIOP.
...@@ -649,9 +650,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) ...@@ -649,9 +650,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
info->board = board; info->board = board;
info->aiop = aiop; info->aiop = aiop;
info->chan = chan; info->chan = chan;
info->port.closing_wait = 3000; tty_port_init(&info->port);
info->port.close_delay = 50; info->port.ops = &rocket_port_ops;
init_waitqueue_head(&info->port.open_wait);
init_completion(&info->close_wait); init_completion(&info->close_wait);
info->flags &= ~ROCKET_MODE_MASK; info->flags &= ~ROCKET_MODE_MASK;
switch (pc104[board][line]) { switch (pc104[board][line]) {
...@@ -864,11 +864,18 @@ static void configure_r_port(struct r_port *info, ...@@ -864,11 +864,18 @@ static void configure_r_port(struct r_port *info,
} }
} }
static int carrier_raised(struct tty_port *port)
{
struct r_port *info = container_of(port, struct r_port, port);
return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0;
}
/* info->port.count is considered critical, protected by spinlocks. */ /* info->port.count is considered critical, protected by spinlocks. */
static int block_til_ready(struct tty_struct *tty, struct file *filp, static int block_til_ready(struct tty_struct *tty, struct file *filp,
struct r_port *info) struct r_port *info)
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
struct tty_port *port = &info->port;
int retval; int retval;
int do_clocal = 0, extra_count = 0; int do_clocal = 0, extra_count = 0;
unsigned long flags; unsigned long flags;
...@@ -898,13 +905,13 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -898,13 +905,13 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
/* /*
* Block waiting for the carrier detect and the line to become free. While we are in * Block waiting for the carrier detect and the line to become free. While we are in
* this loop, info->port.count is dropped by one, so that rp_close() knows when to free things. * this loop, port->count is dropped by one, so that rp_close() knows when to free things.
* We restore it upon exit, either normal or abnormal. * We restore it upon exit, either normal or abnormal.
*/ */
retval = 0; retval = 0;
add_wait_queue(&info->port.open_wait, &wait); add_wait_queue(&port->open_wait, &wait);
#ifdef ROCKET_DEBUG_OPEN #ifdef ROCKET_DEBUG_OPEN
printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, info->port.count); printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, port->count);
#endif #endif
spin_lock_irqsave(&info->slock, flags); spin_lock_irqsave(&info->slock, flags);
...@@ -913,10 +920,10 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -913,10 +920,10 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
#else #else
if (!tty_hung_up_p(filp)) { if (!tty_hung_up_p(filp)) {
extra_count = 1; extra_count = 1;
info->port.count--; port->count--;
} }
#endif #endif
info->port.blocked_open++; port->blocked_open++;
spin_unlock_irqrestore(&info->slock, flags); spin_unlock_irqrestore(&info->slock, flags);
...@@ -933,7 +940,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -933,7 +940,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
break; break;
} }
if (!(info->flags & ROCKET_CLOSING) && (do_clocal || (sGetChanStatusLo(&info->channel) & CD_ACT))) if (!(info->flags & ROCKET_CLOSING) &&
(do_clocal || tty_port_carrier_raised(port)))
break; break;
if (signal_pending(current)) { if (signal_pending(current)) {
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
...@@ -941,24 +949,24 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -941,24 +949,24 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
} }
#ifdef ROCKET_DEBUG_OPEN #ifdef ROCKET_DEBUG_OPEN
printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n", printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n",
info->line, info->port.count, info->flags); info->line, port->count, info->flags);
#endif #endif
schedule(); /* Don't hold spinlock here, will hang PC */ schedule(); /* Don't hold spinlock here, will hang PC */
} }
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
remove_wait_queue(&info->port.open_wait, &wait); remove_wait_queue(&port->open_wait, &wait);
spin_lock_irqsave(&info->slock, flags); spin_lock_irqsave(&info->slock, flags);
if (extra_count) if (extra_count)
info->port.count++; port->count++;
info->port.blocked_open--; port->blocked_open--;
spin_unlock_irqrestore(&info->slock, flags); spin_unlock_irqrestore(&info->slock, flags);
#ifdef ROCKET_DEBUG_OPEN #ifdef ROCKET_DEBUG_OPEN
printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n", printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n",
info->line, info->port.count); info->line, port->count);
#endif #endif
if (retval) if (retval)
return retval; return retval;
...@@ -2371,6 +2379,10 @@ static const struct tty_operations rocket_ops = { ...@@ -2371,6 +2379,10 @@ static const struct tty_operations rocket_ops = {
.tiocmset = rp_tiocmset, .tiocmset = rp_tiocmset,
}; };
static const struct tty_port_operations rocket_port_ops = {
.carrier_raised = carrier_raised,
};
/* /*
* The module "startup" routine; it's run when the module is loaded. * The module "startup" routine; it's run when the module is loaded.
*/ */
......
...@@ -122,7 +122,7 @@ static void a2232_disable_tx_interrupts(void *ptr); ...@@ -122,7 +122,7 @@ static void a2232_disable_tx_interrupts(void *ptr);
static void a2232_enable_tx_interrupts(void *ptr); static void a2232_enable_tx_interrupts(void *ptr);
static void a2232_disable_rx_interrupts(void *ptr); static void a2232_disable_rx_interrupts(void *ptr);
static void a2232_enable_rx_interrupts(void *ptr); static void a2232_enable_rx_interrupts(void *ptr);
static int a2232_get_CD(void *ptr); static int a2232_carrier_raised(struct tty_port *port);
static void a2232_shutdown_port(void *ptr); static void a2232_shutdown_port(void *ptr);
static int a2232_set_real_termios(void *ptr); static int a2232_set_real_termios(void *ptr);
static int a2232_chars_in_buffer(void *ptr); static int a2232_chars_in_buffer(void *ptr);
...@@ -148,7 +148,6 @@ static struct real_driver a2232_real_driver = { ...@@ -148,7 +148,6 @@ static struct real_driver a2232_real_driver = {
a2232_enable_tx_interrupts, a2232_enable_tx_interrupts,
a2232_disable_rx_interrupts, a2232_disable_rx_interrupts,
a2232_enable_rx_interrupts, a2232_enable_rx_interrupts,
a2232_get_CD,
a2232_shutdown_port, a2232_shutdown_port,
a2232_set_real_termios, a2232_set_real_termios,
a2232_chars_in_buffer, a2232_chars_in_buffer,
...@@ -260,9 +259,10 @@ static void a2232_enable_rx_interrupts(void *ptr) ...@@ -260,9 +259,10 @@ static void a2232_enable_rx_interrupts(void *ptr)
port->disable_rx = 0; port->disable_rx = 0;
} }
static int a2232_get_CD(void *ptr) static int a2232_carrier_raised(struct tty_port *port)
{ {
return ((struct a2232_port *) ptr)->cd_status; struct a2232_port *ap = container_of(port, struct a2232_port, gs.port);
return ap->cd_status;
} }
static void a2232_shutdown_port(void *ptr) static void a2232_shutdown_port(void *ptr)
...@@ -638,6 +638,10 @@ int ch, err, n, p; ...@@ -638,6 +638,10 @@ int ch, err, n, p;
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static const struct tty_port_operations a2232_port_ops = {
.carrier_raised = a2232_carrier_raised,
};
static void a2232_init_portstructs(void) static void a2232_init_portstructs(void)
{ {
struct a2232_port *port; struct a2232_port *port;
...@@ -645,6 +649,8 @@ static void a2232_init_portstructs(void) ...@@ -645,6 +649,8 @@ static void a2232_init_portstructs(void)
for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) { for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) {
port = a2232_ports + i; port = a2232_ports + i;
tty_port_init(&port->gs.port);
port->gs.port.ops = &a2232_port_ops;
port->which_a2232 = i/NUMLINES; port->which_a2232 = i/NUMLINES;
port->which_port_on_a2232 = i%NUMLINES; port->which_port_on_a2232 = i%NUMLINES;
port->disable_rx = port->throttle_input = port->cd_status = 0; port->disable_rx = port->throttle_input = port->cd_status = 0;
...@@ -652,11 +658,6 @@ static void a2232_init_portstructs(void) ...@@ -652,11 +658,6 @@ static void a2232_init_portstructs(void)
port->gs.close_delay = HZ/2; port->gs.close_delay = HZ/2;
port->gs.closing_wait = 30 * HZ; port->gs.closing_wait = 30 * HZ;
port->gs.rd = &a2232_real_driver; port->gs.rd = &a2232_real_driver;
#ifdef NEW_WRITE_LOCKING
mutex_init(&(port->gs.port_write_mutex));
#endif
init_waitqueue_head(&port->gs.port.open_wait);
init_waitqueue_head(&port->gs.port.close_wait);
} }
} }
......
...@@ -130,6 +130,8 @@ static char stl_unwanted[SC26198_RXFIFOSIZE]; ...@@ -130,6 +130,8 @@ static char stl_unwanted[SC26198_RXFIFOSIZE];
static DEFINE_MUTEX(stl_brdslock); static DEFINE_MUTEX(stl_brdslock);
static struct stlbrd *stl_brds[STL_MAXBRDS]; static struct stlbrd *stl_brds[STL_MAXBRDS];
static const struct tty_port_operations stl_port_ops;
/* /*
* Per board state flags. Used with the state field of the board struct. * Per board state flags. Used with the state field of the board struct.
* Not really much here! * Not really much here!
...@@ -786,6 +788,12 @@ static int stl_open(struct tty_struct *tty, struct file *filp) ...@@ -786,6 +788,12 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
/*****************************************************************************/ /*****************************************************************************/
static int stl_carrier_raised(struct tty_port *port)
{
struct stlport *portp = container_of(port, struct stlport, port);
return (portp->sigs & TIOCM_CD) ? 1 : 0;
}
/* /*
* Possibly need to wait for carrier (DCD signal) to come high. Say * Possibly need to wait for carrier (DCD signal) to come high. Say
* maybe because if we are clocal then we don't need to wait... * maybe because if we are clocal then we don't need to wait...
...@@ -796,6 +804,7 @@ static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, ...@@ -796,6 +804,7 @@ static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp,
{ {
unsigned long flags; unsigned long flags;
int rc, doclocal; int rc, doclocal;
struct tty_port *port = &portp->port;
pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp); pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
...@@ -809,32 +818,32 @@ static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, ...@@ -809,32 +818,32 @@ static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp,
portp->openwaitcnt++; portp->openwaitcnt++;
if (! tty_hung_up_p(filp)) if (! tty_hung_up_p(filp))
portp->port.count--; port->count--;
for (;;) { for (;;) {
/* Takes brd_lock internally */ /* Takes brd_lock internally */
stl_setsignals(portp, 1, 1); stl_setsignals(portp, 1, 1);
if (tty_hung_up_p(filp) || if (tty_hung_up_p(filp) ||
((portp->port.flags & ASYNC_INITIALIZED) == 0)) { ((port->flags & ASYNC_INITIALIZED) == 0)) {
if (portp->port.flags & ASYNC_HUP_NOTIFY) if (port->flags & ASYNC_HUP_NOTIFY)
rc = -EBUSY; rc = -EBUSY;
else else
rc = -ERESTARTSYS; rc = -ERESTARTSYS;
break; break;
} }
if (((portp->port.flags & ASYNC_CLOSING) == 0) && if (((port->flags & ASYNC_CLOSING) == 0) &&
(doclocal || (portp->sigs & TIOCM_CD))) (doclocal || tty_port_carrier_raised(port)))
break; break;
if (signal_pending(current)) { if (signal_pending(current)) {
rc = -ERESTARTSYS; rc = -ERESTARTSYS;
break; break;
} }
/* FIXME */ /* FIXME */
interruptible_sleep_on(&portp->port.open_wait); interruptible_sleep_on(&port->open_wait);
} }
if (! tty_hung_up_p(filp)) if (! tty_hung_up_p(filp))
portp->port.count++; port->count++;
portp->openwaitcnt--; portp->openwaitcnt--;
spin_unlock_irqrestore(&stallion_lock, flags); spin_unlock_irqrestore(&stallion_lock, flags);
...@@ -1776,6 +1785,7 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) ...@@ -1776,6 +1785,7 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
break; break;
} }
tty_port_init(&portp->port); tty_port_init(&portp->port);
portp->port.ops = &stl_port_ops;
portp->magic = STL_PORTMAGIC; portp->magic = STL_PORTMAGIC;
portp->portnr = i; portp->portnr = i;
portp->brdnr = panelp->brdnr; portp->brdnr = panelp->brdnr;
...@@ -2659,6 +2669,10 @@ static const struct tty_operations stl_ops = { ...@@ -2659,6 +2669,10 @@ static const struct tty_operations stl_ops = {
.tiocmset = stl_tiocmset, .tiocmset = stl_tiocmset,
}; };
static const struct tty_port_operations stl_port_ops = {
.carrier_raised = stl_carrier_raised,
};
/*****************************************************************************/ /*****************************************************************************/
/* CD1400 HARDWARE FUNCTIONS */ /* CD1400 HARDWARE FUNCTIONS */
/*****************************************************************************/ /*****************************************************************************/
......
...@@ -279,7 +279,7 @@ static void sx_disable_tx_interrupts(void *ptr); ...@@ -279,7 +279,7 @@ static void sx_disable_tx_interrupts(void *ptr);
static void sx_enable_tx_interrupts(void *ptr); static void sx_enable_tx_interrupts(void *ptr);
static void sx_disable_rx_interrupts(void *ptr); static void sx_disable_rx_interrupts(void *ptr);
static void sx_enable_rx_interrupts(void *ptr); static void sx_enable_rx_interrupts(void *ptr);
static int sx_get_CD(void *ptr); static int sx_carrier_raised(struct tty_port *port);
static void sx_shutdown_port(void *ptr); static void sx_shutdown_port(void *ptr);
static int sx_set_real_termios(void *ptr); static int sx_set_real_termios(void *ptr);
static void sx_close(void *ptr); static void sx_close(void *ptr);
...@@ -360,7 +360,6 @@ static struct real_driver sx_real_driver = { ...@@ -360,7 +360,6 @@ static struct real_driver sx_real_driver = {
sx_enable_tx_interrupts, sx_enable_tx_interrupts,
sx_disable_rx_interrupts, sx_disable_rx_interrupts,
sx_enable_rx_interrupts, sx_enable_rx_interrupts,
sx_get_CD,
sx_shutdown_port, sx_shutdown_port,
sx_set_real_termios, sx_set_real_termios,
sx_chars_in_buffer, sx_chars_in_buffer,
...@@ -791,7 +790,7 @@ static int sx_getsignals(struct sx_port *port) ...@@ -791,7 +790,7 @@ static int sx_getsignals(struct sx_port *port)
sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) " sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) "
"%02x/%02x\n", "%02x/%02x\n",
(o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
port->c_dcd, sx_get_CD(port), port->c_dcd, tty_port_carrier_raised(&port->gs.port),
sx_read_channel_byte(port, hi_ip), sx_read_channel_byte(port, hi_ip),
sx_read_channel_byte(port, hi_state)); sx_read_channel_byte(port, hi_state));
...@@ -1190,7 +1189,7 @@ static inline void sx_check_modem_signals(struct sx_port *port) ...@@ -1190,7 +1189,7 @@ static inline void sx_check_modem_signals(struct sx_port *port)
hi_state = sx_read_channel_byte(port, hi_state); hi_state = sx_read_channel_byte(port, hi_state);
sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n", sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
port->c_dcd, sx_get_CD(port)); port->c_dcd, tty_port_carrier_raised(&port->gs.port));
if (hi_state & ST_BREAK) { if (hi_state & ST_BREAK) {
hi_state &= ~ST_BREAK; hi_state &= ~ST_BREAK;
...@@ -1202,11 +1201,11 @@ static inline void sx_check_modem_signals(struct sx_port *port) ...@@ -1202,11 +1201,11 @@ static inline void sx_check_modem_signals(struct sx_port *port)
hi_state &= ~ST_DCD; hi_state &= ~ST_DCD;
sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n"); sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
sx_write_channel_byte(port, hi_state, hi_state); sx_write_channel_byte(port, hi_state, hi_state);
c_dcd = sx_get_CD(port); c_dcd = tty_port_carrier_raised(&port->gs.port);
sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd); sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
if (c_dcd != port->c_dcd) { if (c_dcd != port->c_dcd) {
port->c_dcd = c_dcd; port->c_dcd = c_dcd;
if (sx_get_CD(port)) { if (tty_port_carrier_raised(&port->gs.port)) {
/* DCD went UP */ /* DCD went UP */
if ((sx_read_channel_byte(port, hi_hstat) != if ((sx_read_channel_byte(port, hi_hstat) !=
HS_IDLE_CLOSED) && HS_IDLE_CLOSED) &&
...@@ -1415,13 +1414,10 @@ static void sx_enable_rx_interrupts(void *ptr) ...@@ -1415,13 +1414,10 @@ static void sx_enable_rx_interrupts(void *ptr)
} }
/* Jeez. Isn't this simple? */ /* Jeez. Isn't this simple? */
static int sx_get_CD(void *ptr) static int sx_carrier_raised(struct tty_port *port)
{ {
struct sx_port *port = ptr; struct sx_port *sp = container_of(port, struct sx_port, gs.port);
func_enter2(); return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0);
func_exit();
return ((sx_read_channel_byte(port, hi_ip) & IP_DCD) != 0);
} }
/* Jeez. Isn't this simple? */ /* Jeez. Isn't this simple? */
...@@ -1536,7 +1532,7 @@ static int sx_open(struct tty_struct *tty, struct file *filp) ...@@ -1536,7 +1532,7 @@ static int sx_open(struct tty_struct *tty, struct file *filp)
} }
/* tty->low_latency = 1; */ /* tty->low_latency = 1; */
port->c_dcd = sx_get_CD(port); port->c_dcd = sx_carrier_raised(&port->gs.port);
sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
func_exit(); func_exit();
...@@ -2354,6 +2350,10 @@ static const struct tty_operations sx_ops = { ...@@ -2354,6 +2350,10 @@ static const struct tty_operations sx_ops = {
.tiocmset = sx_tiocmset, .tiocmset = sx_tiocmset,
}; };
static const struct tty_port_operations sx_port_ops = {
.carrier_raised = sx_carrier_raised,
};
static int sx_init_drivers(void) static int sx_init_drivers(void)
{ {
int error; int error;
...@@ -2410,6 +2410,7 @@ static int sx_init_portstructs(int nboards, int nports) ...@@ -2410,6 +2410,7 @@ static int sx_init_portstructs(int nboards, int nports)
for (j = 0; j < boards[i].nports; j++) { for (j = 0; j < boards[i].nports; j++) {
sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j); sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
tty_port_init(&port->gs.port); tty_port_init(&port->gs.port);
port->gs.port.ops = &sx_port_ops;
port->gs.magic = SX_MAGIC; port->gs.magic = SX_MAGIC;
port->gs.close_delay = HZ / 2; port->gs.close_delay = HZ / 2;
port->gs.closing_wait = 30 * HZ; port->gs.closing_wait = 30 * HZ;
......
...@@ -3281,6 +3281,23 @@ static void mgsl_hangup(struct tty_struct *tty) ...@@ -3281,6 +3281,23 @@ static void mgsl_hangup(struct tty_struct *tty)
} /* end of mgsl_hangup() */ } /* end of mgsl_hangup() */
/*
* carrier_raised()
*
* Return true if carrier is raised
*/
static int carrier_raised(struct tty_port *port)
{
unsigned long flags;
struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
spin_lock_irqsave(&info->irq_spinlock, flags);
usc_get_serial_signals(info);
spin_unlock_irqrestore(&info->irq_spinlock, flags);
return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
}
/* block_til_ready() /* block_til_ready()
* *
* Block the current process until the specified port * Block the current process until the specified port
...@@ -3302,6 +3319,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, ...@@ -3302,6 +3319,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
bool do_clocal = false; bool do_clocal = false;
bool extra_count = false; bool extra_count = false;
unsigned long flags; unsigned long flags;
int dcd;
struct tty_port *port = &info->port;
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready on %s\n", printk("%s(%d):block_til_ready on %s\n",
...@@ -3309,7 +3328,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, ...@@ -3309,7 +3328,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
/* nonblock mode is set or port is not enabled */ /* nonblock mode is set or port is not enabled */
info->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -3318,25 +3337,25 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, ...@@ -3318,25 +3337,25 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
/* Wait for carrier detect and the line to become /* Wait for carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in * free (i.e., not in use by the callout). While we are in
* this loop, info->port.count is dropped by one, so that * this loop, port->count is dropped by one, so that
* mgsl_close() knows when to free things. We restore it upon * mgsl_close() knows when to free things. We restore it upon
* exit, either normal or abnormal. * exit, either normal or abnormal.
*/ */
retval = 0; retval = 0;
add_wait_queue(&info->port.open_wait, &wait); add_wait_queue(&port->open_wait, &wait);
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready before block on %s count=%d\n", printk("%s(%d):block_til_ready before block on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, info->port.count ); __FILE__,__LINE__, tty->driver->name, port->count );
spin_lock_irqsave(&info->irq_spinlock, flags); spin_lock_irqsave(&info->irq_spinlock, flags);
if (!tty_hung_up_p(filp)) { if (!tty_hung_up_p(filp)) {
extra_count = true; extra_count = true;
info->port.count--; port->count--;
} }
spin_unlock_irqrestore(&info->irq_spinlock, flags); spin_unlock_irqrestore(&info->irq_spinlock, flags);
info->port.blocked_open++; port->blocked_open++;
while (1) { while (1) {
if (tty->termios->c_cflag & CBAUD) { if (tty->termios->c_cflag & CBAUD) {
...@@ -3348,20 +3367,16 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, ...@@ -3348,20 +3367,16 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS; -EAGAIN : -ERESTARTSYS;
break; break;
} }
spin_lock_irqsave(&info->irq_spinlock,flags); dcd = tty_port_carrier_raised(&info->port);
usc_get_serial_signals(info);
spin_unlock_irqrestore(&info->irq_spinlock,flags);
if (!(info->port.flags & ASYNC_CLOSING) && if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd))
(do_clocal || (info->serial_signals & SerialSignal_DCD)) ) {
break; break;
}
if (signal_pending(current)) { if (signal_pending(current)) {
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
...@@ -3370,24 +3385,24 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, ...@@ -3370,24 +3385,24 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready blocking on %s count=%d\n", printk("%s(%d):block_til_ready blocking on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, info->port.count ); __FILE__,__LINE__, tty->driver->name, port->count );
schedule(); schedule();
} }
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&info->port.open_wait, &wait); remove_wait_queue(&port->open_wait, &wait);
if (extra_count) if (extra_count)
info->port.count++; port->count++;
info->port.blocked_open--; port->blocked_open--;
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready after blocking on %s count=%d\n", printk("%s(%d):block_til_ready after blocking on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, info->port.count ); __FILE__,__LINE__, tty->driver->name, port->count );
if (!retval) if (!retval)
info->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return retval; return retval;
...@@ -4304,6 +4319,11 @@ static void mgsl_add_device( struct mgsl_struct *info ) ...@@ -4304,6 +4319,11 @@ static void mgsl_add_device( struct mgsl_struct *info )
} /* end of mgsl_add_device() */ } /* end of mgsl_add_device() */
static const struct tty_port_operations mgsl_port_ops = {
.carrier_raised = carrier_raised,
};
/* mgsl_allocate_device() /* mgsl_allocate_device()
* *
* Allocate and initialize a device instance structure * Allocate and initialize a device instance structure
...@@ -4322,6 +4342,7 @@ static struct mgsl_struct* mgsl_allocate_device(void) ...@@ -4322,6 +4342,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
printk("Error can't allocate device instance data\n"); printk("Error can't allocate device instance data\n");
} else { } else {
tty_port_init(&info->port); tty_port_init(&info->port);
info->port.ops = &mgsl_port_ops;
info->magic = MGSL_MAGIC; info->magic = MGSL_MAGIC;
INIT_WORK(&info->task, mgsl_bh_handler); INIT_WORK(&info->task, mgsl_bh_handler);
info->max_frame_size = 4096; info->max_frame_size = 4096;
......
...@@ -3132,6 +3132,17 @@ static int tiocmset(struct tty_struct *tty, struct file *file, ...@@ -3132,6 +3132,17 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
return 0; return 0;
} }
static int carrier_raised(struct tty_port *port)
{
unsigned long flags;
struct slgt_info *info = container_of(port, struct slgt_info, port);
spin_lock_irqsave(&info->lock,flags);
get_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
return (info->signals & SerialSignal_DCD) ? 1 : 0;
}
/* /*
* block current process until the device is ready to open * block current process until the device is ready to open
*/ */
...@@ -3143,12 +3154,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3143,12 +3154,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
bool do_clocal = false; bool do_clocal = false;
bool extra_count = false; bool extra_count = false;
unsigned long flags; unsigned long flags;
int cd;
struct tty_port *port = &info->port;
DBGINFO(("%s block_til_ready\n", tty->driver->name)); DBGINFO(("%s block_til_ready\n", tty->driver->name));
if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
/* nonblock mode is set or port is not enabled */ /* nonblock mode is set or port is not enabled */
info->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -3157,21 +3170,21 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3157,21 +3170,21 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
/* Wait for carrier detect and the line to become /* Wait for carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in * free (i.e., not in use by the callout). While we are in
* this loop, info->port.count is dropped by one, so that * this loop, port->count is dropped by one, so that
* close() knows when to free things. We restore it upon * close() knows when to free things. We restore it upon
* exit, either normal or abnormal. * exit, either normal or abnormal.
*/ */
retval = 0; retval = 0;
add_wait_queue(&info->port.open_wait, &wait); add_wait_queue(&port->open_wait, &wait);
spin_lock_irqsave(&info->lock, flags); spin_lock_irqsave(&info->lock, flags);
if (!tty_hung_up_p(filp)) { if (!tty_hung_up_p(filp)) {
extra_count = true; extra_count = true;
info->port.count--; port->count--;
} }
spin_unlock_irqrestore(&info->lock, flags); spin_unlock_irqrestore(&info->lock, flags);
info->port.blocked_open++; port->blocked_open++;
while (1) { while (1) {
if ((tty->termios->c_cflag & CBAUD)) { if ((tty->termios->c_cflag & CBAUD)) {
...@@ -3183,20 +3196,16 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3183,20 +3196,16 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS; -EAGAIN : -ERESTARTSYS;
break; break;
} }
spin_lock_irqsave(&info->lock,flags); cd = tty_port_carrier_raised(port);
get_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
if (!(info->port.flags & ASYNC_CLOSING) && if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd ))
(do_clocal || (info->signals & SerialSignal_DCD)) ) {
break; break;
}
if (signal_pending(current)) { if (signal_pending(current)) {
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
...@@ -3208,14 +3217,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3208,14 +3217,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
} }
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&info->port.open_wait, &wait); remove_wait_queue(&port->open_wait, &wait);
if (extra_count) if (extra_count)
info->port.count++; port->count++;
info->port.blocked_open--; port->blocked_open--;
if (!retval) if (!retval)
info->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval));
return retval; return retval;
...@@ -3444,6 +3453,10 @@ static void add_device(struct slgt_info *info) ...@@ -3444,6 +3453,10 @@ static void add_device(struct slgt_info *info)
#endif #endif
} }
static const struct tty_port_operations slgt_port_ops = {
.carrier_raised = carrier_raised,
};
/* /*
* allocate device instance structure, return NULL on failure * allocate device instance structure, return NULL on failure
*/ */
...@@ -3458,6 +3471,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev ...@@ -3458,6 +3471,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
driver_name, adapter_num, port_num)); driver_name, adapter_num, port_num));
} else { } else {
tty_port_init(&info->port); tty_port_init(&info->port);
info->port.ops = &slgt_port_ops;
info->magic = MGSL_MAGIC; info->magic = MGSL_MAGIC;
INIT_WORK(&info->task, bh_handler); INIT_WORK(&info->task, bh_handler);
info->max_frame_size = 4096; info->max_frame_size = 4096;
......
...@@ -558,6 +558,7 @@ static void release_resources(SLMP_INFO *info); ...@@ -558,6 +558,7 @@ static void release_resources(SLMP_INFO *info);
static int startup(SLMP_INFO *info); static int startup(SLMP_INFO *info);
static int block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info); static int block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info);
static int carrier_raised(struct tty_port *port);
static void shutdown(SLMP_INFO *info); static void shutdown(SLMP_INFO *info);
static void program_hw(SLMP_INFO *info); static void program_hw(SLMP_INFO *info);
static void change_params(SLMP_INFO *info); static void change_params(SLMP_INFO *info);
...@@ -3318,7 +3319,17 @@ static int tiocmset(struct tty_struct *tty, struct file *file, ...@@ -3318,7 +3319,17 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
return 0; return 0;
} }
static int carrier_raised(struct tty_port *port)
{
SLMP_INFO *info = container_of(port, SLMP_INFO, port);
unsigned long flags;
spin_lock_irqsave(&info->lock,flags);
get_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
}
/* Block the current process until the specified port is ready to open. /* Block the current process until the specified port is ready to open.
*/ */
...@@ -3330,6 +3341,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3330,6 +3341,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
bool do_clocal = false; bool do_clocal = false;
bool extra_count = false; bool extra_count = false;
unsigned long flags; unsigned long flags;
int cd;
struct tty_port *port = &info->port;
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s block_til_ready()\n", printk("%s(%d):%s block_til_ready()\n",
...@@ -3338,7 +3351,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3338,7 +3351,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
/* nonblock mode is set or port is not enabled */ /* nonblock mode is set or port is not enabled */
/* just verify that callout device is not active */ /* just verify that callout device is not active */
info->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return 0; return 0;
} }
...@@ -3347,25 +3360,25 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3347,25 +3360,25 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
/* Wait for carrier detect and the line to become /* Wait for carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in * free (i.e., not in use by the callout). While we are in
* this loop, info->port.count is dropped by one, so that * this loop, port->count is dropped by one, so that
* close() knows when to free things. We restore it upon * close() knows when to free things. We restore it upon
* exit, either normal or abnormal. * exit, either normal or abnormal.
*/ */
retval = 0; retval = 0;
add_wait_queue(&info->port.open_wait, &wait); add_wait_queue(&port->open_wait, &wait);
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s block_til_ready() before block, count=%d\n", printk("%s(%d):%s block_til_ready() before block, count=%d\n",
__FILE__,__LINE__, tty->driver->name, info->port.count ); __FILE__,__LINE__, tty->driver->name, port->count );
spin_lock_irqsave(&info->lock, flags); spin_lock_irqsave(&info->lock, flags);
if (!tty_hung_up_p(filp)) { if (!tty_hung_up_p(filp)) {
extra_count = true; extra_count = true;
info->port.count--; port->count--;
} }
spin_unlock_irqrestore(&info->lock, flags); spin_unlock_irqrestore(&info->lock, flags);
info->port.blocked_open++; port->blocked_open++;
while (1) { while (1) {
if ((tty->termios->c_cflag & CBAUD)) { if ((tty->termios->c_cflag & CBAUD)) {
...@@ -3377,20 +3390,16 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3377,20 +3390,16 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS; -EAGAIN : -ERESTARTSYS;
break; break;
} }
spin_lock_irqsave(&info->lock,flags); cd = tty_port_carrier_raised(port);
get_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
if (!(info->port.flags & ASYNC_CLOSING) && if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
(do_clocal || (info->serial_signals & SerialSignal_DCD)) ) {
break; break;
}
if (signal_pending(current)) { if (signal_pending(current)) {
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
...@@ -3399,24 +3408,24 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3399,24 +3408,24 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s block_til_ready() count=%d\n", printk("%s(%d):%s block_til_ready() count=%d\n",
__FILE__,__LINE__, tty->driver->name, info->port.count ); __FILE__,__LINE__, tty->driver->name, port->count );
schedule(); schedule();
} }
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&info->port.open_wait, &wait); remove_wait_queue(&port->open_wait, &wait);
if (extra_count) if (extra_count)
info->port.count++; port->count++;
info->port.blocked_open--; port->blocked_open--;
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s block_til_ready() after, count=%d\n", printk("%s(%d):%s block_til_ready() after, count=%d\n",
__FILE__,__LINE__, tty->driver->name, info->port.count ); __FILE__,__LINE__, tty->driver->name, port->count );
if (!retval) if (!retval)
info->port.flags |= ASYNC_NORMAL_ACTIVE; port->flags |= ASYNC_NORMAL_ACTIVE;
return retval; return retval;
} }
...@@ -3782,6 +3791,10 @@ static void add_device(SLMP_INFO *info) ...@@ -3782,6 +3791,10 @@ static void add_device(SLMP_INFO *info)
#endif #endif
} }
static const struct tty_port_operations port_ops = {
.carrier_raised = carrier_raised,
};
/* Allocate and initialize a device instance structure /* Allocate and initialize a device instance structure
* *
* Return Value: pointer to SLMP_INFO if success, otherwise NULL * Return Value: pointer to SLMP_INFO if success, otherwise NULL
...@@ -3798,6 +3811,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) ...@@ -3798,6 +3811,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
__FILE__,__LINE__, adapter_num, port_num); __FILE__,__LINE__, adapter_num, port_num);
} else { } else {
tty_port_init(&info->port); tty_port_init(&info->port);
info->port.ops = &port_ops;
info->magic = MGSL_MAGIC; info->magic = MGSL_MAGIC;
INIT_WORK(&info->task, bh_handler); INIT_WORK(&info->task, bh_handler);
info->max_frame_size = 4096; info->max_frame_size = 4096;
...@@ -3940,6 +3954,7 @@ static const struct tty_operations ops = { ...@@ -3940,6 +3954,7 @@ static const struct tty_operations ops = {
.tiocmset = tiocmset, .tiocmset = tiocmset,
}; };
static void synclinkmp_cleanup(void) static void synclinkmp_cleanup(void)
{ {
int rc; int rc;
......
...@@ -94,3 +94,20 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty) ...@@ -94,3 +94,20 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
} }
EXPORT_SYMBOL(tty_port_tty_set); EXPORT_SYMBOL(tty_port_tty_set);
/**
* tty_port_carrier_raised - carrier raised check
* @port: tty port
*
* Wrapper for the carrier detect logic. For the moment this is used
* to hide some internal details. This will eventually become entirely
* internal to the tty port.
*/
int tty_port_carrier_raised(struct tty_port *port)
{
if (port->ops->carrier_raised == NULL)
return 1;
return port->ops->carrier_raised(port);
}
EXPORT_SYMBOL(tty_port_carrier_raised);
...@@ -69,7 +69,7 @@ static void scc_disable_tx_interrupts(void * ptr); ...@@ -69,7 +69,7 @@ static void scc_disable_tx_interrupts(void * ptr);
static void scc_enable_tx_interrupts(void * ptr); static void scc_enable_tx_interrupts(void * ptr);
static void scc_disable_rx_interrupts(void * ptr); static void scc_disable_rx_interrupts(void * ptr);
static void scc_enable_rx_interrupts(void * ptr); static void scc_enable_rx_interrupts(void * ptr);
static int scc_get_CD(void * ptr); static int scc_carrier_raised(struct tty_port *port);
static void scc_shutdown_port(void * ptr); static void scc_shutdown_port(void * ptr);
static int scc_set_real_termios(void *ptr); static int scc_set_real_termios(void *ptr);
static void scc_hungup(void *ptr); static void scc_hungup(void *ptr);
...@@ -100,7 +100,6 @@ static struct real_driver scc_real_driver = { ...@@ -100,7 +100,6 @@ static struct real_driver scc_real_driver = {
scc_enable_tx_interrupts, scc_enable_tx_interrupts,
scc_disable_rx_interrupts, scc_disable_rx_interrupts,
scc_enable_rx_interrupts, scc_enable_rx_interrupts,
scc_get_CD,
scc_shutdown_port, scc_shutdown_port,
scc_set_real_termios, scc_set_real_termios,
scc_chars_in_buffer, scc_chars_in_buffer,
...@@ -129,6 +128,10 @@ static const struct tty_operations scc_ops = { ...@@ -129,6 +128,10 @@ static const struct tty_operations scc_ops = {
.break_ctl = scc_break_ctl, .break_ctl = scc_break_ctl,
}; };
static const struct tty_port_operations scc_port_ops = {
.carrier_raised = scc_carrier_raised,
};
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* vme_scc_init() and support functions * vme_scc_init() and support functions
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
...@@ -176,6 +179,8 @@ static void scc_init_portstructs(void) ...@@ -176,6 +179,8 @@ static void scc_init_portstructs(void)
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
port = scc_ports + i; port = scc_ports + i;
tty_port_init(&port->gs.port);
port->gs.port.ops = &scc_port_ops;
port->gs.magic = SCC_MAGIC; port->gs.magic = SCC_MAGIC;
port->gs.close_delay = HZ/2; port->gs.close_delay = HZ/2;
port->gs.closing_wait = 30 * HZ; port->gs.closing_wait = 30 * HZ;
...@@ -624,9 +629,9 @@ static void scc_enable_rx_interrupts(void *ptr) ...@@ -624,9 +629,9 @@ static void scc_enable_rx_interrupts(void *ptr)
} }
static int scc_get_CD(void *ptr) static int scc_carrier_raised(struct tty_port *port)
{ {
struct scc_port *port = ptr; struct scc_port *scc = container_of(port, struct scc_port, gs.port);
unsigned channel = port->channel; unsigned channel = port->channel;
return !!(scc_last_status_reg[channel] & SR_DCD); return !!(scc_last_status_reg[channel] & SR_DCD);
...@@ -896,7 +901,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp) ...@@ -896,7 +901,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp)
return retval; return retval;
} }
port->c_dcd = scc_get_CD (port); port->c_dcd = tty_port_carrier_raised(&port->gs.port);
scc_enable_rx_interrupts(port); scc_enable_rx_interrupts(port);
......
...@@ -21,7 +21,6 @@ struct real_driver { ...@@ -21,7 +21,6 @@ struct real_driver {
void (*enable_tx_interrupts) (void *); void (*enable_tx_interrupts) (void *);
void (*disable_rx_interrupts) (void *); void (*disable_rx_interrupts) (void *);
void (*enable_rx_interrupts) (void *); void (*enable_rx_interrupts) (void *);
int (*get_CD) (void *);
void (*shutdown_port) (void*); void (*shutdown_port) (void*);
int (*set_real_termios) (void*); int (*set_real_termios) (void*);
int (*chars_in_buffer) (void*); int (*chars_in_buffer) (void*);
......
...@@ -180,8 +180,16 @@ struct signal_struct; ...@@ -180,8 +180,16 @@ struct signal_struct;
* until a hangup so don't use the wrong path. * until a hangup so don't use the wrong path.
*/ */
struct tty_port;
struct tty_port_operations {
/* Return 1 if the carrier is raised */
int (*carrier_raised)(struct tty_port *port);
};
struct tty_port { struct tty_port {
struct tty_struct *tty; /* Back pointer */ struct tty_struct *tty; /* Back pointer */
const struct tty_port_operations *ops; /* Port operations */
spinlock_t lock; /* Lock protecting tty field */ spinlock_t lock; /* Lock protecting tty field */
int blocked_open; /* Waiting to open */ int blocked_open; /* Waiting to open */
int count; /* Usage count */ int count; /* Usage count */
...@@ -427,6 +435,7 @@ extern int tty_port_alloc_xmit_buf(struct tty_port *port); ...@@ -427,6 +435,7 @@ extern int tty_port_alloc_xmit_buf(struct tty_port *port);
extern void tty_port_free_xmit_buf(struct tty_port *port); extern void tty_port_free_xmit_buf(struct tty_port *port);
extern struct tty_struct *tty_port_tty_get(struct tty_port *port); 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_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
extern int tty_unregister_ldisc(int disc); extern int tty_unregister_ldisc(int disc);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册