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

📄 mxpcdrv.c

📁 isa总线设备
💻 C
📖 第 1 页 / 共 5 页
字号:
		cnow = info->icount;	/* atomic copy */        MX_UNLOCK(&info->slock);		if ( cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&		     cnow.dcd == cprev.dcd && cnow.cts == cprev.cts )		    return(-EIO);	/* no change => error */		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)) ) {		    return(0);		}		cprev = cnow;	    }	    /* NOTREACHED */	/*	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)	 * Return: write counters to the user passed counter struct	 * NB: both 1->0 and 0->1 transitions are counted except for	 *     RI where only 0->1 is counted.	 */	case TIOCGICOUNT:	    error = MX_ACCESS_CHK(VERIFY_WRITE, (void *)arg,				sizeof(struct serial_icounter_struct));	    if ( MX_ERR(error) )		return(error);	    MX_LOCK(&info->slock);	    cnow = info->icount;	    MX_UNLOCK(&info->slock);	    p_cuser = (struct serial_icounter_struct *)arg;/* modified by casper 1/11/2000 */ #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))	        if (put_user(cnow.frame, &p_cuser->frame))			return -EFAULT;	        if (put_user(cnow.brk, &p_cuser->brk))			return -EFAULT;	        if (put_user(cnow.overrun, &p_cuser->overrun))			return -EFAULT;	        if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun))			return -EFAULT;	        if (put_user(cnow.parity, &p_cuser->parity))			return -EFAULT;	        if (put_user(cnow.rx, &p_cuser->rx))			return -EFAULT;	        if (put_user(cnow.tx, &p_cuser->tx))			return -EFAULT;#endif	    put_to_user(cnow.cts, &p_cuser->cts);	    put_to_user(cnow.dsr, &p_cuser->dsr);	    put_to_user(cnow.rng, &p_cuser->rng);	    put_to_user(cnow.dcd, &p_cuser->dcd);/* */	    return(0);	case MOXA_HighSpeedOn:	    error = MX_ACCESS_CHK(VERIFY_WRITE, (void *)arg, sizeof(int));	    if ( MX_ERR(error) )		return(error);	    put_to_user(info->baud_base != 115200 ? 1 : 0, (int *)arg);	    return(0);	    	case MOXA_SET_SPECIAL_BAUD_RATE:		error = MX_ACCESS_CHK(VERIFY_READ, (void *)arg, sizeof(int));	    	if ( MX_ERR(error) )			return(error);					MX_LOCK(&info->slock);		mxpcdrv_set_special_baudrate(info, (int)arg);		MX_UNLOCK(&info->slock);		return(0);				case MOXA_GET_SPECIAL_BAUD_RATE:		error = MX_ACCESS_CHK(VERIFY_WRITE, (void *)arg, sizeof(int));	    	if ( MX_ERR(error) )			return(error);						put_to_user(info->cur_baud, (int *)arg);							return(0);	    	default:	    return(-ENOIOCTLCMD);	}	return(0);}static int mxpcdrv_ioctl_special(unsigned int cmd, unsigned long arg){	int		error, i, result, status;	switch ( cmd ) {	case MOXA_GET_CONF:	    error = MX_ACCESS_CHK(VERIFY_WRITE, (void *)arg, 			    sizeof(struct mxpcdrv_hwconf)*4);	    if ( MX_ERR(error) )		return(error);	    if (copy_to_user((struct mxpcdrv_hwconf *)arg, mxpcdrvcfg, 			    sizeof(struct mxpcdrv_hwconf)*4))		return -EFAULT;	    return 0;        case MOXA_GET_MAJOR:	    error = MX_ACCESS_CHK(VERIFY_WRITE, (void *)arg, sizeof(int));	    if ( MX_ERR(error) )                return(error);	    if (copy_to_user((int*)arg, &ttymajor, sizeof(int)))		return -EFAULT;            return 0;        case MOXA_GET_CUMAJOR:	    error = MX_ACCESS_CHK(VERIFY_WRITE, (void *)arg, sizeof(int));	    if ( MX_ERR(error) )                return(error);	    if (copy_to_user((int*)arg, &calloutmajor, sizeof(int)))		return -EFAULT;            return 0;	case MOXA_CHKPORTENABLE:	    error = MX_ACCESS_CHK(VERIFY_WRITE, (void *)arg, sizeof(long));	    if ( MX_ERR(error) )		return(error);	    result = 0;	    for ( i=0; i<MXPCDRV_PORTS; i++ ) {		if ( mxvar_table[i].base )		    result |= (1 << i);	    }	    put_to_user(result, (unsigned long *)arg);	    return(0);	case MOXA_GETDATACOUNT:	    error = MX_ACCESS_CHK(VERIFY_WRITE, (void *)arg,				sizeof(struct mxpcdrv_log));	    if ( MX_ERR(error) )		return(error);	    if (copy_to_user((struct mxpcdrv_log *)arg, &mxvar_log, sizeof(mxvar_log)))		return -EFAULT;	    return(0);        case MOXA_GETMSTATUS:	    error = MX_ACCESS_CHK(VERIFY_WRITE, (void *)arg,				sizeof(struct mxpcdrv_mstatus) * MXPCDRV_PORTS);	    if ( MX_ERR(error) )		return(error);            for(i=0; i<MXPCDRV_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 mxpcdrv_mstatus *)arg, GMStatus,                                    sizeof(struct mxpcdrv_mstatus) * MXPCDRV_PORTS))		return -EFAULT;            return 0;	default:	    return(-ENOIOCTLCMD);	}	return(0);}static void mxpcdrv_stoprx(struct tty_struct * tty){	struct mxpcdrv_struct *info = (struct mxpcdrv_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	      if(!(info->flags & ASYNC_CLOSING)){	        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 mxpcdrv_startrx(struct tty_struct * tty){	struct mxpcdrv_struct *info = (struct mxpcdrv_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			if(!(info->flags & ASYNC_CLOSING)){		    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 mxpcdrv_throttle(struct tty_struct * tty){	mxpcdrv_stoprx(tty);}static void mxpcdrv_unthrottle(struct tty_struct * tty){	mxpcdrv_startrx(tty);}#if (LINUX_VERSION_CODE > VERSION_CODE(2,6,19))static void mxpcdrv_set_termios(struct tty_struct * tty,			      struct ktermios * old_termios)#elsestatic void mxpcdrv_set_termios(struct tty_struct * tty,			      struct termios * old_termios)#endif{	struct mxpcdrv_struct *info = (struct mxpcdrv_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)) ) {		mxpcdrv_change_speed(info, old_termios);		if ( (old_termios->c_cflag & CRTSCTS) &&	     	     !(tty->termios->c_cflag & CRTSCTS) ) {	    		tty->hw_stopped = 0;	    		mxpcdrv_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    		mxpcdrv_start(tty);	}}/* * mxpcdrv_stop() and mxpcdrv_start() * * This routines are called before setting or resetting tty->stopped. * They enable or disable transmitter interrupts, as necessary. */static void mxpcdrv_stop(struct tty_struct * tty){	struct mxpcdrv_struct *info = (struct mxpcdrv_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 mxpcdrv_start(struct tty_struct * tty){	struct mxpcdrv_struct *info = (struct mxpcdrv_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);	    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))/* * mxpcdrv_wait_until_sent() --- wait until the transmitter is empty */static void mxpcdrv_wait_until_sent(struct tty_struct *tty, int timeout){	struct mxpcdrv_struct * info = (struct mxpcdrv_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 character, and make it at least 1.  The check	 * interval should also be less than the timeout.	 * 	 * Note: we have to use pretty tight timings here to satisfy	 * the NIST-PCTS.	 */	char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;	char_time = char_time / 5;	if (char_time == 0)		char_time = 1;	if (timeout && timeout < char_time)		char_time = timeout;	/*	 * If the transmitter hasn't cleared in twice the approximate	 * amount of time to send the entire FIFO, it probably won't	 * ever clear.  This assumes the UART isn't doing flow	 * control, which is currently the case.  Hence, if it ever	 * takes longer than info->timeout, this is probably due to a	 * UART bug of some kind.  So, we clamp the timeout parameter at	 * 2*info->timeout.	 */	if (!timeout || timeout > 2*info->timeout)		timeout = 2*info->timeout;#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT	printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);	printk("jiff=%lu...", jiffies);#endif	while (!((lsr = inb(info->base+ UART_LSR)) & UART_LSR_TEMT)) {#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);#endif#if (LINUX_VERSION_CODE >= VERSION_CODE(2,3,0))		set_current_state(TASK_INTERRUPTIBLE);#else		current->state = TASK_INTERRUPTIBLE;#endif		schedule_timeout(char_time);		if (signal_pending(current))			break;		if (timeout && time_after(jiffies, orig_jiffies + timeout))			break;	}#if (LINUX_VERSION_CODE >= VERSION_CODE(2,3,0))		set_current_state(TASK_RUNNING);#else		current->state = TASK_RUNNING;#endif#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);#endif}#endif/* * This routine is called by tty_hangup() when a hangup is signaled. */void mxpcdrv_hangup(struct tty_struct * tty){	struct mxpcdrv_struct * info = (struct mxpcdrv_struct *)tty->driver_data;	mxpcdrv_flush_buffer(tty);	mxpcdrv_shutdown(info);	info->event = 0;	info->count = 0;	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);	info->tty = 0;	wake_up_interruptible(&info->open_wait);}/* * This is the serial driver's generic interrupt routine */#if (LINUX_VERSION_CODE > VERSION_CODE(2,6,19))static irqreturn_t mxpcdrv_interrupt(int irq, void *dev_id)#elsestatic IRQ_RET mxpcdrv_interrupt(int irq, void *dev_id, struct pt_regs * regs)#endif{	int			status, iir, i;	struct mxpcdrv_struct *	info;	struct mxpcdrv_struct *	port;	int			max, irqbits, bits, msr;	int			pass_counter = 0;	int			handled = 0;        port = 0;        for(i=0; i<MXPCDRV_BOARDS; i++){            if(dev_id == &(mxvar_table[i*MXPCDRV_PORTS_PER_BOARD])){                port = dev_id;                break;            }        }        if(i==MXPCDRV_BOARDS)            goto irq_stop;        if(port==0)            goto irq_stop;        max = mxpcdrv_numports[mxpcdrvcfg[i].board_type-1];        

⌨️ 快捷键说明

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