/* Parse the ISR register for the specific port */ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) { struct channel_t *ch; unsigned char isr = 0; unsigned long flags; /* * No need to verify board pointer, it was already * verified in the interrupt routine. */ if (port >= brd->nasync) 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_cls_uart->isr_fcr); /* Bail if no pending interrupt on port */ if (isr & UART_IIR_NO_INT) break; /* Receive Interrupt pending */ if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) { /* Read data from uart -> queue */ brd->intr_rx++; ch->ch_intr_rx++; cls_copy_data_from_uart_to_queue(ch); dgnc_check_queue_flow_control(ch); } /* Transmit Hold register empty pending */ if (isr & UART_IIR_THRI) { /* 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); brd->intr_tx++; ch->ch_intr_tx++; spin_unlock_irqrestore(&ch->ch_lock, flags); cls_copy_data_from_queue_to_uart(ch); } /* CTS/RTS change of state */ if (isr & UART_IIR_CTSRTS) { brd->intr_modem++; ch->ch_intr_modem++; /* * Don't need to do anything, the cls_parse_modem * below will grab the updated modem signals. */ } /* Parse any modem signal changes */ cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr)); } }
static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) { struct channel_t *ch; int linestatus; unsigned long flags; /* * Check to make sure it didn't receive interrupt with a null board * associated or a board pointer that wasn't ours. */ if (!brd || brd->magic != DGNC_BOARD_MAGIC) return; if (port >= brd->maxports) return; ch = brd->channels[port]; if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; linestatus = readb(&ch->ch_neo_uart->lsr); ch->ch_cached_lsr |= linestatus; if (ch->ch_cached_lsr & UART_LSR_DR) { brd->intr_rx++; ch->ch_intr_rx++; /* Read data from uart -> queue */ neo_copy_data_from_uart_to_queue(ch); spin_lock_irqsave(&ch->ch_lock, flags); dgnc_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, flags); } /* * The next 3 tests should *NOT* happen, as the above test * should encapsulate all 3... At least, thats what Exar says. */ if (linestatus & UART_LSR_PE) ch->ch_err_parity++; if (linestatus & UART_LSR_FE) ch->ch_err_frame++; if (linestatus & UART_LSR_BI) ch->ch_err_break++; if (linestatus & UART_LSR_OE) { /* * Rx Oruns. Exar says that an orun will NOT corrupt * the FIFO. It will just replace the holding register * with this new data byte. So basically just ignore this. * Probably we should eventually have an orun stat in our driver... */ ch->ch_err_overrun++; } if (linestatus & UART_LSR_THRE) { brd->intr_tx++; ch->ch_intr_tx++; 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); /* Transfer data (if any) from Write Queue -> UART. */ neo_copy_data_from_queue_to_uart(ch); } else if (linestatus & UART_17158_TX_AND_FIFO_CLR) { brd->intr_tx++; ch->ch_intr_tx++; 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); /* Transfer data (if any) from Write Queue -> UART. */ neo_copy_data_from_queue_to_uart(ch); } }
/* * 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 for the specific port */ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) { struct channel_t *ch; uchar isr = 0; ulong lock_flags; /* * No need to verify board pointer, it was already * verified in the interrupt routine. */ if (port > brd->nasync) return; ch = brd->channels[port]; if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; /* Here we try to figure out what caused the interrupt to happen */ while (1) { isr = readb(&ch->ch_cls_uart->isr_fcr); /* Bail if no pending interrupt on port */ if (isr & UART_IIR_NO_INT) break; DPR_INTR(("%s:%d port: %x isr: %x\n", __FILE__, __LINE__, port, isr)); /* Receive Interrupt pending */ if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) { /* Read data from uart -> queue */ brd->intr_rx++; ch->ch_intr_rx++; cls_copy_data_from_uart_to_queue(ch); dgnc_check_queue_flow_control(ch); } /* Transmit Hold register empty pending */ if (isr & UART_IIR_THRI) { /* Transfer data (if any) from Write Queue -> UART. */ DGNC_LOCK(ch->ch_lock, lock_flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); brd->intr_tx++; ch->ch_intr_tx++; DGNC_UNLOCK(ch->ch_lock, lock_flags); cls_copy_data_from_queue_to_uart(ch); } /* Received Xoff signal/Special character */ if (isr & UART_IIR_XOFF) /* Empty */ /* CTS/RTS change of state */ if (isr & UART_IIR_CTSRTS) { brd->intr_modem++; ch->ch_intr_modem++; /* * Don't need to do anything, the cls_parse_modem * below will grab the updated modem signals. */ } /* Parse any modem signal changes */ DPR_INTR(("MOD_STAT: sending to parse_modem_sigs\n")); cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr)); } }