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

📄 synclink_cs.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Returns:	0 if success, otherwise error code */static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params){ 	unsigned long flags;	MGSL_PARAMS tmp_params;	int err; 	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):set_params %s\n", __FILE__,__LINE__,			info->device_name );	COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS));	if (err) {		if ( debug_level >= DEBUG_LEVEL_INFO )			printk( "%s(%d):set_params(%s) user buffer copy failed\n",				__FILE__,__LINE__,info->device_name);		return -EFAULT;	}		spin_lock_irqsave(&info->lock,flags);	memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));	spin_unlock_irqrestore(&info->lock,flags);	 	mgslpc_change_params(info);		return 0;}static int get_txidle(MGSLPC_INFO * info, int __user *idle_mode){	int err;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("get_txidle(%s)=%d\n", info->device_name, info->idle_mode);	COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int));	if (err)		return -EFAULT;	return 0;}static int set_txidle(MGSLPC_INFO * info, int idle_mode){ 	unsigned long flags;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("set_txidle(%s,%d)\n", info->device_name, idle_mode);	spin_lock_irqsave(&info->lock,flags);	info->idle_mode = idle_mode;	tx_set_idle(info);	spin_unlock_irqrestore(&info->lock,flags);	return 0;}static int get_interface(MGSLPC_INFO * info, int __user *if_mode){	int err;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("get_interface(%s)=%d\n", info->device_name, info->if_mode);	COPY_TO_USER(err,if_mode, &info->if_mode, sizeof(int));	if (err)		return -EFAULT;	return 0;}static int set_interface(MGSLPC_INFO * info, int if_mode){ 	unsigned long flags;	unsigned char val;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("set_interface(%s,%d)\n", info->device_name, if_mode);	spin_lock_irqsave(&info->lock,flags);	info->if_mode = if_mode;	val = read_reg(info, PVR) & 0x0f;	switch (info->if_mode)	{	case MGSL_INTERFACE_RS232: val |= PVR_RS232; break;	case MGSL_INTERFACE_V35:   val |= PVR_V35;   break;	case MGSL_INTERFACE_RS422: val |= PVR_RS422; break;	}	write_reg(info, PVR, val);	spin_unlock_irqrestore(&info->lock,flags);	return 0;}static int set_txenable(MGSLPC_INFO * info, int enable){ 	unsigned long flags; 	if (debug_level >= DEBUG_LEVEL_INFO)		printk("set_txenable(%s,%d)\n", info->device_name, enable);				spin_lock_irqsave(&info->lock,flags);	if (enable) {		if (!info->tx_enabled)			tx_start(info);	} else {		if (info->tx_enabled)			tx_stop(info);	}	spin_unlock_irqrestore(&info->lock,flags);	return 0;}static int tx_abort(MGSLPC_INFO * info){ 	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 t

⌨️ 快捷键说明

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