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

📄 mxser.c

📁 MOXA 串口驱动编程
💻 C
📖 第 1 页 / 共 5 页
字号:
	    info->mon_data.rxcnt = 0;	    info->mon_data.txcnt = 0;	    return(0);    }// (above) added by James.    case MOXA_ASPP_SETBAUD:{        long    baud;		error = verify_area(VERIFY_READ, (void *)arg, sizeof(long));		if ( error )    		return(error);		get_from_user(baud, (long *)arg);        mxser_set_baud(info, baud);        return (0);        }    case MOXA_ASPP_GETBAUD:		error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long));		if ( error )    		return(error);	    if (copy_to_user((long *)arg, &info->realbaud, sizeof(long)))	        return -EFAULT;        return (0);    case MOXA_ASPP_OQUEUE:{        int len, lsr;		error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));		if ( error )    		return(error);        len = mxser_chars_in_buffer(tty);        lsr = inb(info->base+ UART_LSR) & UART_LSR_TEMT;        len += (lsr ? 0: 1);		if (copy_to_user((int *)arg, &len, sizeof(int)))	        return -EFAULT;        return (0);    }    case MOXA_ASPP_MON:{        int mcr, status;		error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mxser_mon));		if ( error )    		return(error);//    	info->mon_data.ser_param = tty->termios->c_cflag;		status = mxser_get_msr(info->base, 1, info->port, info);		mxser_check_modem_status(info, status);		mcr = inb(info->base + UART_MCR);		if(mcr & MOXA_MUST_MCR_XON_FLAG)	        info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD;		else	        info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD;			if(mcr & MOXA_MUST_MCR_TX_XON)	        info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT;		else	        info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT;    	    	if(info->tty->hw_stopped)    	    info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;        else    	    info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;    	   			if (copy_to_user((struct mxser_mon *)arg, &(info->mon_data), sizeof(struct mxser_mon)))	        return -EFAULT;        return (0);                }    case MOXA_ASPP_LSTATUS:{	error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mxser_mon));	if ( error )    		return(error);    			if (copy_to_user((struct mxser_mon *)arg, &(info->err_shadow), 		sizeof(unsigned char)))	        return -EFAULT;        info->err_shadow = 0;        return (0);                }	case MOXA_SET_BAUD_METHOD:{		int method;		error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));		if ( error )    		return(error);   	    get_from_user(method,(int *)arg);		mxser_set_baud_method[info->port] = method;		if (copy_to_user((int *)arg, &method, sizeof(int)))	        return -EFAULT;        return (0);    }	default:	    return(-ENOIOCTLCMD);	}	return(0);}static int mxser_ioctl_special(unsigned int cmd, unsigned long arg){	int		error, i, result, status;	switch ( cmd ) {	case MOXA_GET_CONF:	    error = verify_area(VERIFY_WRITE, (void *)arg,			    sizeof(struct mxser_hwconf)*4);	    if ( error )		return(error);	    if(copy_to_user((struct mxser_hwconf *)arg, mxsercfg,			    sizeof(struct mxser_hwconf)*4))		return -EFAULT;	    return 0;        case MOXA_GET_MAJOR:	    error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));	    if ( error )                return(error);	    if(copy_to_user((int*)arg, &ttymajor, sizeof(int)))		return -EFAULT;            return 0;        case MOXA_GET_CUMAJOR:	    error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));	    if ( error )                return(error);	    if(copy_to_user((int*)arg, &calloutmajor, sizeof(int)))		return -EFAULT;            return 0;	case MOXA_CHKPORTENABLE:	    error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long));	    if ( error )		return(error);	    result = 0;	    for ( i=0; i<MXSER_PORTS; i++ ) {		if ( mxvar_table[i].base )		    result |= (1 << i);	    }	    put_to_user(result, (unsigned long *)arg);	    return(0);	case MOXA_GETDATACOUNT:	    error = verify_area(VERIFY_WRITE, (void *)arg,				sizeof(struct mxser_log));	    if ( error )		return(error);	    if(copy_to_user((struct mxser_log *)arg, &mxvar_log, sizeof(mxvar_log)))		return -EFAULT;	    return(0);        case MOXA_GETMSTATUS:	    error = verify_area(VERIFY_WRITE, (void *)arg,				sizeof(struct mxser_mstatus) * MXSER_PORTS);	    if ( error )		return(error);        for(i=0; i<MXSER_PORTS; i++){            GMStatus[i].ri = 0;		if ( !mxvar_table[i].base ){                    GMStatus[i].dcd = 0;                    GMStatus[i].dsr = 0;                    GMStatus[i].cts = 0;		    continue;                }	        if ( !mxvar_table[i].tty || !mxvar_table[i].tty->termios )                    GMStatus[i].cflag=mxvar_table[i].normal_termios.c_cflag;                else                    GMStatus[i].cflag = mxvar_table[i].tty->termios->c_cflag;                status = inb(mxvar_table[i].base + UART_MSR);                if(status  & 0x80/*UART_MSR_DCD*/)                    GMStatus[i].dcd = 1;                else                    GMStatus[i].dcd = 0;                if(status  & 0x20/*UART_MSR_DSR*/)                    GMStatus[i].dsr = 1;                else                    GMStatus[i].dsr = 0;                if(status  & 0x10/*UART_MSR_CTS*/)                    GMStatus[i].cts = 1;                else                    GMStatus[i].cts = 0;            }            if(copy_to_user((struct mxser_mstatus *)arg, GMStatus,                                    sizeof(struct mxser_mstatus) * MXSER_PORTS))		return -EFAULT;            return 0;    case MOXA_ASPP_MON_EXT:{        int status;		int	opmode, p;		int shiftbit;		unsigned	cflag, iflag;		error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mxser_mon_ext));		if ( error )    		return(error);		for(i=0; i<MXSER_PORTS; i++)		{			if ( !mxvar_table[i].base )				continue;			status = mxser_get_msr(mxvar_table[i].base, 0, i, &(mxvar_table[i]));//			mxser_check_modem_status(&mxvar_table[i], status);			if ( status & UART_MSR_TERI )	    mxvar_table[i].icount.rng++;			if ( status & UART_MSR_DDSR )	    mxvar_table[i].icount.dsr++;			if ( status & UART_MSR_DDCD )	    mxvar_table[i].icount.dcd++;			if ( status & UART_MSR_DCTS )	    mxvar_table[i].icount.cts++;			mxvar_table[i].mon_data.modem_status = status;			mon_data_ext.rx_cnt[i] = mxvar_table[i].mon_data.rxcnt;			mon_data_ext.tx_cnt[i] = mxvar_table[i].mon_data.txcnt;			mon_data_ext.up_rxcnt[i] = mxvar_table[i].mon_data.up_rxcnt;			mon_data_ext.up_txcnt[i] = mxvar_table[i].mon_data.up_txcnt;			mon_data_ext.modem_status[i] = mxvar_table[i].mon_data.modem_status;			mon_data_ext.baudrate[i] = mxvar_table[i].realbaud;	        if ( !mxvar_table[i].tty || !mxvar_table[i].tty->termios )	        {            	cflag = mxvar_table[i].normal_termios.c_cflag;            	iflag = mxvar_table[i].normal_termios.c_iflag;            }            else            {            	cflag = mxvar_table[i].tty->termios->c_cflag;            	iflag = mxvar_table[i].tty->termios->c_iflag;            }			mon_data_ext.databits[i] = cflag & CSIZE;			mon_data_ext.stopbits[i] = cflag & CSTOPB;			mon_data_ext.parity[i] = cflag & (PARENB | PARODD | CMSPAR);			mon_data_ext.flowctrl[i] = 0x00;			if( cflag & CRTSCTS )				mon_data_ext.flowctrl[i] |= 0x03;			if( iflag & (IXON | IXOFF) )				mon_data_ext.flowctrl[i] |= 0x0C;								if( mxvar_table[i].type == PORT_16550A)				mon_data_ext.fifo[i] = 1;			else				mon_data_ext.fifo[i] = 0;						p = i % 4;			shiftbit = p * 2;			opmode = inb(mxvar_table[i].opmode_ioaddr) >> shiftbit;			opmode &= OP_MODE_MASK;			mon_data_ext.iftype[i] = opmode;		}		if (copy_to_user((struct mxser_mon_ext *)arg, &mon_data_ext, sizeof(struct mxser_mon_ext)))	        return -EFAULT;        return (0);                }	default:	    return(-ENOIOCTLCMD);	}	return(0);}static void mxser_stoprx(struct tty_struct * tty){	struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;	//MX_LOCK_INIT();        info->ldisc_stop_rx = 1;	if ( I_IXOFF(tty) ) {	    //MX_LOCK(&info->slock);	    // following add by Victor Yu. 09-02-2002	    if ( info->IsMoxaMustChipFlag ) {		info->IER &= ~MOXA_MUST_RECV_ISR;		outb(info->IER, info->base+UART_IER);	    } else {	    // above add by Victor Yu. 09-02-2002	        info->x_char = STOP_CHAR(tty);	//      outb(info->IER, 0); // mask by Victor Yu. 09-02-2002	        outb(0, info->base+UART_IER);	        info->IER |= UART_IER_THRI;	        outb(info->IER, info->base + UART_IER);	/* force Tx interrupt */	    }	// add by Victor Yu. 09-02-2002	    //MX_UNLOCK(&info->slock);	}	if ( info->tty->termios->c_cflag & CRTSCTS ) {	    //MX_LOCK(&info->slock);	    info->MCR &= ~UART_MCR_RTS;	    outb(info->MCR, info->base + UART_MCR);	    //MX_UNLOCK(&info->slock);	}}static void mxser_startrx(struct tty_struct * tty){	struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;	//MX_LOCK_INIT();        info->ldisc_stop_rx = 0;        if ( I_IXOFF(tty) ) {	    if ( info->x_char )		info->x_char = 0;	    else {		//MX_LOCK(&info->slock);		// following add by Victor Yu. 09-02-2002		if ( info->IsMoxaMustChipFlag ) {			info->IER |= MOXA_MUST_RECV_ISR;			outb(info->IER, info->base+UART_IER);		} else {		// above add by Victor Yu. 09-02-2002		    info->x_char = START_CHAR(tty);	//	    outb(info->IER, 0);	// mask by Victor Yu. 09-02-2002		    outb(0, info->base+UART_IER);	// add by Victor Yu. 09-02-2002		    info->IER |= UART_IER_THRI;		/* force Tx interrupt */		    outb(info->IER, info->base + UART_IER);		}	// add by Victor Yu. 09-02-2002		//MX_UNLOCK(&info->slock);	    }	}	if ( info->tty->termios->c_cflag & CRTSCTS ) {	    //MX_LOCK(&info->slock);	    info->MCR |= UART_MCR_RTS;	    outb(info->MCR, info->base + UART_MCR);	    //MX_UNLOCK(&info->slock);	}}/* * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. */static void mxser_throttle(struct tty_struct * tty){	//struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;	//MX_LOCK_INIT();	//MX_LOCK(&info->slock);        mxser_stoprx(tty);	//MX_UNLOCK(&info->slock);}static void mxser_unthrottle(struct tty_struct * tty){	//struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;	//MX_LOCK_INIT();	//MX_LOCK(&info->slock);        mxser_startrx(tty);	//MX_UNLOCK(&info->slock);}static void mxser_set_termios(struct tty_struct * tty,			      struct termios * old_termios){	struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;	MX_LOCK_INIT();	if ( (tty->termios->c_cflag != old_termios->c_cflag) ||	     (RELEVANT_IFLAG(tty->termios->c_iflag) !=	      RELEVANT_IFLAG(old_termios->c_iflag)) ) {		mxser_change_speed(info, old_termios);		if ( (old_termios->c_cflag & CRTSCTS) &&	     	     !(tty->termios->c_cflag & CRTSCTS) ) {	    		tty->hw_stopped = 0;	    		mxser_start(tty);		}	}/* Handle sw stopped */	if ( (old_termios->c_iflag & IXON) &&     	     !(tty->termios->c_iflag & IXON) ) {    		tty->stopped = 0;		// following add by Victor Yu. 09-02-2002		if ( info->IsMoxaMustChipFlag ) {			MX_LOCK(&info->slock);			DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);			MX_UNLOCK(&info->slock);		}		// above add by Victor Yu. 09-02-2002    		mxser_start(tty);	}}/* * mxser_stop() and mxser_start() * * This routines are called before setting or resetting tty->stopped. * They enable or disable transmitter interrupts, as necessary. */static void mxser_stop(struct tty_struct * tty){	struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;	MX_LOCK_INIT();	MX_LOCK(&info->slock);	if ( info->IER & UART_IER_THRI ) {	    info->IER &= ~UART_IER_THRI;	    outb(info->IER, info->base + UART_IER);	}	MX_UNLOCK(&info->slock);}static void mxser_start(struct tty_struct * tty){	struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;	MX_LOCK_INIT();		MX_LOCK(&info->slock);	if ( info->xmit_cnt && info->xmit_buf &&	     !(info->IER & UART_IER_THRI) ) {	    info->IER |= UART_IER_THRI;	    outb(info->IER, info->base + UART_IER);	}	MX_UNLOCK(&info->slock);}#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))/* * mxser_wait_until_sent() --- wait until the transmitter is empty */static void mxser_wait_until_sent(struct tty_struct *tty, int timeout){	struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;	unsigned long orig_jiffies, char_time;	int lsr;	if (info->type == PORT_UNKNOWN)		return;	if (info->xmit_fifo_size == 0)		return; /* Just in case.... */	orig_jiffies = jiffies;	/*	 * Set the check interval to be 1/5 of the estimated time to	 * send a single cha

⌨️ 快捷键说明

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