* Now we wait for the transmit buffer to clear; and we notify 
* Now we wait for the transmit buffer to clear; and we notify 
static void sx_close(struct tty_struct * tty, struct file * filp){	struct specialix_port *port = (struct specialix_port *) tty->driver_data;	struct specialix_board *bp;	unsigned long flags;	unsigned long timeout;		func_enter();	if (!port || sx_paranoia_check(port, tty->name, "close")) {		func_exit();		return;	}	spin_lock_irqsave(&port->lock, flags);	if (tty_hung_up_p(filp)) {		spin_unlock_irqrestore(&port->lock, flags);		func_exit();		return;	}		bp = port_Board(port);	if ((tty->count == 1) && (port->count != 1)) {		printk(KERN_ERR "sx%d: sx_close: bad port count;"		       " tty->count is 1, port count is %d\n",		       board_No(bp), port->count);		port->count = 1;	}	if (port->count > 1) {		port->count--;		bp->count--;		spin_unlock_irqrestore(&port->lock, flags);		func_exit();		return;	}	port->flags |= ASYNC_CLOSING;	/*	 * Now we wait for the transmit buffer to clear; and we notify 	 * the line discipline to only process XON/XOFF characters.	 */	tty->closing = 1;	spin_unlock_irqrestore(&port->lock, flags);	dprintk (SX_DEBUG_OPEN, "Closing\n");	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {		tty_wait_until_sent(tty, port->closing_wait);	}	/*	 * At this point we stop accepting input.  To do this, we	 * disable the receive line status interrupts, and tell the	 * interrupt driver to stop checking the data ready bit in the	 * line status register.	 */	dprintk (SX_DEBUG_OPEN, "Closed\n");	port->IER &= ~IER_RXD;	if (port->flags & ASYNC_INITIALIZED) {		port->IER &= ~IER_TXRDY;		port->IER |= IER_TXEMPTY;		spin_lock_irqsave(&bp->lock, flags);		sx_out(bp, CD186x_CAR, port_No(port));		sx_out(bp, CD186x_IER, port->IER);		spin_unlock_irqrestore(&bp->lock, flags);		/*		 * Before we drop DTR, make sure the UART transmitter		 * has completely drained; this is especially		 * important if there is a transmit FIFO!		 */		timeout = jiffies+HZ;		while(port->IER & IER_TXEMPTY) {			set_current_state (TASK_INTERRUPTIBLE);			msleep_interruptible(jiffies_to_msecs(port->timeout));			if (time_after(jiffies, timeout)) {				printk (KERN_INFO "Timeout waiting for close\n");				break;			}		}	}	if (--bp->count < 0) {		printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",		       board_No(bp), bp->count, tty->index);		bp->count = 0;	}	if (--port->count < 0) {		printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",		       board_No(bp), port_No(port), port->count);		port->count = 0;	}	sx_shutdown_port(bp, port);	if (tty->driver->flush_buffer)		tty->driver->flush_buffer(tty);	tty_ldisc_flush(tty);	spin_lock_irqsave(&port->lock, flags);	tty->closing = 0;	port->event = 0;	port->tty = NULL;	spin_unlock_irqrestore(&port->lock, flags);	if (port->blocked_open) {		if (port->close_delay) {			msleep_interruptible(jiffies_to_msecs(port->close_delay));		}		wake_up_interruptible(&port->open_wait);	}	port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);	wake_up_interruptible(&port->close_wait);	func_exit();}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/d61780c0d384939ef31c46b47442854d5def4623/specialix.c/buggy/drivers/char/specialix.c