-/* info->port.count is considered critical, protected by spinlocks. */
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
- struct r_port *info)
-{
- DECLARE_WAITQUEUE(wait, current);
- struct tty_port *port = &info->port;
- int retval;
- int do_clocal = 0, extra_count = 0;
- unsigned long flags;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp))
- return ((info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
- if (info->flags & ASYNC_CLOSING) {
- if (wait_for_completion_interruptible(&info->close_wait))
- return -ERESTARTSYS;
- return ((info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
-
- /*
- * Block waiting for the carrier detect and the line to become free. While we are in
- * 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.
- */
- retval = 0;
- add_wait_queue(&port->open_wait, &wait);
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, port->count);
-#endif
- spin_lock_irqsave(&port->lock, flags);
-
-#ifdef ROCKET_DISABLE_SIMUSAGE
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
-#else
- if (!tty_hung_up_p(filp)) {
- extra_count = 1;
- port->count--;
- }
-#endif
- port->blocked_open++;
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- while (1) {
- if (tty->termios->c_cflag & CBAUD)
- tty_port_raise_dtr_rts(port);
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)) {
- if (info->port.flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
- break;
- }
- if (!(info->port.flags & ASYNC_CLOSING) &&
- (do_clocal || tty_port_carrier_raised(port)))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n",
- info->line, port->count, info->port.flags);
-#endif
- schedule(); /* Don't hold spinlock here, will hang PC */
- }
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->open_wait, &wait);
-
- spin_lock_irqsave(&port->lock, flags);
-
- if (extra_count)
- port->count++;
- port->blocked_open--;
-
- spin_unlock_irqrestore(&port->lock, flags);
-
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n",
- info->line, port->count);
-#endif
- if (retval)
- return retval;
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
-}
-