📄 jsm_neo.c
字号:
qleft--; ch->ch_rxcount++; } /* * Write new final heads to channel structure. */ ch->ch_r_head = head & RQUEUEMASK; ch->ch_e_head = head & EQUEUEMASK; jsm_input(ch);}static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch){ u16 head; u16 tail; int n; int s; int qlen; u32 len_written = 0; if (!ch) return; /* No data to write to the UART */ if (ch->ch_w_tail == ch->ch_w_head) return; /* If port is "stopped", don't send any data to the UART */ if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_BREAK_SENDING)) return; /* * If FIFOs are disabled. Send data directly to txrx register */ if (!(ch->ch_flags & CH_FIFO_ENABLED)) { u8 lsrbits = readb(&ch->ch_neo_uart->lsr); ch->ch_cached_lsr |= lsrbits; if (ch->ch_cached_lsr & UART_LSR_THRE) { ch->ch_cached_lsr &= ~(UART_LSR_THRE); writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx); jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev, "Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head]); ch->ch_w_tail++; ch->ch_w_tail &= WQUEUEMASK; ch->ch_txcount++; } return; } /* * We have to do it this way, because of the EXAR TXFIFO count bug. */ if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) return; len_written = 0; n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel; /* cache head and tail of queue */ head = ch->ch_w_head & WQUEUEMASK; tail = ch->ch_w_tail & WQUEUEMASK; qlen = (head - tail) & WQUEUEMASK; /* Find minimum of the FIFO space, versus queue length */ n = min(n, qlen); while (n > 0) { s = ((head >= tail) ? head : WQUEUESIZE) - tail; s = min(s, n); if (s <= 0) break; memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s); /* Add and flip queue if needed */ tail = (tail + s) & WQUEUEMASK; n -= s; ch->ch_txcount += s; len_written += s; } /* Update the final tail */ ch->ch_w_tail = tail & WQUEUEMASK; if (len_written >= ch->ch_t_tlevel) ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); if (!jsm_tty_write(&ch->uart_port)) uart_write_wakeup(&ch->uart_port);}static void neo_parse_modem(struct jsm_channel *ch, u8 signals){ u8 msignals = signals; jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev, "neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals); if (!ch) return; /* Scrub off lower bits. They signify delta's, which I don't care about */ msignals &= 0xf0; if (msignals & UART_MSR_DCD) ch->ch_mistat |= UART_MSR_DCD; else ch->ch_mistat &= ~UART_MSR_DCD; if (msignals & UART_MSR_DSR) ch->ch_mistat |= UART_MSR_DSR; else ch->ch_mistat &= ~UART_MSR_DSR; if (msignals & UART_MSR_RI) ch->ch_mistat |= UART_MSR_RI; else ch->ch_mistat &= ~UART_MSR_RI; if (msignals & UART_MSR_CTS) ch->ch_mistat |= UART_MSR_CTS; else ch->ch_mistat &= ~UART_MSR_CTS; jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev, "Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n", ch->ch_portnum, !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR), !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS), !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS), !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR), !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI), !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD));}/* Make the UART raise any of the output signals we want up */static void neo_assert_modem_signals(struct jsm_channel *ch){ u8 out; if (!ch) return; out = ch->ch_mostat; writeb(out, &ch->ch_neo_uart->mcr); /* flush write operation */ neo_pci_posting_flush(ch->ch_bd);}/* * Flush the WRITE FIFO on the Neo. * * NOTE: Channel lock MUST be held before calling this function! */static void neo_flush_uart_write(struct jsm_channel *ch){ u8 tmp = 0; int i = 0; if (!ch) return; writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr); for (i = 0; i < 10; i++) { /* Check to see if the UART feels it completely flushed the FIFO. */ tmp = readb(&ch->ch_neo_uart->isr_fcr); if (tmp & 4) { jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "Still flushing TX UART... i: %d\n", i); udelay(10); } else break; } ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);}/* * Flush the READ FIFO on the Neo. * * NOTE: Channel lock MUST be held before calling this function! */static void neo_flush_uart_read(struct jsm_channel *ch){ u8 tmp = 0; int i = 0; if (!ch) return; writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_neo_uart->isr_fcr); for (i = 0; i < 10; i++) { /* Check to see if the UART feels it completely flushed the FIFO. */ tmp = readb(&ch->ch_neo_uart->isr_fcr); if (tmp & 2) { jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "Still flushing RX UART... i: %d\n", i); udelay(10); } else break; }}/* * No locks are assumed to be held when calling this function. */static void neo_clear_break(struct jsm_channel *ch, int force){ unsigned long lock_flags; spin_lock_irqsave(&ch->ch_lock, lock_flags); /* Turn break off, and unset some variables */ if (ch->ch_flags & CH_BREAK_SENDING) { u8 temp = readb(&ch->ch_neo_uart->lcr); writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr); ch->ch_flags &= ~(CH_BREAK_SENDING); jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "clear break Finishing UART_LCR_SBC! finished: %lx\n", jiffies); /* flush write operation */ neo_pci_posting_flush(ch->ch_bd); } spin_unlock_irqrestore(&ch->ch_lock, lock_flags);}/* * 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)); }}static inline void neo_parse_lsr(struct jsm_board *brd, u32 port){ struct jsm_channel *ch; int linestatus; unsigned long lock_flags; if (!brd) return; if (port > brd->maxports) return; ch = brd->channels[port]; if (!ch) return; linestatus = readb(&ch->ch_neo_uart->lsr); jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev, "%s:%d port: %d linestatus: %x\n", __FILE__, __LINE__, port, linestatus); ch->ch_cached_lsr |= linestatus; if (ch->ch_cached_lsr & UART_LSR_DR) { /* Read data from uart -> queue */ neo_copy_data_from_uart_to_queue(ch); spin_lock_irqsave(&ch->ch_lock, lock_flags); jsm_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, lock_flags); } /* * This is a special flag. It indicates that at least 1 * RX error (parity, framing, or break) has happened. * Mark this in our struct, which will tell me that I have *to do the special RX+LSR read for this FIFO load. */ if (linestatus & UART_17158_RX_FIFO_DATA_ERROR) jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev, "%s:%d Port: %d Got an RX error, need to parse LSR\n", __FILE__, __LINE__, port); /* * 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++; jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev, "%s:%d Port: %d. PAR ERR!\n", __FILE__, __LINE__, port); } if (linestatus & UART_LSR_FE) { ch->ch_err_frame++; jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev, "%s:%d Port: %d. FRM ERR!\n", __FILE__, __LINE__, port); } if (linestatus & UART_LSR_BI) { ch->ch_err_break++; jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev, "%s:%d Port: %d. BRK INTR!\n", __FILE__, __LINE__, port); } 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++; jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev, "%s:%d Port: %d. Rx Overrun!\n", __FILE__, __LINE__, port); } if (linestatus & UART_LSR_THRE) { 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); /* 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) { 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); /* Transfer data (if any) from Write Queue -> UART. */ neo_copy_data_from_queue_to_uart(ch); }}/* * neo_param() * Send any/all changes to the line to the UART. */static void neo_param(struct jsm_channel *ch){ u8 lcr = 0; u8 uart_lcr = 0; u8 ier = 0; u32 baud = 9600; int quot = 0; struct jsm_board *bd; bd = ch->ch_bd; if (!bd) return; /* * If baud rate is zero, flush queues, and set mval to drop DTR. */ if ((ch->ch_c_cflag & (CBAUD)) == 0) { ch->ch_r_head = ch->ch_r_tail = 0; ch->ch_e_head = ch->ch_e_tail = 0; ch->ch_w_head = ch->ch_w_tail = 0; neo_flush_uart_write(ch); neo_flush_uart_read(ch);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -