/* * Parse the ISR register. */ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) { struct channel_t *ch; unsigned char isr; unsigned char cause; unsigned long flags; if (!brd || brd->magic != DGNC_BOARD_MAGIC) return; if (port >= brd->maxports) return; ch = brd->channels[port]; if (ch->magic != DGNC_CHANNEL_MAGIC) return; /* Here we try to figure out what caused the interrupt to happen */ while (1) { isr = readb(&ch->ch_neo_uart->isr_fcr); /* Bail if no pending interrupt */ if (isr & UART_IIR_NO_INT) break; /* * Yank off the upper 2 bits, which just show that the FIFO's are enabled. */ isr &= ~(UART_17158_IIR_FIFO_ENABLED); if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) { /* Read data from uart -> queue */ brd->intr_rx++; ch->ch_intr_rx++; neo_copy_data_from_uart_to_queue(ch); /* Call our tty layer to enforce queue flow control if needed. */ spin_lock_irqsave(&ch->ch_lock, flags); dgnc_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, flags); } if (isr & UART_IIR_THRI) { brd->intr_tx++; ch->ch_intr_tx++; /* Transfer data (if any) from Write Queue -> UART. */ spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); spin_unlock_irqrestore(&ch->ch_lock, flags); neo_copy_data_from_queue_to_uart(ch); } if (isr & UART_17158_IIR_XONXOFF) { cause = readb(&ch->ch_neo_uart->xoffchar1); /* * Since the UART detected either an XON or * XOFF match, we need to figure out which * one it was, so we can suspend or resume data flow. */ if (cause == UART_17158_XON_DETECT) { /* Is output stopped right now, if so, resume it */ if (brd->channels[port]->ch_flags & CH_STOP) { spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags &= ~(CH_STOP); spin_unlock_irqrestore(&ch->ch_lock, flags); } } else if (cause == UART_17158_XOFF_DETECT) { if (!(brd->channels[port]->ch_flags & CH_STOP)) { spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= CH_STOP; spin_unlock_irqrestore(&ch->ch_lock, flags); } } } if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) { /* * If we get here, this means the hardware is doing auto flow control. * Check to see whether RTS/DTR or CTS/DSR caused this interrupt. */ brd->intr_modem++; ch->ch_intr_modem++; cause = readb(&ch->ch_neo_uart->mcr); /* Which pin is doing auto flow? RTS or DTR? */ if ((cause & 0x4) == 0) { if (cause & UART_MCR_RTS) { spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_mostat |= UART_MCR_RTS; spin_unlock_irqrestore(&ch->ch_lock, flags); } else { spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_mostat &= ~(UART_MCR_RTS); spin_unlock_irqrestore(&ch->ch_lock, flags); } } else { if (cause & UART_MCR_DTR) { spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_mostat |= UART_MCR_DTR; spin_unlock_irqrestore(&ch->ch_lock, flags); } else { spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_mostat &= ~(UART_MCR_DTR); spin_unlock_irqrestore(&ch->ch_lock, flags); } } } /* Parse any modem signal changes */ neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr)); } }
/* * Parse the ISR register. */ static inline void neo_parse_isr(struct jsm_board *brd, u32 port) { struct jsm_channel *ch; u8 isr; u8 cause; unsigned long lock_flags; if (!brd) return; if (port > brd->maxports) return; ch = brd->channels[port]; if (!ch) return; /* Here we try to figure out what caused the interrupt to happen */ while (1) { isr = readb(&ch->ch_neo_uart->isr_fcr); /* Bail if no pending interrupt */ if (isr & UART_IIR_NO_INT) break; /* * Yank off the upper 2 bits, which just show that the FIFO's are enabled. */ isr &= ~(UART_17158_IIR_FIFO_ENABLED); jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev, "%s:%d isr: %x\n", __FILE__, __LINE__, isr); if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) { /* Read data from uart -> queue */ neo_copy_data_from_uart_to_queue(ch); /* Call our tty layer to enforce queue flow control if needed. */ spin_lock_irqsave(&ch->ch_lock, lock_flags); jsm_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, lock_flags); } if (isr & UART_IIR_THRI) { /* Transfer data (if any) from Write Queue -> UART. */ spin_lock_irqsave(&ch->ch_lock, lock_flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); spin_unlock_irqrestore(&ch->ch_lock, lock_flags); neo_copy_data_from_queue_to_uart(ch); } if (isr & UART_17158_IIR_XONXOFF) { cause = readb(&ch->ch_neo_uart->xoffchar1); jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev, "Port %d. Got ISR_XONXOFF: cause:%x\n", port, cause); /* * Since the UART detected either an XON or * XOFF match, we need to figure out which * one it was, so we can suspend or resume data flow. */ spin_lock_irqsave(&ch->ch_lock, lock_flags); if (cause == UART_17158_XON_DETECT) { /* Is output stopped right now, if so, resume it */ if (brd->channels[port]->ch_flags & CH_STOP) { ch->ch_flags &= ~(CH_STOP); } jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev, "Port %d. XON detected in incoming data\n", port); } else if (cause == UART_17158_XOFF_DETECT) { if (!(brd->channels[port]->ch_flags & CH_STOP)) { ch->ch_flags |= CH_STOP; jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev, "Setting CH_STOP\n"); } jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev, "Port: %d. XOFF detected in incoming data\n", port); } spin_unlock_irqrestore(&ch->ch_lock, lock_flags); } if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) { /* * If we get here, this means the hardware is doing auto flow control. * Check to see whether RTS/DTR or CTS/DSR caused this interrupt. */ cause = readb(&ch->ch_neo_uart->mcr); /* Which pin is doing auto flow? RTS or DTR? */ spin_lock_irqsave(&ch->ch_lock, lock_flags); if ((cause & 0x4) == 0) { if (cause & UART_MCR_RTS) ch->ch_mostat |= UART_MCR_RTS; else ch->ch_mostat &= ~(UART_MCR_RTS); } else { if (cause & UART_MCR_DTR) ch->ch_mostat |= UART_MCR_DTR; else ch->ch_mostat &= ~(UART_MCR_DTR); } spin_unlock_irqrestore(&ch->ch_lock, lock_flags); } /* Parse any modem signal changes */ jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev, "MOD_STAT: sending to parse_modem_sigs\n"); neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr)); } }