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

📄 jsm_neo.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		ch->ch_flags |= (CH_BAUD0);		ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);		neo_assert_modem_signals(ch);		ch->ch_old_baud = 0;		return;	} else if (ch->ch_custom_speed) {			baud = ch->ch_custom_speed;			if (ch->ch_flags & CH_BAUD0)				ch->ch_flags &= ~(CH_BAUD0);		} else {			int iindex = 0;			int jindex = 0;			const u64 bauds[4][16] = {				{					0,	50,	75,	110,					134,	150,	200,	300,					600,	1200,	1800,	2400,					4800,	9600,	19200,	38400 },				{					0,	57600,	115200, 230400,					460800, 150,	200,	921600,					600,	1200,	1800,	2400,					4800,	9600,	19200,	38400 },				{					0,	57600,	76800, 115200,					131657, 153600, 230400, 460800,					921600, 1200,	1800,	2400,					4800,	9600,	19200,	38400 },				{					0,	57600,	115200, 230400,					460800, 150,	200,	921600,					600,	1200,	1800,	2400,					4800,	9600,	19200,	38400 }			};			baud = C_BAUD(ch->uart_port.info->tty) & 0xff;			if (ch->ch_c_cflag & CBAUDEX)				iindex = 1;			jindex = baud;			if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16))				baud = bauds[iindex][jindex];			else {				jsm_printk(IOCTL, DEBUG, &ch->ch_bd->pci_dev,					"baud indices were out of range (%d)(%d)",				iindex, jindex);				baud = 0;			}			if (baud == 0)				baud = 9600;			if (ch->ch_flags & CH_BAUD0)				ch->ch_flags &= ~(CH_BAUD0);		}	if (ch->ch_c_cflag & PARENB)		lcr |= UART_LCR_PARITY;	if (!(ch->ch_c_cflag & PARODD))		lcr |= UART_LCR_EPAR;	/*	 * Not all platforms support mark/space parity,	 * so this will hide behind an ifdef.	 */#ifdef CMSPAR	if (ch->ch_c_cflag & CMSPAR)		lcr |= UART_LCR_SPAR;#endif	if (ch->ch_c_cflag & CSTOPB)		lcr |= UART_LCR_STOP;	switch (ch->ch_c_cflag & CSIZE) {		case CS5:			lcr |= UART_LCR_WLEN5;			break;		case CS6:			lcr |= UART_LCR_WLEN6;			break;		case CS7:			lcr |= UART_LCR_WLEN7;			break;		case CS8:		default:			lcr |= UART_LCR_WLEN8;		break;	}	ier = readb(&ch->ch_neo_uart->ier);	uart_lcr = readb(&ch->ch_neo_uart->lcr);	if (baud == 0)		baud = 9600;	quot = ch->ch_bd->bd_dividend / baud;	if (quot != 0) {		ch->ch_old_baud = baud;		writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr);		writeb((quot & 0xff), &ch->ch_neo_uart->txrx);		writeb((quot >> 8), &ch->ch_neo_uart->ier);		writeb(lcr, &ch->ch_neo_uart->lcr);	}	if (uart_lcr != lcr)		writeb(lcr, &ch->ch_neo_uart->lcr);	if (ch->ch_c_cflag & CREAD)		ier |= (UART_IER_RDI | UART_IER_RLSI);	ier |= (UART_IER_THRI | UART_IER_MSI);	writeb(ier, &ch->ch_neo_uart->ier);	/* Set new start/stop chars */	neo_set_new_start_stop_chars(ch);	if (ch->ch_c_cflag & CRTSCTS)		neo_set_cts_flow_control(ch);	else if (ch->ch_c_iflag & IXON) {		/* If start/stop is set to disable, then we should disable flow control */		if ((ch->ch_startc == __DISABLED_CHAR) || (ch->ch_stopc == __DISABLED_CHAR))			neo_set_no_output_flow_control(ch);		else			neo_set_ixon_flow_control(ch);	}	else		neo_set_no_output_flow_control(ch);	if (ch->ch_c_cflag & CRTSCTS)		neo_set_rts_flow_control(ch);	else if (ch->ch_c_iflag & IXOFF) {		/* If start/stop is set to disable, then we should disable flow control */		if ((ch->ch_startc == __DISABLED_CHAR) || (ch->ch_stopc == __DISABLED_CHAR))			neo_set_no_input_flow_control(ch);		else			neo_set_ixoff_flow_control(ch);	}	else		neo_set_no_input_flow_control(ch);	/*	 * Adjust the RX FIFO Trigger level if baud is less than 9600.	 * Not exactly elegant, but this is needed because of the Exar chip's	 * delay on firing off the RX FIFO interrupt on slower baud rates.	 */	if (baud < 9600) {		writeb(1, &ch->ch_neo_uart->rfifo);		ch->ch_r_tlevel = 1;	}	neo_assert_modem_signals(ch);	/* Get current status of the modem signals now */	neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));	return;}/* * jsm_neo_intr() * * Neo specific interrupt handler. */static irqreturn_t neo_intr(int irq, void *voidbrd, struct pt_regs *regs){	struct jsm_board *brd = (struct jsm_board *) voidbrd;	struct jsm_channel *ch;	int port = 0;	int type = 0;	int current_port;	u32 tmp;	u32 uart_poll;	unsigned long lock_flags;	unsigned long lock_flags2;	int outofloop_count = 0;	brd->intr_count++;	/* Lock out the slow poller from running on this board. */	spin_lock_irqsave(&brd->bd_intr_lock, lock_flags);	/*	 * Read in "extended" IRQ information from the 32bit Neo register.	 * Bits 0-7: What port triggered the interrupt.	 * Bits 8-31: Each 3bits indicate what type of interrupt occurred.	 */	uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);	jsm_printk(INTR, INFO, &brd->pci_dev,		"%s:%d uart_poll: %x\n", __FILE__, __LINE__, uart_poll);	if (!uart_poll) {		jsm_printk(INTR, INFO, &brd->pci_dev,			"Kernel interrupted to me, but no pending interrupts...\n");		spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);		return IRQ_NONE;	}	/* At this point, we have at least SOMETHING to service, dig further... */	current_port = 0;	/* Loop on each port */	while (((uart_poll & 0xff) != 0) && (outofloop_count < 0xff)){		tmp = uart_poll;		outofloop_count++;		/* Check current port to see if it has interrupt pending */		if ((tmp & jsm_offset_table[current_port]) != 0) {			port = current_port;			type = tmp >> (8 + (port * 3));			type &= 0x7;		} else {			current_port++;			continue;		}		jsm_printk(INTR, INFO, &brd->pci_dev,		"%s:%d port: %x type: %x\n", __FILE__, __LINE__, port, type);		/* Remove this port + type from uart_poll */		uart_poll &= ~(jsm_offset_table[port]);		if (!type) {			/* If no type, just ignore it, and move onto next port */			jsm_printk(INTR, ERR, &brd->pci_dev,				"Interrupt with no type! port: %d\n", port);			continue;		}		/* Switch on type of interrupt we have */		switch (type) {		case UART_17158_RXRDY_TIMEOUT:			/*			 * RXRDY Time-out is cleared by reading data in the			* RX FIFO until it falls below the trigger level.			 */			/* Verify the port is in range. */			if (port > brd->nasync)				continue;			ch = brd->channels[port];			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_flags2);			jsm_check_queue_flow_control(ch);			spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);			continue;		case UART_17158_RX_LINE_STATUS:			/*			 * RXRDY and RX LINE Status (logic OR of LSR[4:1])			 */			neo_parse_lsr(brd, port);			continue;		case UART_17158_TXRDY:			/*			 * TXRDY interrupt clears after reading ISR register for the UART channel.			 */			/*			 * Yes, this is odd...			 * Why would I check EVERY possibility of type of			 * interrupt, when we know its TXRDY???			 * Becuz for some reason, even tho we got triggered for TXRDY,			 * it seems to be occassionally wrong. Instead of TX, which			 * it should be, I was getting things like RXDY too. Weird.			 */			neo_parse_isr(brd, port);			continue;		case UART_17158_MSR:			/*			 * MSR or flow control was seen.			 */			neo_parse_isr(brd, port);			continue;		default:			/*			 * The UART triggered us with a bogus interrupt type.			 * It appears the Exar chip, when REALLY bogged down, will throw			 * these once and awhile.			 * Its harmless, just ignore it and move on.			 */			jsm_printk(INTR, ERR, &brd->pci_dev,				"%s:%d Unknown Interrupt type: %x\n", __FILE__, __LINE__, type);			continue;		}	}	spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);	jsm_printk(INTR, INFO, &brd->pci_dev, "finish.\n");	return IRQ_HANDLED;}/* * Neo specific way of turning off the receiver. * Used as a way to enforce queue flow control when in * hardware flow control mode. */static void neo_disable_receiver(struct jsm_channel *ch){	u8 tmp = readb(&ch->ch_neo_uart->ier);	tmp &= ~(UART_IER_RDI);	writeb(tmp, &ch->ch_neo_uart->ier);	/* flush write operation */	neo_pci_posting_flush(ch->ch_bd);}/* * Neo specific way of turning on the receiver. * Used as a way to un-enforce queue flow control when in * hardware flow control mode. */static void neo_enable_receiver(struct jsm_channel *ch){	u8 tmp = readb(&ch->ch_neo_uart->ier);	tmp |= (UART_IER_RDI);	writeb(tmp, &ch->ch_neo_uart->ier);	/* flush write operation */	neo_pci_posting_flush(ch->ch_bd);}static void neo_send_start_character(struct jsm_channel *ch){	if (!ch)		return;	if (ch->ch_startc != __DISABLED_CHAR) {		ch->ch_xon_sends++;		writeb(ch->ch_startc, &ch->ch_neo_uart->txrx);		/* flush write operation */		neo_pci_posting_flush(ch->ch_bd);	}}static void neo_send_stop_character(struct jsm_channel *ch){	if (!ch)		return;	if (ch->ch_stopc != __DISABLED_CHAR) {		ch->ch_xoff_sends++;		writeb(ch->ch_stopc, &ch->ch_neo_uart->txrx);		/* flush write operation */		neo_pci_posting_flush(ch->ch_bd);	}}/* * neo_uart_init */static void neo_uart_init(struct jsm_channel *ch){	writeb(0, &ch->ch_neo_uart->ier);	writeb(0, &ch->ch_neo_uart->efr);	writeb(UART_EFR_ECB, &ch->ch_neo_uart->efr);	/* Clear out UART and FIFO */	readb(&ch->ch_neo_uart->txrx);	writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);	readb(&ch->ch_neo_uart->lsr);	readb(&ch->ch_neo_uart->msr);	ch->ch_flags |= CH_FIFO_ENABLED;	/* Assert any signals we want up */	writeb(ch->ch_mostat, &ch->ch_neo_uart->mcr);}/* * Make the UART completely turn off. */static void neo_uart_off(struct jsm_channel *ch){	/* Turn off UART enhanced bits */	writeb(0, &ch->ch_neo_uart->efr);	/* Stop all interrupts from occurring. */	writeb(0, &ch->ch_neo_uart->ier);}static u32 neo_get_uart_bytes_left(struct jsm_channel *ch){	u8 left = 0;	u8 lsr = readb(&ch->ch_neo_uart->lsr);	/* We must cache the LSR as some of the bits get reset once read... */	ch->ch_cached_lsr |= lsr;	/* Determine whether the Transmitter is empty or not */	if (!(lsr & UART_LSR_TEMT))		left = 1;	else {		ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);		left = 0;	}	return left;}/* Channel lock MUST be held by the calling function! */static void neo_send_break(struct jsm_channel *ch){	/*	 * Set the time we should stop sending the break.	 * If we are already sending a break, toss away the existing	 * time to stop, and use this new value instead.	 */	/* Tell the UART to start sending the break */	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);		/* flush write operation */		neo_pci_posting_flush(ch->ch_bd);	}}/* * neo_send_immediate_char. * * Sends a specific character as soon as possible to the UART, * jumping over any bytes that might be in the write queue. * * The channel lock MUST be held by the calling function. */static void neo_send_immediate_char(struct jsm_channel *ch, unsigned char c){	if (!ch)		return;	writeb(c, &ch->ch_neo_uart->txrx);	/* flush write operation */	neo_pci_posting_flush(ch->ch_bd);}struct board_ops jsm_neo_ops = {	.intr				= neo_intr,	.uart_init			= neo_uart_init,	.uart_off			= neo_uart_off,	.param				= neo_param,	.assert_modem_signals		= neo_assert_modem_signals,	.flush_uart_write		= neo_flush_uart_write,	.flush_uart_read		= neo_flush_uart_read,	.disable_receiver		= neo_disable_receiver,	.enable_receiver		= neo_enable_receiver,	.send_break			= neo_send_break,	.clear_break			= neo_clear_break,	.send_start_character		= neo_send_start_character,	.send_stop_character		= neo_send_stop_character,	.copy_data_from_queue_to_uart	= neo_copy_data_from_queue_to_uart,	.get_uart_bytes_left		= neo_get_uart_bytes_left,	.send_immediate_char		= neo_send_immediate_char};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -