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

📄 synclink_cs.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
{ 	unsigned long flags; 	if (debug_level >= DEBUG_LEVEL_INFO)		printk("tx_abort(%s)\n", info->device_name);				spin_lock_irqsave(&info->lock,flags);	if (info->tx_active && info->tx_count &&	    info->params.mode == MGSL_MODE_HDLC) {		/* clear data count so FIFO is not filled on next IRQ.		 * This results in underrun and abort transmission.		 */		info->tx_count = info->tx_put = info->tx_get = 0;		info->tx_aborting = TRUE;	}	spin_unlock_irqrestore(&info->lock,flags);	return 0;}static int set_rxenable(MGSLPC_INFO * info, int enable){ 	unsigned long flags; 	if (debug_level >= DEBUG_LEVEL_INFO)		printk("set_rxenable(%s,%d)\n", info->device_name, enable);				spin_lock_irqsave(&info->lock,flags);	if (enable) {		if (!info->rx_enabled)			rx_start(info);	} else {		if (info->rx_enabled)			rx_stop(info);	}	spin_unlock_irqrestore(&info->lock,flags);	return 0;}/* wait for specified event to occur * 	 * Arguments:	 	info	pointer to device instance data * 			mask	pointer to bitmask of events to wait for * Return Value:	0 	if successful and bit mask updated with *				of events triggerred, * 			otherwise error code */static int wait_events(MGSLPC_INFO * info, int __user *mask_ptr){ 	unsigned long flags;	int s;	int rc=0;	struct mgsl_icount cprev, cnow;	int events;	int mask;	struct	_input_signal_events oldsigs, newsigs;	DECLARE_WAITQUEUE(wait, current);	COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));	if (rc)		return  -EFAULT;		 	if (debug_level >= DEBUG_LEVEL_INFO)		printk("wait_events(%s,%d)\n", info->device_name, mask);	spin_lock_irqsave(&info->lock,flags);	/* return immediately if state matches requested events */	get_signals(info);	s = info->serial_signals;	events = mask &		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );	if (events) {		spin_unlock_irqrestore(&info->lock,flags);		goto exit;	}	/* save current irq counts */	cprev = info->icount;	oldsigs = info->input_signal_events;		if ((info->params.mode == MGSL_MODE_HDLC) &&	    (mask & MgslEvent_ExitHuntMode))		irq_enable(info, CHA, IRQ_EXITHUNT);		set_current_state(TASK_INTERRUPTIBLE);	add_wait_queue(&info->event_wait_q, &wait);		spin_unlock_irqrestore(&info->lock,flags);			for(;;) {		schedule();		if (signal_pending(current)) {			rc = -ERESTARTSYS;			break;		}					/* get current irq counts */		spin_lock_irqsave(&info->lock,flags);		cnow = info->icount;		newsigs = info->input_signal_events;		set_current_state(TASK_INTERRUPTIBLE);		spin_unlock_irqrestore(&info->lock,flags);		/* if no change, wait aborted for some reason */		if (newsigs.dsr_up   == oldsigs.dsr_up   &&		    newsigs.dsr_down == oldsigs.dsr_down &&		    newsigs.dcd_up   == oldsigs.dcd_up   &&		    newsigs.dcd_down == oldsigs.dcd_down &&		    newsigs.cts_up   == oldsigs.cts_up   &&		    newsigs.cts_down == oldsigs.cts_down &&		    newsigs.ri_up    == oldsigs.ri_up    &&		    newsigs.ri_down  == oldsigs.ri_down  &&		    cnow.exithunt    == cprev.exithunt   &&		    cnow.rxidle      == cprev.rxidle) {			rc = -EIO;			break;		}		events = mask &			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +			  (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +			  (newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +			  (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +			  (newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +			  (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +			  (newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +			  (newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +			  (cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );		if (events)			break;				cprev = cnow;		oldsigs = newsigs;	}		remove_wait_queue(&info->event_wait_q, &wait);	set_current_state(TASK_RUNNING);	if (mask & MgslEvent_ExitHuntMode) {		spin_lock_irqsave(&info->lock,flags);		if (!waitqueue_active(&info->event_wait_q))			irq_disable(info, CHA, IRQ_EXITHUNT);		spin_unlock_irqrestore(&info->lock,flags);	}exit:	if (rc == 0)		PUT_USER(rc, events, mask_ptr);	return rc;}static int modem_input_wait(MGSLPC_INFO *info,int arg){ 	unsigned long flags;	int rc;	struct mgsl_icount cprev, cnow;	DECLARE_WAITQUEUE(wait, current);	/* save current irq counts */	spin_lock_irqsave(&info->lock,flags);	cprev = info->icount;	add_wait_queue(&info->status_event_wait_q, &wait);	set_current_state(TASK_INTERRUPTIBLE);	spin_unlock_irqrestore(&info->lock,flags);	for(;;) {		schedule();		if (signal_pending(current)) {			rc = -ERESTARTSYS;			break;		}		/* get new irq counts */		spin_lock_irqsave(&info->lock,flags);		cnow = info->icount;		set_current_state(TASK_INTERRUPTIBLE);		spin_unlock_irqrestore(&info->lock,flags);		/* if no change, wait aborted for some reason */		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {			rc = -EIO;			break;		}		/* check for change in caller specified modem input */		if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||		    (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||		    (arg & TIOCM_CD  && cnow.dcd != cprev.dcd) ||		    (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {			rc = 0;			break;		}		cprev = cnow;	}	remove_wait_queue(&info->status_event_wait_q, &wait);	set_current_state(TASK_RUNNING);	return rc;}/* return the state of the serial control and status signals */static int tiocmget(struct tty_struct *tty, struct file *file){	MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;	unsigned int result; 	unsigned long flags;	spin_lock_irqsave(&info->lock,flags); 	get_signals(info);	spin_unlock_irqrestore(&info->lock,flags);	result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) +		((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) +		((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) +		((info->serial_signals & SerialSignal_RI)  ? TIOCM_RNG:0) +		((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) +		((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0);	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):%s tiocmget() value=%08X\n",			 __FILE__,__LINE__, info->device_name, result );	return result;}/* set modem control signals (DTR/RTS) */static int tiocmset(struct tty_struct *tty, struct file *file,		    unsigned int set, unsigned int clear){	MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; 	unsigned long flags;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):%s tiocmset(%x,%x)\n",			__FILE__,__LINE__,info->device_name, set, clear);	if (set & TIOCM_RTS)		info->serial_signals |= SerialSignal_RTS;	if (set & TIOCM_DTR)		info->serial_signals |= SerialSignal_DTR;	if (clear & TIOCM_RTS)		info->serial_signals &= ~SerialSignal_RTS;	if (clear & TIOCM_DTR)		info->serial_signals &= ~SerialSignal_DTR;	spin_lock_irqsave(&info->lock,flags); 	set_signals(info);	spin_unlock_irqrestore(&info->lock,flags);	return 0;}/* Set or clear transmit break condition * * Arguments:		tty		pointer to tty instance data *			break_state	-1=set break condition, 0=clear */static void mgslpc_break(struct tty_struct *tty, int break_state){	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;	unsigned long flags;		if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):mgslpc_break(%s,%d)\n",			 __FILE__,__LINE__, info->device_name, break_state);			 	if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break"))		return;	spin_lock_irqsave(&info->lock,flags); 	if (break_state == -1)		set_reg_bits(info, CHA+DAFO, BIT6);	else 		clear_reg_bits(info, CHA+DAFO, BIT6);	spin_unlock_irqrestore(&info->lock,flags);}/* Service an IOCTL request * 	 * Arguments: *  * 	tty	pointer to tty instance data * 	file	pointer to associated file object for device * 	cmd	IOCTL command code * 	arg	command argument/context * 	 * Return Value:	0 if success, otherwise error code */static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,			unsigned int cmd, unsigned long arg){	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;		if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,			info->device_name, cmd );		if (mgslpc_paranoia_check(info, tty->name, "mgslpc_ioctl"))		return -ENODEV;	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {		if (tty->flags & (1 << TTY_IO_ERROR))		    return -EIO;	}	return ioctl_common(info, cmd, arg);}int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg){	int error;	struct mgsl_icount cnow;	/* kernel counter temps */	struct serial_icounter_struct __user *p_cuser;	/* user space */	void __user *argp = (void __user *)arg;	unsigned long flags;		switch (cmd) {	case MGSL_IOCGPARAMS:		return get_params(info, argp);	case MGSL_IOCSPARAMS:		return set_params(info, argp);	case MGSL_IOCGTXIDLE:		return get_txidle(info, argp);	case MGSL_IOCSTXIDLE:		return set_txidle(info, (int)arg);	case MGSL_IOCGIF:		return get_interface(info, argp);	case MGSL_IOCSIF:		return set_interface(info,(int)arg);	case MGSL_IOCTXENABLE:		return set_txenable(info,(int)arg);	case MGSL_IOCRXENABLE:		return set_rxenable(info,(int)arg);	case MGSL_IOCTXABORT:		return tx_abort(info);	case MGSL_IOCGSTATS:		return get_stats(info, argp);	case MGSL_IOCWAITEVENT:		return wait_events(info, argp);	case TIOCMIWAIT:		return modem_input_wait(info,(int)arg);	case TIOCGICOUNT:		spin_lock_irqsave(&info->lock,flags);		cnow = info->icount;		spin_unlock_irqrestore(&info->lock,flags);		p_cuser = argp;		PUT_USER(error,cnow.cts, &p_cuser->cts);		if (error) return error;		PUT_USER(error,cnow.dsr, &p_cuser->dsr);		if (error) return error;		PUT_USER(error,cnow.rng, &p_cuser->rng);		if (error) return error;		PUT_USER(error,cnow.dcd, &p_cuser->dcd);		if (error) return error;		PUT_USER(error,cnow.rx, &p_cuser->rx);		if (error) return error;		PUT_USER(error,cnow.tx, &p_cuser->tx);		if (error) return error;		PUT_USER(error,cnow.frame, &p_cuser->frame);		if (error) return error;		PUT_USER(error,cnow.overrun, &p_cuser->overrun);		if (error) return error;		PUT_USER(error,cnow.parity, &p_cuser->parity);		if (error) return error;		PUT_USER(error,cnow.brk, &p_cuser->brk);		if (error) return error;		PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);		if (error) return error;		return 0;	default:		return -ENOIOCTLCMD;	}	return 0;}/* Set new termios settings * 	 * Arguments: *  * 	tty		pointer to tty structure * 	termios		pointer to buffer to hold returned old termios */static void mgslpc_set_termios(struct tty_struct *tty, struct termios *old_termios){	MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;	unsigned long flags;		if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):mgslpc_set_termios %s\n", __FILE__,__LINE__,			tty->driver->name );		/* just return if nothing has changed */	if ((tty->termios->c_cflag == old_termios->c_cflag)	    && (RELEVANT_IFLAG(tty->termios->c_iflag) 		== RELEVANT_IFLAG(old_termios->c_iflag)))	  return;	mgslpc_change_params(info);	/* Handle transition to B0 status */	if (old_termios->c_cflag & CBAUD &&	    !(tty->termios->c_cflag & CBAUD)) {		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);		spin_lock_irqsave(&info->lock,flags);	 	set_signals(info);		spin_unlock_irqrestore(&info->lock,flags);	}		/* Handle transition away from B0 status */	if (!(old_termios->c_cflag & CBAUD) &&	    tty->termios->c_cflag & CBAUD) {		info->serial_signals |= SerialSignal_DTR; 		if (!(tty->termios->c_cflag & CRTSCTS) ||  		    !test_bit(TTY_THROTTLED, &tty->flags)) {			info->serial_signals |= SerialSignal_RTS; 		}		spin_lock_irqsave(&info->lock,flags);	 	set_signals(info);		spin_unlock_irqrestore(&info->lock,flags);	}		/* Handle turning off CRTSCTS */	if (old_termios->c_cflag & CRTSCTS &&	    !(tty->termios->c_cflag & CRTSCTS)) {		tty->hw_stopped = 0;		tx_release(tty);	}}static void mgslpc_close(struct tty_struct *tty, struct file * filp){	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;	if (mgslpc_paranoia_check(info, tty->name, "mgslpc_close"))		return;		if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",			 __FILE__,__LINE__, info->device_name, info->count);			 	if (!info->count)		return;	if (tty_hung_up_p(filp))		goto cleanup;				if ((tty->count == 1) && (info->count != 1)) {		/*		 * tty->count is 1 and the tty structure will be freed.		 * info->count should be one in this case.		 * if it's not, correct it so that the port is shutdown.		 */		printk("mgslpc_close: bad refcount; tty->count is 1, "		       "info->count is %d\n", info->count);		info->count = 1;	}		info->count--;		/* if at least one open remaining, leave hardware active */	if (info->count)		goto cleanup;		info->flags |= ASYNC_CLOSING;		/* set tty->closing to notify line discipline to 	 * only process XON/XOFF characters. Only the N_TTY	 * discipline appears to use this (ppp does not).	 */	tty->closing = 1;		/* wait for transmit data to clear all layers */		if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) {		if (debug_level >= DEBUG_LEVEL_INFO)			printk("%s(%d):mgslpc_close(%s) calling tty_wait_until_sent\n",				 __FILE__,__LINE__, info->device_name );		tty_wait_until_sent(tty, info->closing_wait);	}		 	if (info->flags & ASYNC_INITIALIZED) 		mgslpc_wait_until_sent(tty, info->timeout);	if (tty->driver->flush_buffer)		tty->driver->flush_buffer(tty);	ldisc_flush_buff

⌨️ 快捷键说明

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