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

📄 serial.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
e100_disable_txdma_channel(struct e100_serial *info){	unsigned long flags;  	/* Disable output DMA channel for the serial port in question	 * ( set to something other then serialX)	 */	save_flags(flags);	cli();	DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line));	if (info->line == 0) {		if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) ==		    IO_STATE(R_GEN_CONFIG, dma6, serial0)) {			genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma6);			genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused);		}	} else if (info->line == 1) {		if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma8)) ==		    IO_STATE(R_GEN_CONFIG, dma8, serial1)) {			genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma8);			genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb);		}	} else if (info->line == 2) {		if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma2)) ==		    IO_STATE(R_GEN_CONFIG, dma2, serial2)) {			genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma2);			genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0);		}	} else if (info->line == 3) {		if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma4)) ==		    IO_STATE(R_GEN_CONFIG, dma4, serial3)) {			genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma4);			genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1);		}	}	*R_GEN_CONFIG = genconfig_shadow;	restore_flags(flags);}static _INLINE_ voide100_enable_txdma_channel(struct e100_serial *info){	unsigned long flags;  	save_flags(flags);	cli();	DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line));	/* Enable output DMA channel for the serial port in question */	if (info->line == 0) {		genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma6);		genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, serial0);	} else if (info->line == 1) {		genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma8);		genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, serial1);	} else if (info->line == 2) {		genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma2);		genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, serial2);	} else if (info->line == 3) {		genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma4);		genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3);	}	*R_GEN_CONFIG = genconfig_shadow;	restore_flags(flags);}static _INLINE_ voide100_disable_rxdma_channel(struct e100_serial *info){	unsigned long flags;  	/* Disable input DMA channel for the serial port in question	 * ( set to something other then serialX)	 */	save_flags(flags);	cli();  	if (info->line == 0) {		if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) ==		    IO_STATE(R_GEN_CONFIG, dma7, serial0)) {			genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma7);			genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma7, unused);		}	} else if (info->line == 1) {		if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma9)) ==		    IO_STATE(R_GEN_CONFIG, dma9, serial1)) {			genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma9);			genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma9, usb);		}	} else if (info->line == 2) {		if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma3)) ==		    IO_STATE(R_GEN_CONFIG, dma3, serial2)) {			genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma3);			genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, par0);		}	} else if (info->line == 3) {		if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma5)) ==		    IO_STATE(R_GEN_CONFIG, dma5, serial3)) {			genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma5);			genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, par1);		}	}	*R_GEN_CONFIG = genconfig_shadow;	restore_flags(flags);}static _INLINE_ voide100_enable_rxdma_channel(struct e100_serial *info){	unsigned long flags;  	save_flags(flags);	cli();  	/* Enable input DMA channel for the serial port in question */	if (info->line == 0) {		genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma7);		genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma7, serial0);	} else if (info->line == 1) {		genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma9);		genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma9, serial1);	} else if (info->line == 2) {		genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma3);		genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, serial2);	} else if (info->line == 3) {		genconfig_shadow &=  ~IO_MASK(R_GEN_CONFIG, dma5);		genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3);	}	*R_GEN_CONFIG = genconfig_shadow;	restore_flags(flags);}#ifdef SERIAL_HANDLE_EARLY_ERRORS/* in order to detect and fix errors on the first byte   we have to use the serial interrupts as well. */static inline voide100_disable_serial_data_irq(struct e100_serial *info) {#ifdef SERIAL_DEBUG_INTR	printk("ser_irq(%d): 0\n",info->line);#endif	DINTR1(DEBUG_LOG(info->line,"IRQ disable data_irq %i\n", info->line));	*R_IRQ_MASK1_CLR = (1U << (8+2*info->line));}static inline voide100_enable_serial_data_irq(struct e100_serial *info) {#ifdef SERIAL_DEBUG_INTR	printk("ser_irq(%d): 1\n",info->line);	printk("**** %d = %d\n",	       (8+2*info->line),	       (1U << (8+2*info->line)));#endif	DINTR1(DEBUG_LOG(info->line,"IRQ enable data_irq %i\n", info->line));	*R_IRQ_MASK1_SET = (1U << (8+2*info->line));}#endifstatic inline voide100_disable_serial_tx_ready_irq(struct e100_serial *info) {#ifdef SERIAL_DEBUG_INTR	printk("ser_tx_irq(%d): 0\n",info->line);#endif	DINTR1(DEBUG_LOG(info->line,"IRQ disable ready_irq %i\n", info->line));	*R_IRQ_MASK1_CLR = (1U << (8+1+2*info->line));}static inline voide100_enable_serial_tx_ready_irq(struct e100_serial *info) {#ifdef SERIAL_DEBUG_INTR	printk("ser_tx_irq(%d): 1\n",info->line);	printk("**** %d = %d\n",	       (8+1+2*info->line),	       (1U << (8+1+2*info->line)));#endif	DINTR2(DEBUG_LOG(info->line,"IRQ enable ready_irq %i\n", info->line));	*R_IRQ_MASK1_SET = (1U << (8+1+2*info->line));}static inline void e100_enable_rx_irq(struct e100_serial *info){	if (info->uses_dma_in)		e100_enable_rxdma_irq(info);	else		e100_enable_serial_data_irq(info);}static inline void e100_disable_rx_irq(struct e100_serial *info){	if (info->uses_dma_in)		e100_disable_rxdma_irq(info);	else		e100_disable_serial_data_irq(info);}#if defined(CONFIG_ETRAX_RS485)/* Enable RS-485 mode on selected port. This is UGLY. */static inte100_enable_rs485(struct tty_struct *tty,struct rs485_control *r){	struct e100_serial * info = (struct e100_serial *)tty->driver_data;#if defined(CONFIG_ETRAX_RS485_ON_PA)		*R_PORT_PA_DATA = port_pa_data_shadow |= (1 << rs485_pa_bit);#endif	info->rs485.rts_on_send = 0x01 & r->rts_on_send;	info->rs485.rts_after_sent = 0x01 & r->rts_after_sent;	if (r->delay_rts_before_send >= 1000)		info->rs485.delay_rts_before_send = 1000;	else		info->rs485.delay_rts_before_send = r->delay_rts_before_send;	info->rs485.enabled = r->enabled;/*	printk("rts: on send = %i, after = %i, enabled = %i",		    info->rs485.rts_on_send,		    info->rs485.rts_after_sent,		    info->rs485.enabled	);*/			return 0;}static inte100_write_rs485(struct tty_struct *tty, int from_user,                 const unsigned char *buf, int count){	struct e100_serial * info = (struct e100_serial *)tty->driver_data;	int old_enabled = info->rs485.enabled;	/* rs485 is always implicitly enabled if we're using the ioctl() 	 * but it doesn't have to be set in the rs485_control	 * (to be backward compatible with old apps)	 * So we store, set and restore it.	 */	info->rs485.enabled = 1;	/* rs_write now deals with RS485 if enabled */	count = rs_write(tty, from_user, buf, count);	info->rs485.enabled = old_enabled;	return count;}#ifdef CONFIG_ETRAX_FAST_TIMER/* Timer function to toggle RTS when using FAST_TIMER */static void rs485_toggle_rts_timer_function(unsigned long data){	struct e100_serial *info = (struct e100_serial *)data;	fast_timers_rs485[info->line].function = NULL;	e100_rts(info, info->rs485.rts_after_sent);#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)	e100_enable_rx(info);	e100_enable_rx_irq(info);	#endif}#endif#endif /* CONFIG_ETRAX_RS485 *//* * ------------------------------------------------------------ * rs_stop() and rs_start() * * This routines are called before setting or resetting tty->stopped. * They enable or disable transmitter using the XOFF registers, as necessary. * ------------------------------------------------------------ */static void rs_stop(struct tty_struct *tty){	struct e100_serial *info = (struct e100_serial *)tty->driver_data;	if (info) {		unsigned long flags;		unsigned long xoff;		save_flags(flags); cli();		DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n",				CIRC_CNT(info->xmit.head,					 info->xmit.tail,SERIAL_XMIT_SIZE)));				xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->tty));		xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop);		if (tty->termios->c_iflag & IXON ) {			xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);		}			*((unsigned long *)&info->port[REG_XOFF]) = xoff;		restore_flags(flags);	}}static void rs_start(struct tty_struct *tty){	struct e100_serial *info = (struct e100_serial *)tty->driver_data;	if (info) {		unsigned long flags;		unsigned long xoff;		save_flags(flags); cli();		DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n",				CIRC_CNT(info->xmit.head,					 info->xmit.tail,SERIAL_XMIT_SIZE)));		xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty));		xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);		if (tty->termios->c_iflag & IXON ) {			xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);		}			*((unsigned long *)&info->port[REG_XOFF]) = xoff;		if (!info->uses_dma_out &&		    info->xmit.head != info->xmit.tail && info->xmit.buf)			e100_enable_serial_tx_ready_irq(info);				restore_flags(flags);	}}/* * ---------------------------------------------------------------------- * * Here starts the interrupt handling routines.  All of the following * subroutines are declared as inline and are folded into * rs_interrupt().  They were separated out for readability's sake. * * Note: rs_interrupt() is a "fast" interrupt, which means that it * runs with interrupts turned off.  People who may want to modify * rs_interrupt() should try to keep the interrupt handler as fast as * possible.  After you are done making modifications, it is not a bad * idea to do: *  * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c * * and look at the resulting assemble code in serial.s. * * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93 * ----------------------------------------------------------------------- *//* * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. */static _INLINE_ void rs_sched_event(struct e100_serial *info,				    int event){	if (info->event & (1 << event))		return;	info->event |= 1 << event;	queue_task(&info->tqueue, &tq_serial);	mark_bh(SERIAL_BH);}/* The output DMA channel is free - use it to send as many chars as possible * NOTES: *   We don't pay attention to info->x_char, which means if the TTY wants to *   use XON/XOFF it will set info->x_char but we won't send any X char! *  *   To implement this, we'd just start a DMA send of 1 byte pointing at a *   buffer containing the X char, and skip updating xmit. We'd also have to *   check if the last sent char was the X char when we enter this function *   the next time, to avoid updating xmit with the sent X value. */static void transmit_chars_dma(struct e100_serial *info){	unsigned int c, sentl;	struct etrax_dma_descr *descr;#ifdef CONFIG_SVINTO_SIM	/* This will output too little if tail is not 0 always since	 * we don't reloop to send the other part. Anyway this SHOULD be a	 * no-op - transmit_chars_dma would never really be called during sim	 * since rs_write does not write into the xmit buffer then.	 */	if (info->xmit.tail)		printk("Error in serial.c:transmit_chars_dma(), tail!=0\n");	if (info->xmit.head != info->xmit.tail) {		SIMCOUT(info->xmit.buf + info->xmit.tail,			CIRC_CNT(info->xmit.head,				 info->xmit.tail,				 SERIAL_XMIT_SIZE));		info->xmit.head = info->xmit.tail;  /* move back head */		info->tr_running = 0;	}	return;#endif	/* acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */	*info->oclrintradr =		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |		IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);#ifdef SERIAL_DEBUG_INTR	if (info->line == SERIAL_DEBUG_LINE)		printk("tc\n");#endif	if (!info->tr_running) {		/* weirdo... we shouldn't get here! */		printk(KERN_WARNING "Achtung: transmit_chars_dma with !tr_running\n");		return;	}	descr = &info->tr_descr;	/* first get the amount of bytes sent during the last DMA transfer,	   and u

⌨️ 快捷键说明

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