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

📄 synclink_cs.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		data   = read_reg(info, CHA + RXFIFO);		status = read_reg(info, CHA + RXFIFO);		fifo_count -= 2;		icount->rx++;		flag = TTY_NORMAL;		// if no frameing/crc error then save data		// BIT7:parity error		// BIT6:framing error		if (status & (BIT7 + BIT6)) {			if (status & BIT7) 				icount->parity++;			else				icount->frame++;			/* discard char if tty control flags say so */			if (status & info->ignore_status_mask)				continue;							status &= info->read_status_mask;			if (status & BIT7)				flag = TTY_PARITY;			else if (status & BIT6)				flag = TTY_FRAME;		}		work += tty_insert_flip_char(tty, data, flag);	}	issue_command(info, CHA, CMD_RXFIFO);	if (debug_level >= DEBUG_LEVEL_ISR) {		printk("%s(%d):rx_ready_async",			__FILE__,__LINE__);		printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",			__FILE__,__LINE__,icount->rx,icount->brk,			icount->parity,icount->frame,icount->overrun);	}				if (work)		tty_flip_buffer_push(tty);}static void tx_done(MGSLPC_INFO *info){	if (!info->tx_active)		return;				info->tx_active = 0;	info->tx_aborting = 0;	if (info->params.mode == MGSL_MODE_ASYNC)		return;	info->tx_count = info->tx_put = info->tx_get = 0;	del_timer(&info->tx_timer);			if (info->drop_rts_on_tx_done) {		get_signals(info);		if (info->serial_signals & SerialSignal_RTS) {			info->serial_signals &= ~SerialSignal_RTS;			set_signals(info);		}		info->drop_rts_on_tx_done = 0;	}#ifdef CONFIG_HDLC	if (info->netcount)		hdlcdev_tx_done(info);	else #endif	{		if (info->tty->stopped || info->tty->hw_stopped) {			tx_stop(info);			return;		}		info->pending_bh |= BH_TRANSMIT;	}}static void tx_ready(MGSLPC_INFO *info){	unsigned char fifo_count = 32;	int c;	if (debug_level >= DEBUG_LEVEL_ISR)		printk("%s(%d):tx_ready(%s)\n", __FILE__,__LINE__,info->device_name);	if (info->params.mode == MGSL_MODE_HDLC) {		if (!info->tx_active)			return;	} else {		if (info->tty->stopped || info->tty->hw_stopped) {			tx_stop(info);			return;		}		if (!info->tx_count)			info->tx_active = 0;	}	if (!info->tx_count)		return;	while (info->tx_count && fifo_count) {		c = min(2, min_t(int, fifo_count, min(info->tx_count, TXBUFSIZE - info->tx_get)));				if (c == 1) {			write_reg(info, CHA + TXFIFO, *(info->tx_buf + info->tx_get));		} else {			write_reg16(info, CHA + TXFIFO,					  *((unsigned short*)(info->tx_buf + info->tx_get)));		}		info->tx_count -= c;		info->tx_get = (info->tx_get + c) & (TXBUFSIZE - 1);		fifo_count -= c;	}	if (info->params.mode == MGSL_MODE_ASYNC) {		if (info->tx_count < WAKEUP_CHARS)			info->pending_bh |= BH_TRANSMIT;		issue_command(info, CHA, CMD_TXFIFO);	} else {		if (info->tx_count)			issue_command(info, CHA, CMD_TXFIFO);		else			issue_command(info, CHA, CMD_TXFIFO + CMD_TXEOM);	}}static void cts_change(MGSLPC_INFO *info){	get_signals(info);	if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)		irq_disable(info, CHB, IRQ_CTS);	info->icount.cts++;	if (info->serial_signals & SerialSignal_CTS)		info->input_signal_events.cts_up++;	else		info->input_signal_events.cts_down++;	wake_up_interruptible(&info->status_event_wait_q);	wake_up_interruptible(&info->event_wait_q);	if (info->flags & ASYNC_CTS_FLOW) {		if (info->tty->hw_stopped) {			if (info->serial_signals & SerialSignal_CTS) {				if (debug_level >= DEBUG_LEVEL_ISR)					printk("CTS tx start...");				if (info->tty)					info->tty->hw_stopped = 0;				tx_start(info);				info->pending_bh |= BH_TRANSMIT;				return;			}		} else {			if (!(info->serial_signals & SerialSignal_CTS)) {				if (debug_level >= DEBUG_LEVEL_ISR)					printk("CTS tx stop...");				if (info->tty)					info->tty->hw_stopped = 1;				tx_stop(info);			}		}	}	info->pending_bh |= BH_STATUS;}static void dcd_change(MGSLPC_INFO *info){	get_signals(info);	if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)		irq_disable(info, CHB, IRQ_DCD);	info->icount.dcd++;	if (info->serial_signals & SerialSignal_DCD) {		info->input_signal_events.dcd_up++;	}	else		info->input_signal_events.dcd_down++;#ifdef CONFIG_HDLC	if (info->netcount)		hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, info->netdev);#endif	wake_up_interruptible(&info->status_event_wait_q);	wake_up_interruptible(&info->event_wait_q);	if (info->flags & ASYNC_CHECK_CD) {		if (debug_level >= DEBUG_LEVEL_ISR)			printk("%s CD now %s...", info->device_name,			       (info->serial_signals & SerialSignal_DCD) ? "on" : "off");		if (info->serial_signals & SerialSignal_DCD)			wake_up_interruptible(&info->open_wait);		else {			if (debug_level >= DEBUG_LEVEL_ISR)				printk("doing serial hangup...");			if (info->tty)				tty_hangup(info->tty);		}	}	info->pending_bh |= BH_STATUS;}static void dsr_change(MGSLPC_INFO *info){	get_signals(info);	if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)		port_irq_disable(info, PVR_DSR);	info->icount.dsr++;	if (info->serial_signals & SerialSignal_DSR)		info->input_signal_events.dsr_up++;	else		info->input_signal_events.dsr_down++;	wake_up_interruptible(&info->status_event_wait_q);	wake_up_interruptible(&info->event_wait_q);	info->pending_bh |= BH_STATUS;}static void ri_change(MGSLPC_INFO *info){	get_signals(info);	if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)		port_irq_disable(info, PVR_RI);	info->icount.rng++;	if (info->serial_signals & SerialSignal_RI)		info->input_signal_events.ri_up++;	else		info->input_signal_events.ri_down++;	wake_up_interruptible(&info->status_event_wait_q);	wake_up_interruptible(&info->event_wait_q);	info->pending_bh |= BH_STATUS;}/* Interrupt service routine entry point. * 	 * Arguments: *  * irq     interrupt number that caused interrupt * dev_id  device ID supplied during interrupt registration * regs    interrupted processor context */static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs){	MGSLPC_INFO * info = (MGSLPC_INFO *)dev_id;	unsigned short isr;	unsigned char gis, pis;	int count=0;	if (debug_level >= DEBUG_LEVEL_ISR)			printk("mgslpc_isr(%d) entry.\n", irq);	if (!info)		return IRQ_NONE;			if (!(info->p_dev->_locked))		return IRQ_HANDLED;	spin_lock(&info->lock);	while ((gis = read_reg(info, CHA + GIS))) {		if (debug_level >= DEBUG_LEVEL_ISR)				printk("mgslpc_isr %s gis=%04X\n", info->device_name,gis);		if ((gis & 0x70) || count > 1000) {			printk("synclink_cs:hardware failed or ejected\n");			break;		}		count++;		if (gis & (BIT1 + BIT0)) {			isr = read_reg16(info, CHB + ISR);			if (isr & IRQ_DCD)				dcd_change(info);			if (isr & IRQ_CTS)				cts_change(info);		}		if (gis & (BIT3 + BIT2))		{			isr = read_reg16(info, CHA + ISR);			if (isr & IRQ_TIMER) {				info->irq_occurred = 1;				irq_disable(info, CHA, IRQ_TIMER);			}			/* receive IRQs */ 			if (isr & IRQ_EXITHUNT) {				info->icount.exithunt++;				wake_up_interruptible(&info->event_wait_q);			}			if (isr & IRQ_BREAK_ON) {				info->icount.brk++;				if (info->flags & ASYNC_SAK)					do_SAK(info->tty);			}			if (isr & IRQ_RXTIME) {				issue_command(info, CHA, CMD_RXFIFO_READ);			}			if (isr & (IRQ_RXEOM + IRQ_RXFIFO)) {				if (info->params.mode == MGSL_MODE_HDLC)					rx_ready_hdlc(info, isr & IRQ_RXEOM); 				else					rx_ready_async(info, isr & IRQ_RXEOM);			}			/* transmit IRQs */ 			if (isr & IRQ_UNDERRUN) {				if (info->tx_aborting)					info->icount.txabort++;				else					info->icount.txunder++;				tx_done(info);			}			else if (isr & IRQ_ALLSENT) {				info->icount.txok++;				tx_done(info);			}			else if (isr & IRQ_TXFIFO)				tx_ready(info);		}		if (gis & BIT7) {			pis = read_reg(info, CHA + PIS);			if (pis & BIT1)				dsr_change(info);			if (pis & BIT2)				ri_change(info);		}	}		/* Request bottom half processing if there's something 	 * for it to do and the bh is not already running	 */	if (info->pending_bh && !info->bh_running && !info->bh_requested) {		if ( debug_level >= DEBUG_LEVEL_ISR )				printk("%s(%d):%s queueing bh task.\n",				__FILE__,__LINE__,info->device_name);		schedule_work(&info->task);		info->bh_requested = 1;	}	spin_unlock(&info->lock);		if (debug_level >= DEBUG_LEVEL_ISR)			printk("%s(%d):mgslpc_isr(%d)exit.\n",		       __FILE__,__LINE__,irq);	return IRQ_HANDLED;}/* Initialize and start device. */static int startup(MGSLPC_INFO * info){	int retval = 0;		if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):startup(%s)\n",__FILE__,__LINE__,info->device_name);			if (info->flags & ASYNC_INITIALIZED)		return 0;		if (!info->tx_buf) {		/* allocate a page of memory for a transmit buffer */		info->tx_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);		if (!info->tx_buf) {			printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",				__FILE__,__LINE__,info->device_name);			return -ENOMEM;		}	}	info->pending_bh = 0;		memset(&info->icount, 0, sizeof(info->icount));	init_timer(&info->tx_timer);	info->tx_timer.data = (unsigned long)info;	info->tx_timer.function = tx_timeout;	/* Allocate and claim adapter resources */	retval = claim_resources(info);		/* perform existance check and diagnostics */	if ( !retval )		retval = adapter_test(info);			if ( retval ) {  		if (capable(CAP_SYS_ADMIN) && info->tty)			set_bit(TTY_IO_ERROR, &info->tty->flags);		release_resources(info);  		return retval;  	}	/* program hardware for current parameters */	mgslpc_change_params(info);		if (info->tty)		clear_bit(TTY_IO_ERROR, &info->tty->flags);	info->flags |= ASYNC_INITIALIZED;		return 0;}/* Called by mgslpc_close() and mgslpc_hangup() to shutdown hardware */static void shutdown(MGSLPC_INFO * info){	unsigned long flags;		if (!(info->flags & ASYNC_INITIALIZED))		return;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):mgslpc_shutdown(%s)\n",			 __FILE__,__LINE__, info->device_name );	/* clear status wait queue because status changes */	/* can't happen after shutting down the hardware */	wake_up_interruptible(&info->status_event_wait_q);	wake_up_interruptible(&info->event_wait_q);	del_timer(&info->tx_timer);		if (info->tx_buf) {		free_page((unsigned long) info->tx_buf);		info->tx_buf = NULL;	}	spin_lock_irqsave(&info->lock,flags);	rx_stop(info);	tx_stop(info);	/* TODO:disable interrupts instead of reset to preserve signal states */	reset_device(info);	 	if (!info->tty || info->tty->termios->c_cflag & HUPCL) { 		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);		set_signals(info);	}		spin_unlock_irqrestore(&info->lock,flags);	release_resources(info);			if (info->tty)		set_bit(TTY_IO_ERROR, &info->tty->flags);	info->flags &= ~ASYNC_INITIALIZED;}static void mgslpc_program_hw(MGSLPC_INFO *info){	unsigned long flags;	spin_lock_irqsave(&info->lock,flags);		rx_stop(info);	tx_stop(info);	info->tx_count = info->tx_put = info->tx_get = 0;		if (info->params.mode == MGSL_MODE_HDLC || info->netcount)		hdlc_mode(info);	else		async_mode(info);			set_signals(info);		info->dcd_chkcount = 0;	info->cts_chkcount = 0;	info->ri_chkcount = 0;	info->dsr_chkcount = 0;	irq_enable(info, CHB, IRQ_DCD | IRQ_CTS);	port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI);	get_signals(info);			if (info->netcount || info->tty->termios->c_cflag & CREAD)		rx_start(info);			spin_unlock_irqrestore(&info->lock,flags);}/* Reconfigure adapter based on new parameters */static void mgslpc_change_params(MGSLPC_INFO *info){	unsigned cflag;	int bits_per_char;	if (!info->tty || !info->tty->termios)		return;			if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):mgslpc_change_params(%s)\n",			 __FILE__,__LINE__, info->device_name );			 	cflag = info->tty->termios->c_cflag;

⌨️ 快捷键说明

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