- spin_unlock_irqrestore(&info->slock, flags);
-}
-
-static void mxser_check_modem_status(struct mxser_struct *info, int status)
-{
- /* update input line counters */
- if (status & UART_MSR_TERI)
- info->icount.rng++;
- if (status & UART_MSR_DDSR)
- info->icount.dsr++;
- if (status & UART_MSR_DDCD)
- info->icount.dcd++;
- if (status & UART_MSR_DCTS)
- info->icount.cts++;
- info->mon_data.modem_status = status;
- wake_up_interruptible(&info->delta_msr_wait);
-
- if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
- if (status & UART_MSR_DCD)
- wake_up_interruptible(&info->open_wait);
- schedule_work(&info->tqueue);
- }
-
- if (info->flags & ASYNC_CTS_FLOW) {
- if (info->tty->hw_stopped) {
- if (status & UART_MSR_CTS) {
- info->tty->hw_stopped = 0;
-
- if ((info->type != PORT_16550A) &&
- (!info->IsMoxaMustChipFlag)) {
- info->IER |= UART_IER_THRI;
- outb(info->IER, info->base + UART_IER);
- }
- set_bit(MXSER_EVENT_TXLOW, &info->event);
- schedule_work(&info->tqueue); }
- } else {
- if (!(status & UART_MSR_CTS)) {
- info->tty->hw_stopped = 1;
- if ((info->type != PORT_16550A) &&
- (!info->IsMoxaMustChipFlag)) {
- info->IER &= ~UART_IER_THRI;
- outb(info->IER, info->base + UART_IER);
- }
- }
- }
- }
-}
-
-static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, struct mxser_struct *info)
-{
- DECLARE_WAITQUEUE(wait, current);
- int retval;
- int do_clocal = 0;
- unsigned long flags;
-
- /*
- * 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->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 (i.e., not in use by the callout). While we are in
- * this loop, info->count is dropped by one, so that
- * mxser_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
-
- spin_lock_irqsave(&info->slock, flags);
- if (!tty_hung_up_p(filp))
- info->count--;
- spin_unlock_irqrestore(&info->slock, flags);
- info->blocked_open++;
- while (1) {
- spin_lock_irqsave(&info->slock, flags);
- outb(inb(info->base + UART_MCR) |
- UART_MCR_DTR | UART_MCR_RTS, info->base + UART_MCR);
- spin_unlock_irqrestore(&info->slock, flags);
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) {
- if (info->flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
- break;
- }
- if (!(info->flags & ASYNC_CLOSING) &&
- (do_clocal ||
- (inb(info->base + UART_MSR) & UART_MSR_DCD)))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- schedule();
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&info->open_wait, &wait);
- if (!tty_hung_up_p(filp))
- info->count++;
- info->blocked_open--;
- if (retval)
- return retval;
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
-}
-
-static int mxser_startup(struct mxser_struct *info)
-{
- unsigned long page;
- unsigned long flags;
-
- page = __get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- spin_lock_irqsave(&info->slock, flags);
-
- if (info->flags & ASYNC_INITIALIZED) {
- free_page(page);
- spin_unlock_irqrestore(&info->slock, flags);
- return 0;
- }
-
- if (!info->base || !info->type) {
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- free_page(page);
- spin_unlock_irqrestore(&info->slock, flags);
- return 0;
- }
- if (info->xmit_buf)
- free_page(page);
- else
- info->xmit_buf = (unsigned char *) page;
-
- /*
- * Clear the FIFO buffers and disable them
- * (they will be reenabled in mxser_change_speed())
- */
- if (info->IsMoxaMustChipFlag)
- outb((UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT |
- MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
- else
- outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
- info->base + UART_FCR);
-
- /*
- * At this point there's no way the LSR could still be 0xFF;
- * if it is, then bail out, because there's likely no UART
- * here.
- */
- if (inb(info->base + UART_LSR) == 0xff) {
- spin_unlock_irqrestore(&info->slock, flags);
- if (capable(CAP_SYS_ADMIN)) {
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- return 0;
- } else
- return -ENODEV;
- }
-
- /*
- * Clear the interrupt registers.
- */
- (void) inb(info->base + UART_LSR);
- (void) inb(info->base + UART_RX);
- (void) inb(info->base + UART_IIR);
- (void) inb(info->base + UART_MSR);
-
- /*
- * Now, initialize the UART
- */
- outb(UART_LCR_WLEN8, info->base + UART_LCR); /* reset DLAB */
- info->MCR = UART_MCR_DTR | UART_MCR_RTS;
- outb(info->MCR, info->base + UART_MCR);
-
- /*
- * Finally, enable interrupts
- */
- info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
- /* info->IER = UART_IER_RLSI | UART_IER_RDI; */
-
- /* following add by Victor Yu. 08-30-2002 */
- if (info->IsMoxaMustChipFlag)
- info->IER |= MOXA_MUST_IER_EGDAI;
- /* above add by Victor Yu. 08-30-2002 */
- outb(info->IER, info->base + UART_IER); /* enable interrupts */
-
- /*
- * And clear the interrupt registers again for luck.
- */
- (void) inb(info->base + UART_LSR);
- (void) inb(info->base + UART_RX);
- (void) inb(info->base + UART_IIR);
- (void) inb(info->base + UART_MSR);
-
- if (info->tty)
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
- /*
- * and set the speed of the serial port
- */
- spin_unlock_irqrestore(&info->slock, flags);
- mxser_change_speed(info, NULL);
-
- info->flags |= ASYNC_INITIALIZED;
- return 0;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts maybe disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void mxser_shutdown(struct mxser_struct *info)
-{
- unsigned long flags;
-
- if (!(info->flags & ASYNC_INITIALIZED))
- return;
-
- spin_lock_irqsave(&info->slock, flags);
-
- /*
- * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
- * here so the queue might never be waken up
- */
- wake_up_interruptible(&info->delta_msr_wait);
-
- /*
- * Free the IRQ, if necessary
- */
- if (info->xmit_buf) {
- free_page((unsigned long) info->xmit_buf);
- info->xmit_buf = NULL;
- }
-
- info->IER = 0;
- outb(0x00, info->base + UART_IER);
-
- if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
- info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
- outb(info->MCR, info->base + UART_MCR);
-
- /* clear Rx/Tx FIFO's */
- /* following add by Victor Yu. 08-30-2002 */
- if (info->IsMoxaMustChipFlag)
- outb((UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT |
- MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
- else
- /* above add by Victor Yu. 08-30-2002 */
- outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
- info->base + UART_FCR);
-
- /* read data port to reset things */
- (void) inb(info->base + UART_RX);
-
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
-
- info->flags &= ~ASYNC_INITIALIZED;
-
- /* following add by Victor Yu. 09-23-2002 */
- if (info->IsMoxaMustChipFlag)
- SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base);
- /* above add by Victor Yu. 09-23-2002 */
-
- spin_unlock_irqrestore(&info->slock, flags);