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

📄 ip22zilog.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	xmit = &up->port.info->xmit;	if (uart_circ_empty(xmit))		goto ack_tx_int;	if (uart_tx_stopped(&up->port))		goto ack_tx_int;	up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;	writeb(xmit->buf[xmit->tail], &channel->data);	ZSDELAY();	ZS_WSYNC(channel);	xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);	up->port.icount.tx++;	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)		uart_write_wakeup(&up->port);	return;ack_tx_int:	writeb(RES_Tx_P, &channel->control);	ZSDELAY();	ZS_WSYNC(channel);}static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id){	struct uart_ip22zilog_port *up = dev_id;	while (up) {		struct zilog_channel *channel			= ZILOG_CHANNEL_FROM_PORT(&up->port);		struct tty_struct *tty;		unsigned char r3;		spin_lock(&up->port.lock);		r3 = read_zsreg(channel, R3);		/* Channel A */		tty = NULL;		if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {			writeb(RES_H_IUS, &channel->control);			ZSDELAY();			ZS_WSYNC(channel);			if (r3 & CHARxIP)				tty = ip22zilog_receive_chars(up, channel);			if (r3 & CHAEXT)				ip22zilog_status_handle(up, channel);			if (r3 & CHATxIP)				ip22zilog_transmit_chars(up, channel);		}		spin_unlock(&up->port.lock);		if (tty)			tty_flip_buffer_push(tty);		/* Channel B */		up = up->next;		channel = ZILOG_CHANNEL_FROM_PORT(&up->port);		spin_lock(&up->port.lock);		tty = NULL;		if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {			writeb(RES_H_IUS, &channel->control);			ZSDELAY();			ZS_WSYNC(channel);			if (r3 & CHBRxIP)				tty = ip22zilog_receive_chars(up, channel);			if (r3 & CHBEXT)				ip22zilog_status_handle(up, channel);			if (r3 & CHBTxIP)				ip22zilog_transmit_chars(up, channel);		}		spin_unlock(&up->port.lock);		if (tty)			tty_flip_buffer_push(tty);		up = up->next;	}	return IRQ_HANDLED;}/* A convenient way to quickly get R0 status.  The caller must _not_ hold the * port lock, it is acquired here. */static __inline__ unsigned char ip22zilog_read_channel_status(struct uart_port *port){	struct zilog_channel *channel;	unsigned char status;	channel = ZILOG_CHANNEL_FROM_PORT(port);	status = readb(&channel->control);	ZSDELAY();	return status;}/* The port lock is not held.  */static unsigned int ip22zilog_tx_empty(struct uart_port *port){	unsigned long flags;	unsigned char status;	unsigned int ret;	spin_lock_irqsave(&port->lock, flags);	status = ip22zilog_read_channel_status(port);	spin_unlock_irqrestore(&port->lock, flags);	if (status & Tx_BUF_EMP)		ret = TIOCSER_TEMT;	else		ret = 0;	return ret;}/* The port lock is held and interrupts are disabled.  */static unsigned int ip22zilog_get_mctrl(struct uart_port *port){	unsigned char status;	unsigned int ret;	status = ip22zilog_read_channel_status(port);	ret = 0;	if (status & DCD)		ret |= TIOCM_CAR;	if (status & SYNC)		ret |= TIOCM_DSR;	if (status & CTS)		ret |= TIOCM_CTS;	return ret;}/* The port lock is held and interrupts are disabled.  */static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl){	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);	unsigned char set_bits, clear_bits;	set_bits = clear_bits = 0;	if (mctrl & TIOCM_RTS)		set_bits |= RTS;	else		clear_bits |= RTS;	if (mctrl & TIOCM_DTR)		set_bits |= DTR;	else		clear_bits |= DTR;	/* NOTE: Not subject to 'transmitter active' rule.  */	up->curregs[R5] |= set_bits;	up->curregs[R5] &= ~clear_bits;	write_zsreg(channel, R5, up->curregs[R5]);}/* The port lock is held and interrupts are disabled.  */static void ip22zilog_stop_tx(struct uart_port *port){	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;	up->flags |= IP22ZILOG_FLAG_TX_STOPPED;}/* The port lock is held and interrupts are disabled.  */static void ip22zilog_start_tx(struct uart_port *port){	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);	unsigned char status;	up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;	up->flags &= ~IP22ZILOG_FLAG_TX_STOPPED;	status = readb(&channel->control);	ZSDELAY();	/* TX busy?  Just wait for the TX done interrupt.  */	if (!(status & Tx_BUF_EMP))		return;	/* Send the first character to jump-start the TX done	 * IRQ sending engine.	 */	if (port->x_char) {		writeb(port->x_char, &channel->data);		ZSDELAY();		ZS_WSYNC(channel);		port->icount.tx++;		port->x_char = 0;	} else {		struct circ_buf *xmit = &port->info->xmit;		writeb(xmit->buf[xmit->tail], &channel->data);		ZSDELAY();		ZS_WSYNC(channel);		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);		port->icount.tx++;		if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)			uart_write_wakeup(&up->port);	}}/* The port lock is held and interrupts are disabled.  */static void ip22zilog_stop_rx(struct uart_port *port){	struct uart_ip22zilog_port *up = UART_ZILOG(port);	struct zilog_channel *channel;	if (ZS_IS_CONS(up))		return;	channel = ZILOG_CHANNEL_FROM_PORT(port);	/* Disable all RX interrupts.  */	up->curregs[R1] &= ~RxINT_MASK;	ip22zilog_maybe_update_regs(up, channel);}/* The port lock is held.  */static void ip22zilog_enable_ms(struct uart_port *port){	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);	unsigned char new_reg;	new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE);	if (new_reg != up->curregs[R15]) {		up->curregs[R15] = new_reg;		/* NOTE: Not subject to 'transmitter active' rule.  */		write_zsreg(channel, R15, up->curregs[R15]);	}}/* The port lock is not held.  */static void ip22zilog_break_ctl(struct uart_port *port, int break_state){	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);	unsigned char set_bits, clear_bits, new_reg;	unsigned long flags;	set_bits = clear_bits = 0;	if (break_state)		set_bits |= SND_BRK;	else		clear_bits |= SND_BRK;	spin_lock_irqsave(&port->lock, flags);	new_reg = (up->curregs[R5] | set_bits) & ~clear_bits;	if (new_reg != up->curregs[R5]) {		up->curregs[R5] = new_reg;		/* NOTE: Not subject to 'transmitter active' rule.  */		write_zsreg(channel, R5, up->curregs[R5]);	}	spin_unlock_irqrestore(&port->lock, flags);}static void __ip22zilog_reset(struct uart_ip22zilog_port *up){	struct zilog_channel *channel;	int i;	if (up->flags & IP22ZILOG_FLAG_RESET_DONE)		return;	/* Let pending transmits finish.  */	channel = ZILOG_CHANNEL_FROM_PORT(&up->port);	for (i = 0; i < 1000; i++) {		unsigned char stat = read_zsreg(channel, R1);		if (stat & ALL_SNT)			break;		udelay(100);	}	if (!ZS_IS_CHANNEL_A(up)) {		up++;		channel = ZILOG_CHANNEL_FROM_PORT(&up->port);	}	write_zsreg(channel, R9, FHWRES);	ZSDELAY_LONG();	(void) read_zsreg(channel, R0);	up->flags |= IP22ZILOG_FLAG_RESET_DONE;	up->next->flags |= IP22ZILOG_FLAG_RESET_DONE;}static void __ip22zilog_startup(struct uart_ip22zilog_port *up){	struct zilog_channel *channel;	channel = ZILOG_CHANNEL_FROM_PORT(&up->port);	__ip22zilog_reset(up);	__load_zsregs(channel, up->curregs);	/* set master interrupt enable */	write_zsreg(channel, R9, up->curregs[R9]);	up->prev_status = readb(&channel->control);	/* Enable receiver and transmitter.  */	up->curregs[R3] |= RxENAB;	up->curregs[R5] |= TxENAB;	up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;	ip22zilog_maybe_update_regs(up, channel);}static int ip22zilog_startup(struct uart_port *port){	struct uart_ip22zilog_port *up = UART_ZILOG(port);	unsigned long flags;	if (ZS_IS_CONS(up))		return 0;	spin_lock_irqsave(&port->lock, flags);	__ip22zilog_startup(up);	spin_unlock_irqrestore(&port->lock, flags);	return 0;}/* * The test for ZS_IS_CONS is explained by the following e-mail: ***** * From: Russell King <rmk@arm.linux.org.uk> * Date: Sun, 8 Dec 2002 10:18:38 +0000 * * On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote: * > I boot my 2.5 boxes using "console=ttyS0,9600" argument, * > and I noticed that something is not right with reference * > counting in this case. It seems that when the console * > is open by kernel initially, this is not accounted * > as an open, and uart_startup is not called. * * That is correct.  We are unable to call uart_startup when the serial * console is initialised because it may need to allocate memory (as * request_irq does) and the memory allocators may not have been * initialised. * * 1. initialise the port into a state where it can send characters in the *    console write method. * * 2. don't do the actual hardware shutdown in your shutdown() method (but *    do the normal software shutdown - ie, free irqs etc) ***** */static void ip22zilog_shutdown(struct uart_port *port){	struct uart_ip22zilog_port *up = UART_ZILOG(port);	struct zilog_channel *channel;	unsigned long flags;	if (ZS_IS_CONS(up))		return;	spin_lock_irqsave(&port->lock, flags);	channel = ZILOG_CHANNEL_FROM_PORT(port);	/* Disable receiver and transmitter.  */	up->curregs[R3] &= ~RxENAB;	up->curregs[R5] &= ~TxENAB;	/* Disable all interrupts and BRK assertion.  */	up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);	up->curregs[R5] &= ~SND_BRK;	ip22zilog_maybe_update_regs(up, channel);	spin_unlock_irqrestore(&port->lock, flags);}/* Shared by TTY driver and serial console setup.  The port lock is held * and local interrupts are disabled. */static voidip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag,		       unsigned int iflag, int brg){	up->curregs[R10] = NRZ;	up->curregs[R11] = TCBR | RCBR;	/* Program BAUD and clock source. */	up->curregs[R4] &= ~XCLK_MASK;	up->curregs[R4] |= X16CLK;	up->curregs[R12] = brg & 0xff;	up->curregs[R13] = (brg >> 8) & 0xff;	up->curregs[R14] = BRENAB;	/* Character size, stop bits, and parity. */

⌨️ 快捷键说明

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