⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsm_neo.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 + -