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

📄 moxa.c

📁 moxa多串口卡linux下的驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return (0);	port = ch->port;	save_flags(flags);	cli();	if (from_user) {	    copy_from_user(moxaXmitBuff, buf, count);	    temp = moxaXmitBuff;	} else		temp = (unsigned char *) buf;	len = MoxaPortWriteData(port, temp, count);	restore_flags(flags);	/*********************************************	if ( !(ch->statusflags & LOWWAIT) &&	     ((len != count) || (MoxaPortTxFree(port) <= 100)) )	************************************************/	    ch->statusflags |= LOWWAIT;	return (len);}static int moxa_write_room(struct tty_struct *tty){	struct moxa_str *ch;	if (tty->stopped)		return (0);	ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return (0);	return (MoxaPortTxFree(ch->port));}static void moxa_flush_buffer(struct tty_struct *tty){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return;	MoxaPortFlushData2(ch->port, 1);	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	    tty->ldisc.write_wakeup)		(tty->ldisc.write_wakeup) (tty);	wake_up_interruptible(&tty->write_wait);}static int moxa_chars_in_buffer(struct tty_struct *tty){	int chars;	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	/*	 * Sigh...I have to check if driver_data is NULL here, because	 * if an open() fails, the TTY subsystem eventually calls	 * tty_wait_until_sent(), which calls the driver's chars_in_buffer()	 * routine.  And since the open() failed, we return 0 here.  TDJ	 */	if (ch == NULL)		return (0);	chars = MoxaPortTxQueue(ch->port);	if (chars) {	    /*	     * Make it possible to wakeup anything waiting for output	     * in tty_ioctl.c, etc.	     */		if (!(ch->statusflags & EMPTYWAIT))			setup_empty_event(tty);	}	return (chars);}static void moxa_flush_chars(struct tty_struct *tty){	/*	 * Don't think I need this, because this is called to empty the TX	 * buffer for the 16450, 16550, etc.	 */}static void moxa_put_char(struct tty_struct *tty, unsigned char c){	struct moxa_str *ch;	int port;	unsigned long flags;	ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)	    return;	port = ch->port;	save_flags(flags);	cli();	moxaXmitBuff[0] = c;	MoxaPortWriteData(port, moxaXmitBuff, 1);	restore_flags(flags);	/************************************************	if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )	*************************************************/	    ch->statusflags |= LOWWAIT;}static int moxa_ioctl(struct tty_struct *tty, struct file * file,		      unsigned int cmd, unsigned long arg){	struct moxa_str *ch = (struct moxa_str *)tty->driver_data;	register int	port;	int		retval, dtr, rts;	unsigned long		flag;	port = PORTNO(tty);	if ( (port != MAX_PORTS) && (!ch) )	    return(-EINVAL);	switch ( cmd ) {	case TCSBRK:	/* SVID version: non-zero arg --> no break */	    retval = tty_check_change(tty);	    if ( retval )		return(retval);	    setup_empty_event(tty);	    tty_wait_until_sent(tty, 0);	    if ( !arg )		MoxaPortSendBreak(ch->port, 0);	    return(0);	case TCSBRKP:	/* support for POSIX tcsendbreak() */	    retval = tty_check_change(tty);	    if ( retval )		return(retval);	    setup_empty_event(tty);	    tty_wait_until_sent(tty, 0);	    MoxaPortSendBreak(ch->port, arg);	    return(0);	case TIOCGSOFTCAR:	    retval = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long));	    if ( retval )		return(retval);	    put_to_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);	    return(0);	case TIOCSSOFTCAR:	    retval = verify_area(VERIFY_READ, (void *)arg, sizeof(long));	    if ( retval )		return(retval);	    get_from_user(retval,(unsigned long *)arg);	    arg = retval;	    tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |				    (arg ? CLOCAL : 0));		if (C_CLOCAL(tty))		ch->asyncflags &= ~ASYNC_CHECK_CD;	    else		ch->asyncflags |= ASYNC_CHECK_CD;	    return(0);	case TIOCMGET:	    retval = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long));	    if ( retval )		return(retval);	    flag = 0;	    MoxaPortGetLineOut(ch->port, &dtr, &rts);	    if ( dtr )		flag |= TIOCM_DTR;	    if ( rts )		flag |= TIOCM_RTS;	    dtr = MoxaPortLineStatus(ch->port);	    if ( dtr & 1 )		flag |= TIOCM_CTS;	    if ( dtr & 2 )		flag |= TIOCM_DSR;	    if ( dtr & 4 )		flag |= TIOCM_CD;	    put_to_user(flag, (unsigned long *)arg);	    return(0);	case TIOCMBIS:	    retval = verify_area(VERIFY_READ, (void *)arg, sizeof(long));	    if ( retval )		return(retval);	    get_from_user(retval,(unsigned long *)arg);	    MoxaPortGetLineOut(ch->port, &dtr, &rts);	    if ( retval & TIOCM_RTS )		rts = 1;	    if ( retval & TIOCM_DTR )		dtr = 1;	    MoxaPortLineCtrl(ch->port, dtr, rts);	    return(0);	case TIOCMBIC:	    retval = verify_area(VERIFY_READ, (void *)arg, sizeof(long));	    if ( retval )		return(retval);	    get_from_user(retval,(unsigned long *)arg);	    MoxaPortGetLineOut(ch->port, &dtr, &rts);	    if ( retval & TIOCM_RTS )		rts = 0;	    if ( retval & TIOCM_DTR )		dtr = 0;	    MoxaPortLineCtrl(ch->port, dtr, rts);	    return(0);	case TIOCMSET:	    retval = verify_area(VERIFY_READ, (void *)arg, sizeof(long));	    if ( retval )		return(retval);	    get_from_user(retval,(unsigned long *)arg);	    dtr = rts = 0;	    if ( retval & TIOCM_RTS )		rts = 1;	    if ( retval & TIOCM_DTR )		dtr = 1;	    MoxaPortLineCtrl(ch->port, dtr, rts);	    return(0);	case TIOCGSERIAL:	    retval = verify_area(VERIFY_WRITE, (void *)arg,				sizeof(struct serial_struct));	    if ( retval )		return(retval);	    return(moxa_get_serial_info(ch, (struct serial_struct *)arg));	case TIOCSSERIAL:	    retval = verify_area(VERIFY_READ, (void *)arg,				sizeof(struct serial_struct));	    if ( retval )		return(retval);	    return(moxa_set_serial_info(ch, (struct serial_struct *)arg));	default:	    retval = MoxaDriverIoctl(cmd, arg, port);	}	return(retval);}static void moxa_throttle(struct tty_struct * tty){	struct moxa_str *ch = (struct moxa_str *)tty->driver_data;	ch->statusflags |= THROTTLE;}static void moxa_unthrottle(struct tty_struct * tty){	struct moxa_str *ch = (struct moxa_str *)tty->driver_data;	ch->statusflags &= ~THROTTLE;}static void moxa_set_termios(struct tty_struct *tty,			     struct termios *old_termios){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return;	set_tty_param(tty);	if (!(old_termios->c_cflag & CLOCAL) &&	    (tty->termios->c_cflag & CLOCAL))		wake_up_interruptible(&ch->open_wait);}static void moxa_stop(struct tty_struct *tty){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return;	MoxaPortTxDisable(ch->port);	ch->statusflags |= TXSTOPPED;}static void moxa_start(struct tty_struct *tty){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return;	if (!(ch->statusflags & TXSTOPPED))		return;	MoxaPortTxEnable(ch->port);	ch->statusflags &= ~TXSTOPPED;}static void moxa_hangup(struct tty_struct *tty){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	moxa_flush_buffer(tty);	shut_down(ch);	ch->event = 0;	ch->count = 0;	ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);	ch->tty = 0;	wake_up_interruptible(&ch->open_wait);}static void moxa_poll(unsigned long ignored){	register int card;	struct moxa_str *ch;	struct tty_struct *tp;	int i, ports;	moxaTimer_on = 0;	del_timer(&moxaTimer);	if (MoxaDriverPoll() < 0) {		moxaTimer.function = moxa_poll;		moxaTimer.expires = jiffies + (HZ / 50);	    moxaTimer_on = 1;	    add_timer(&moxaTimer);	    return;	}	for ( card=0; card<MAX_BOARDS; card++ ) {	    if ( (ports = MoxaPortsOfCard(card)) <= 0 )		continue;	    ch = &moxaChannels[card * MAX_PORTS_PER_BOARD];	    for ( i=0; i<ports; i++, ch++ ) {		if ( (ch->asyncflags & ASYNC_INITIALIZED) == 0 )		    continue;		if ( !(ch->statusflags & THROTTLE) &&		     (MoxaPortRxQueue(ch->port) > 0) )		    receive_data(ch);		if ( (tp = ch->tty) == 0 )		    continue;		if ( ch->statusflags & LOWWAIT ) {		    if ( MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS ) {			if ( !tp->stopped ) {			    ch->statusflags &= ~LOWWAIT;			    if ( (tp->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&				 tp->ldisc.write_wakeup )				(tp->ldisc.write_wakeup)(tp);			    wake_up_interruptible(&tp->write_wait);			}		    }		}		if ( !I_IGNBRK(tp)&&(MoxaPortResetBrkCnt(ch->port) > 0) ) {		    tty_insert_flip_char(tp, 0, TTY_BREAK);		    tty_schedule_flip(tp);		}		if ( MoxaPortDCDChange(ch->port) ) {		    if ( ch->asyncflags & ASYNC_CHECK_CD ) {			if ( MoxaPortDCDON(ch->port) )			    wake_up_interruptible(&ch->open_wait);			else {	       			set_bit(MOXA_EVENT_HANGUP,&ch->event);				MOD_DEC_USE_COUNT;#if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0))				if (schedule_task(&ch->tqueue) == 0)					MOD_INC_USE_COUNT;#else# if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))				queue_task(&ch->tqueue, &tq_scheduler);# else				queue_task_irq_off(&ch->tqueue,&tq_scheduler);# endif#endif			}		    }		}	    }	}	moxaTimer.function = moxa_poll;	moxaTimer.expires  = jiffies + (HZ/50);	moxaTimer_on = 1;	add_timer(&moxaTimer);}/******************************************************************************/static void set_tty_param(struct tty_struct *tty){	register struct termios *ts;	struct moxa_str *ch;	int rts, cts, txflow, rxflow, xany;	ch = (struct moxa_str *) tty->driver_data;	ts = tty->termios;	if (ts->c_cflag & CLOCAL)	    ch->asyncflags &= ~ASYNC_CHECK_CD;	else	    ch->asyncflags |= ASYNC_CHECK_CD;	rts = cts = txflow = rxflow = xany = 0;	if (ts->c_cflag & CRTSCTS)		rts = cts = 1;	if (ts->c_iflag & IXON)		txflow = 1;	if (ts->c_iflag & IXOFF)		rxflow = 1;	if (ts->c_iflag & IXANY)		xany = 1;	MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany);	MoxaPortSetTermio(ch->port, ts);}static int block_till_ready(struct tty_struct *tty, struct file *filp,			    struct moxa_str *ch){#if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0))	DECLARE_WAITQUEUE(wait,current);  #else	struct wait_queue	wait = {current, NULL};#endif	unsigned long		flags;	int			retval;	int			do_clocal = C_CLOCAL(tty);	/*	 * If the device is in the middle of being closed, then block	 * until it's done, and then try again.	 */	if (tty_hung_up_p(filp) || (ch->asyncflags & ASYNC_CLOSING)) {		if (ch->asyncflags & ASYNC_CLOSING)			interruptible_sleep_on(&ch->close_wait);#ifdef SERIAL_DO_RESTART		if (ch->asyncflags & ASYNC_HUP_NOTIFY)			return (-EAGAIN);		else			return (-ERESTARTSYS);#else		return (-EAGAIN);#endif	}	/*	 * If this is a callout device, then just make sure the normal	 * device isn't being used.	 */	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {		if (ch->asyncflags & ASYNC_NORMAL_ACTIVE)			return (-EBUSY);		if ((ch->asyncflags & ASYNC_CALLOUT_ACTIVE) &&		    (ch->asyncflags & ASYNC_SESSION_LOCKOUT) &&		    (ch->session != current->session))			return (-EBUSY);		if ((ch->asyncflags & ASYNC_CALLOUT_ACTIVE) &&		    (ch->asyncflags & ASYNC_PGRP_LOCKOUT) &&		    (ch->pgrp != current->pgrp))			return (-EBUSY);		ch->asyncflags |= ASYNC_CALLOUT_ACTIVE;		return (0);	}	/*	 * If non-blocking mode is set, then make the check up front	 * and then exit.	 */	if (filp->f_flags & O_NONBLOCK) {		if (ch->asyncflags & ASYNC_CALLOUT_ACTIVE)			return (-EBUSY);		ch->asyncflags |= ASYNC_NORMAL_ACTIVE;		return (0);	}	/*	 * Block waiting for the carrier detect and the line to become free	 */	retval = 0;	add_wait_queue(&ch->open_wait, &wait);#ifdef SERIAL_DEBUG_OPEN	printk("block_til_ready before block: ttys%d, count = %d\n",	       ch->line, ch->count);#endif	save_flags(flags);	cli();	if (!tty_hung_up_p(filp))	    ch->count--;	restore_flags(flags);	ch->blocked_open++;	while (1) {		current->state = TASK_INTERRUPTIBLE;		if (tty_hung_up_p(filp) ||		    !(ch->asyncflags & ASYNC_INITIALIZED)) {#ifdef SERIAL_DO_RESTART			if (ch->asyncflags & ASYNC_HUP_NOTIFY)		    retval = -EAGAIN;		else		    retval = -ERESTARTSYS;

⌨️ 快捷键说明

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