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

📄 synclink_gt.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * Note: use tight timings here to satisfy the NIST-PCTS.	 */	if (info->params.data_rate) {	       	char_time = info->timeout/(32 * 5);		if (!char_time)			char_time++;	} else		char_time = 1;	if (timeout)		char_time = min_t(unsigned long, char_time, timeout);	while (info->tx_active) {		msleep_interruptible(jiffies_to_msecs(char_time));		if (signal_pending(current))			break;		if (timeout && time_after(jiffies, orig_jiffies + timeout))			break;	}exit:	DBGINFO(("%s wait_until_sent exit\n", info->device_name));}static int write_room(struct tty_struct *tty){	struct slgt_info *info = tty->driver_data;	int ret;	if (sanity_check(info, tty->name, "write_room"))		return 0;	ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;	DBGINFO(("%s write_room=%d\n", info->device_name, ret));	return ret;}static void flush_chars(struct tty_struct *tty){	struct slgt_info *info = tty->driver_data;	unsigned long flags;	if (sanity_check(info, tty->name, "flush_chars"))		return;	DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count));	if (info->tx_count <= 0 || tty->stopped ||	    tty->hw_stopped || !info->tx_buf)		return;	DBGINFO(("%s flush_chars start transmit\n", info->device_name));	spin_lock_irqsave(&info->lock,flags);	if (!info->tx_active && info->tx_count) {		tx_load(info, info->tx_buf,info->tx_count);	 	tx_start(info);	}	spin_unlock_irqrestore(&info->lock,flags);}static void flush_buffer(struct tty_struct *tty){	struct slgt_info *info = tty->driver_data;	unsigned long flags;	if (sanity_check(info, tty->name, "flush_buffer"))		return;	DBGINFO(("%s flush_buffer\n", info->device_name));	spin_lock_irqsave(&info->lock,flags);	if (!info->tx_active)		info->tx_count = 0;	spin_unlock_irqrestore(&info->lock,flags);	tty_wakeup(tty);}/* * throttle (stop) transmitter */static void tx_hold(struct tty_struct *tty){	struct slgt_info *info = tty->driver_data;	unsigned long flags;	if (sanity_check(info, tty->name, "tx_hold"))		return;	DBGINFO(("%s tx_hold\n", info->device_name));	spin_lock_irqsave(&info->lock,flags);	if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC)	 	tx_stop(info);	spin_unlock_irqrestore(&info->lock,flags);}/* * release (start) transmitter */static void tx_release(struct tty_struct *tty){	struct slgt_info *info = tty->driver_data;	unsigned long flags;	if (sanity_check(info, tty->name, "tx_release"))		return;	DBGINFO(("%s tx_release\n", info->device_name));	spin_lock_irqsave(&info->lock,flags);	if (!info->tx_active && info->tx_count) {		tx_load(info, info->tx_buf, info->tx_count);	 	tx_start(info);	}	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 0 if success, otherwise error code */static int ioctl(struct tty_struct *tty, struct file *file,		 unsigned int cmd, unsigned long arg){	struct slgt_info *info = tty->driver_data;	struct mgsl_icount cnow;	/* kernel counter temps */	struct serial_icounter_struct __user *p_cuser;	/* user space */	unsigned long flags;	void __user *argp = (void __user *)arg;	if (sanity_check(info, tty->name, "ioctl"))		return -ENODEV;	DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {		if (tty->flags & (1 << TTY_IO_ERROR))		    return -EIO;	}	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_IOCTXENABLE:		return tx_enable(info, (int)arg);	case MGSL_IOCRXENABLE:		return rx_enable(info, (int)arg);	case MGSL_IOCTXABORT:		return tx_abort(info);	case MGSL_IOCGSTATS:		return get_stats(info, argp);	case MGSL_IOCWAITEVENT:		return wait_mgsl_event(info, argp);	case TIOCMIWAIT:		return modem_input_wait(info,(int)arg);	case MGSL_IOCGIF:		return get_interface(info, argp);	case MGSL_IOCSIF:		return set_interface(info,(int)arg);	case MGSL_IOCSGPIO:		return set_gpio(info, argp);	case MGSL_IOCGGPIO:		return get_gpio(info, argp);	case MGSL_IOCWAITGPIO:		return wait_gpio(info, argp);	case TIOCGICOUNT:		spin_lock_irqsave(&info->lock,flags);		cnow = info->icount;		spin_unlock_irqrestore(&info->lock,flags);		p_cuser = argp;		if (put_user(cnow.cts, &p_cuser->cts) ||		    put_user(cnow.dsr, &p_cuser->dsr) ||		    put_user(cnow.rng, &p_cuser->rng) ||		    put_user(cnow.dcd, &p_cuser->dcd) ||		    put_user(cnow.rx, &p_cuser->rx) ||		    put_user(cnow.tx, &p_cuser->tx) ||		    put_user(cnow.frame, &p_cuser->frame) ||		    put_user(cnow.overrun, &p_cuser->overrun) ||		    put_user(cnow.parity, &p_cuser->parity) ||		    put_user(cnow.brk, &p_cuser->brk) ||		    put_user(cnow.buf_overrun, &p_cuser->buf_overrun))			return -EFAULT;		return 0;	default:		return -ENOIOCTLCMD;	}	return 0;}/* * support for 32 bit ioctl calls on 64 bit systems */#ifdef CONFIG_COMPATstatic long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params){	struct MGSL_PARAMS32 tmp_params;	DBGINFO(("%s get_params32\n", info->device_name));	tmp_params.mode            = (compat_ulong_t)info->params.mode;	tmp_params.loopback        = info->params.loopback;	tmp_params.flags           = info->params.flags;	tmp_params.encoding        = info->params.encoding;	tmp_params.clock_speed     = (compat_ulong_t)info->params.clock_speed;	tmp_params.addr_filter     = info->params.addr_filter;	tmp_params.crc_type        = info->params.crc_type;	tmp_params.preamble_length = info->params.preamble_length;	tmp_params.preamble        = info->params.preamble;	tmp_params.data_rate       = (compat_ulong_t)info->params.data_rate;	tmp_params.data_bits       = info->params.data_bits;	tmp_params.stop_bits       = info->params.stop_bits;	tmp_params.parity          = info->params.parity;	if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32)))		return -EFAULT;	return 0;}static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params){	struct MGSL_PARAMS32 tmp_params;	DBGINFO(("%s set_params32\n", info->device_name));	if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32)))		return -EFAULT;	spin_lock(&info->lock);	info->params.mode            = tmp_params.mode;	info->params.loopback        = tmp_params.loopback;	info->params.flags           = tmp_params.flags;	info->params.encoding        = tmp_params.encoding;	info->params.clock_speed     = tmp_params.clock_speed;	info->params.addr_filter     = tmp_params.addr_filter;	info->params.crc_type        = tmp_params.crc_type;	info->params.preamble_length = tmp_params.preamble_length;	info->params.preamble        = tmp_params.preamble;	info->params.data_rate       = tmp_params.data_rate;	info->params.data_bits       = tmp_params.data_bits;	info->params.stop_bits       = tmp_params.stop_bits;	info->params.parity          = tmp_params.parity;	spin_unlock(&info->lock); 	change_params(info);	return 0;}static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,			 unsigned int cmd, unsigned long arg){	struct slgt_info *info = tty->driver_data;	int rc = -ENOIOCTLCMD;	if (sanity_check(info, tty->name, "compat_ioctl"))		return -ENODEV;	DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd));	switch (cmd) {	case MGSL_IOCSPARAMS32:		rc = set_params32(info, compat_ptr(arg));		break;	case MGSL_IOCGPARAMS32:		rc = get_params32(info, compat_ptr(arg));		break;	case MGSL_IOCGPARAMS:	case MGSL_IOCSPARAMS:	case MGSL_IOCGTXIDLE:	case MGSL_IOCGSTATS:	case MGSL_IOCWAITEVENT:	case MGSL_IOCGIF:	case MGSL_IOCSGPIO:	case MGSL_IOCGGPIO:	case MGSL_IOCWAITGPIO:	case TIOCGICOUNT:		rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));		break;	case MGSL_IOCSTXIDLE:	case MGSL_IOCTXENABLE:	case MGSL_IOCRXENABLE:	case MGSL_IOCTXABORT:	case TIOCMIWAIT:	case MGSL_IOCSIF:		rc = ioctl(tty, file, cmd, arg);		break;	}	DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc));	return rc;}#else#define slgt_compat_ioctl NULL#endif /* ifdef CONFIG_COMPAT *//* * proc fs support */static inline int line_info(char *buf, struct slgt_info *info){	char stat_buf[30];	int ret;	unsigned long flags;	ret = sprintf(buf, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n",		      info->device_name, info->phys_reg_addr,		      info->irq_level, info->max_frame_size);	/* output current serial signal states */	spin_lock_irqsave(&info->lock,flags);	get_signals(info);	spin_unlock_irqrestore(&info->lock,flags);	stat_buf[0] = 0;	stat_buf[1] = 0;	if (info->signals & SerialSignal_RTS)		strcat(stat_buf, "|RTS");	if (info->signals & SerialSignal_CTS)		strcat(stat_buf, "|CTS");	if (info->signals & SerialSignal_DTR)		strcat(stat_buf, "|DTR");	if (info->signals & SerialSignal_DSR)		strcat(stat_buf, "|DSR");	if (info->signals & SerialSignal_DCD)		strcat(stat_buf, "|CD");	if (info->signals & SerialSignal_RI)		strcat(stat_buf, "|RI");	if (info->params.mode != MGSL_MODE_ASYNC) {		ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d",			       info->icount.txok, info->icount.rxok);		if (info->icount.txunder)			ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder);		if (info->icount.txabort)			ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort);		if (info->icount.rxshort)			ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort);		if (info->icount.rxlong)			ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong);		if (info->icount.rxover)			ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover);		if (info->icount.rxcrc)			ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc);	} else {		ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d",			       info->icount.tx, info->icount.rx);		if (info->icount.frame)			ret += sprintf(buf+ret, " fe:%d", info->icount.frame);		if (info->icount.parity)			ret += sprintf(buf+ret, " pe:%d", info->icount.parity);		if (info->icount.brk)			ret += sprintf(buf+ret, " brk:%d", info->icount.brk);		if (info->icount.overrun)			ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);	}	/* Append serial signal status to end */	ret += sprintf(buf+ret, " %s\n", stat_buf+1);	ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",		       info->tx_active,info->bh_requested,info->bh_running,		       info->pending_bh);	return ret;}/* Called to print information about devices */static int read_proc(char *page, char **start, off_t off, int count,		     int *eof, void *data){	int len = 0, l;	off_t	begin = 0;	struct slgt_info *info;	len += sprintf(page, "synclink_gt driver:%s\n", driver_version);	info = slgt_device_list;	while( info ) {		l = line_info(page + len, info);		len += l;		if (len+begin > off+count)			goto done;		if (len+begin < off) {			begin += len;			len = 0;		}		info = info->next_device;	}	*eof = 1;done:	if (off >= len+begin)		return 0;	*start = page + (off-begin);	return ((count < begin+len-off) ? count : begin+len-off);}/* * return count of bytes in transmit buffer */static int chars_in_buffer(struct tty_struct *tty){	struct slgt_info *info = tty->driver_data;	if (sanity_check(info, tty->name, "chars_in_buffer"))		return 0;	DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count));	return info->tx_count;}/* * signal remote device to throttle send data (our receive data) */static void throttle(struct tty_struct * tty){	struct slgt_info *info = tty->driver_data;	unsigned long flags;	if (sanity_check(info, tty->name, "throttle"))		return;	DBGINFO(("%s throttle\n", info->device_name));	if (I_IXOFF(tty))		send_xchar(tty, STOP_CHAR(tty)); 	if (tty->termios->c_cflag & CRTSCTS) {		spin_lock_irqsave(&info->lock,flags);		info->signals &= ~SerialSignal_RTS;	 	set_signals(info);		spin_unlock_irqrestore(&info->lock,flags);	}}/* * signal remote device to stop throttling send data (our receive data) */static void unthrottle(struct tty_struct * tty){	struct slgt_info *info = tty->driver_data;	unsigned long flags;	if (sanity_check(info, tty->name, "unthrottle"))		return;	DBGINFO(("%s unthrottle\n", info->device_name));	if (I_IXOFF(tty)) {		if (info->x_char)			info->x_char = 0;		else			send_xchar(tty, START_CHAR(tty));	} 	if (tty->termios->c_cflag & CRTSCTS) {		spin_lock_irqsave(&info->lock,flags);		info->signals |= SerialSignal_RTS;	 	set_signals(info);		spin_unlock_irqrestore(&info->lock,flags);	}}/* * set or clear transmit break condition * break_state	-1=set break condition, 0=clear */static void set_break(struct tty_struct *tty, int break_state){	struct slgt_info *info = tty->driver_data;	unsigned short value;	unsigned long flags;	if (sanity_check(info, tty->name, "set_break"))		return;	DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));	spin_lock_irqsave(&info->lock,flags);	value = rd_reg16(info, TCR); 	if (break_state == -1)		value |= BIT6;

⌨️ 快捷键说明

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