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

📄 mxpcdrv.c

📁 isa总线设备
💻 C
📖 第 1 页 / 共 5 页
字号:
#define READ_MOXA_MUST_GDL(baseio)	inb((baseio)+MOXA_MUST_GDL_REGISTER)#if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,0))static struct tty_operations mxpcdrv_ops = {	.open = mxpcdrv_open,	.close = mxpcdrv_close,	.write = mxpcdrv_write,	.put_char = mxpcdrv_put_char,	.flush_chars = mxpcdrv_flush_chars,	.write_room = mxpcdrv_write_room,	.chars_in_buffer = mxpcdrv_chars_in_buffer,	.flush_buffer = mxpcdrv_flush_buffer,	.ioctl = mxpcdrv_ioctl,	.throttle = mxpcdrv_throttle,	.unthrottle = mxpcdrv_unthrottle,	.set_termios = mxpcdrv_set_termios,	.stop = mxpcdrv_stop,	.start = mxpcdrv_start,	.hangup = mxpcdrv_hangup,	.tiocmget = mxpcdrv_tiocmget,	.tiocmset = mxpcdrv_tiocmset,};#endifstatic int CheckIsMoxaMust(int io){	UCHAR	oldmcr, hwid;	outb(0, io+UART_LCR);	DISABLE_MOXA_MUST_ENCHANCE_MODE(io);	oldmcr = inb(io+UART_MCR);	outb(0, io+UART_MCR);	SET_MOXA_MUST_XON1_VALUE(io, 0x11);	if ( (hwid=inb(io+UART_MCR)) != 0 ) {		outb(oldmcr, io+UART_MCR);		return(0);	}	GET_MOXA_MUST_HARDWARE_ID(io, &hwid);	if ( hwid != MOXA_MUST_HARDWARE_ID )		return(0);	return(1);}// above is modified by Victor Yu. 08-15-2002/* * The MOXA PC104 Communication Module serial driver boot-time initialization code! */INIT_FUNC_RET	INIT_FUNC(void){	int	ret;	if (verbose)		printk("Loading module mxpcdrv ...\n");	ret = mxpcdrv_init();	if (verbose)		printk("Done.\n");	return (ret);}CLEAR_FUNC_RET	CLEAR_FUNC(void){	int i,err = 0;	if (verbose)		printk("Unloading module mxpcdrv ...\n");#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))	if ((err |= tty_unregister_driver(&mxvar_cdriver)))		printk("Couldn't unregister MOXA PC104 Communication Module callout driver\n");#endif			if ((err |= tty_unregister_driver(DRV_VAR)))		printk("Couldn't unregister MOXA PC104 Communication Module serial driver\n");        for(i=0; i<MXPCDRV_BOARDS; i++){	    if(mxpcdrvcfg[i].board_type == -1)	        continue;            else{	        free_irq(mxpcdrvcfg[i].irq, &mxvar_table[i*MXPCDRV_PORTS_PER_BOARD]);		release_region(mxpcdrvcfg[i].ioaddr[0],8*mxpcdrvcfg[i].ports);		if ((mxpcdrvcfg[i].pciInfo.busNum == 0)&&(mxpcdrvcfg[i].pciInfo.devNum == 0))			release_region(mxpcdrvcfg[i].vector,1);		else			release_region(mxpcdrvcfg[i].vector,16);            }        }        	if (verbose)		printk("Done.\n");}int mxpcdrv_initbrd(int board,struct mxpcdrv_hwconf *hwconf){	struct mxpcdrv_struct *	info;    int     retval;	int	i,n;#if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0))	init_MUTEX(&mxvar_tmp_buf_sem); #endif	n = board*MXPCDRV_PORTS_PER_BOARD;	info = &mxvar_table[n];	#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))		printk("        ttyN%d/cum%d - ttyN%d/cum%d  ", 			n, n, n+hwconf->ports-1, n+hwconf->ports-1);#else		printk("        ttyN%d - ttyN%d ", 			n, n+hwconf->ports-1);#endif					printk(" max. baud rate = %d bps.\n", hwconf->MaxCanSetBaudRate[0]);			for ( i=0; i<hwconf->ports; i++, n++, info++ ) {		info->port = n;		info->base = hwconf->ioaddr[i];		info->irq = hwconf->irq;		info->vector = hwconf->vector;		info->vectormask = hwconf->vector_mask;        info->ldisc_stop_rx = 0;        		// following add by Victor Yu. 08-30-2002		// Moxa Must UART support FIFO is 64bytes for Tx/Rx		// but receive FIFO just can set up to 62 will be OK.		info->IsMoxaMustChipFlag = hwconf->IsMoxaMustChipFlag;		if ( hwconf->IsMoxaMustChipFlag )			info->rx_trigger = 56;		else		// above add by Victor Yu. 08-30-2002			info->rx_trigger = 14;		info->baud_base = hwconf->baud_base[i];		info->flags = ASYNC_SHARE_IRQ;		info->type = hwconf->uart_type;		if ( (info->type == PORT_16450) || (info->type == PORT_8250) )		    info->xmit_fifo_size = 1;		else		    info->xmit_fifo_size = 16;		// following add by Victor Yu. 08-30-2002		if ( info->IsMoxaMustChipFlag ) {		    info->xmit_fifo_size = 64;		    ENABLE_MOXA_MUST_ENHANCE_MODE(info->base);		}		info->MaxCanSetBaudRate = hwconf->MaxCanSetBaudRate[i];		// above add by Victor Yu. 08-30-2002		info->custom_divisor = hwconf->baud_base[i] * 16;		info->close_delay = 5*HZ/10;		info->closing_wait = 30*HZ;#if (LINUX_VERSION_CODE > VERSION_CODE(2,6,19))		INIT_WORK(&info->tqueue, mxpcdrv_do_softint);#else		INIT_WORK(&info->tqueue, mxpcdrv_do_softint, info);#endif#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))		info->callout_termios = mxvar_cdriver.init_termios;#endif		info->normal_termios = DRV_VAR_P(init_termios);#if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0))		init_waitqueue_head(&info->open_wait);		init_waitqueue_head(&info->close_wait);		init_waitqueue_head(&info->delta_msr_wait);#endif/* added by casper 1/11/2000 */#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))		info->icount.rx = info->icount.tx = 0;#endif		info->icount.cts = info->icount.dsr = 		    info->icount.dsr = info->icount.dcd = 0;#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))		info->icount.frame = info->icount.overrun = 		    info->icount.brk = info->icount.parity = 0;#endif/* */		spin_lock_init(&info->slock);	}	request_region(hwconf->ioaddr[0],8*hwconf->ports,"mxpcdrv(io)");	if ((hwconf->pciInfo.busNum == 0)&&(hwconf->pciInfo.devNum == 0))		request_region(hwconf->vector,1,"mxpcdrv(vector)");	else		request_region(hwconf->vector,16,"mxpcdrv(vector)");	/*	 * Allocate the IRQ if necessary	 */		/* before set INT ISR, disable all int */	for(i=0; i<hwconf->ports; i++){		outb(inb(hwconf->ioaddr[i] + UART_IER) & 0xf0, hwconf->ioaddr[i]+UART_IER);	}		n = board*MXPCDRV_PORTS_PER_BOARD;	info = &mxvar_table[n];        retval = request_irq(hwconf->irq, mxpcdrv_interrupt, IRQ_T(info),				 "mxpcdrv", info);	if ( retval ) {	    printk("Board %d: %s", board, mxpcdrv_brdname[hwconf->board_type-1]);	    printk("  Request irq fail,IRQ (%d) may be conflit with another device.\n",info->irq);	    return(retval);	}        return 0;}static void mxpcdrv_getcfg(int board,struct mxpcdrv_hwconf *hwconf){	mxpcdrvcfg[board] = *hwconf;}int mxpcdrv_init(void){	int			i, m, retval, b;    int         ret1, ret2;		struct mxpcdrv_hwconf	hwconf;	#if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,0))	mxvar_sdriver = alloc_tty_driver(MXPCDRV_PORTS + 1);	if (!mxvar_sdriver)		return -ENOMEM;#endif	printk("MOXA PC104 Communication Module driver version %s\n",MXPCDRV_VERSION);	/* Initialize the tty_driver structure */	memset(DRV_VAR, 0, sizeof(struct tty_driver));	DRV_VAR_P(magic) = TTY_DRIVER_MAGIC;	DRV_VAR_P(name) = "ttyN";	DRV_VAR_P(major) = ttymajor;	DRV_VAR_P(minor_start) = 0;	DRV_VAR_P(num) = MXPCDRV_PORTS + 1;	DRV_VAR_P(type) = TTY_DRIVER_TYPE_SERIAL;	DRV_VAR_P(subtype) = SERIAL_TYPE_NORMAL;	DRV_VAR_P(init_termios) = tty_std_termios;	DRV_VAR_P(init_termios.c_cflag) = B9600|CS8|CREAD|HUPCL|CLOCAL;	DRV_VAR_P(flags) = TTY_DRIVER_REAL_RAW;#if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,0))	tty_set_operations(DRV_VAR, &mxpcdrv_ops);	DRV_VAR_P(ttys) = mxvar_tty;#else		DRV_VAR_P(refcount) = &mxvar_refcount;	DRV_VAR_P(table) = mxvar_tty;#endif		DRV_VAR_P(termios) = mxvar_termios;	DRV_VAR_P(termios_locked) = mxvar_termios_locked;	DRV_VAR_P(open) = mxpcdrv_open;	DRV_VAR_P(close) = mxpcdrv_close;	DRV_VAR_P(write) = mxpcdrv_write;	DRV_VAR_P(put_char) = mxpcdrv_put_char;	DRV_VAR_P(flush_chars) = mxpcdrv_flush_chars;	DRV_VAR_P(write_room) = mxpcdrv_write_room;	DRV_VAR_P(chars_in_buffer) = mxpcdrv_chars_in_buffer;	DRV_VAR_P(flush_buffer) = mxpcdrv_flush_buffer;	DRV_VAR_P(ioctl) = mxpcdrv_ioctl;	DRV_VAR_P(throttle) = mxpcdrv_throttle;	DRV_VAR_P(unthrottle) = mxpcdrv_unthrottle;	DRV_VAR_P(set_termios) = mxpcdrv_set_termios;	DRV_VAR_P(stop) = mxpcdrv_stop;	DRV_VAR_P(start) = mxpcdrv_start;	DRV_VAR_P(hangup) = mxpcdrv_hangup;#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))	DRV_VAR_P(wait_until_sent) = mxpcdrv_wait_until_sent;#endif#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))	/*	 * The callout device is just like normal device except for	 * major number and the subtype code.	 */	mxvar_cdriver = mxvar_sdriver;	mxvar_cdriver.name = "cun";	mxvar_cdriver.major = calloutmajor;	mxvar_cdriver.subtype = SERIAL_TYPE_CALLOUT;	printk("Tty devices major number = %d, callout devices major number = %d\n",ttymajor,calloutmajor);#endif	mxvar_diagflag = 0;	memset(mxvar_table, 0, MXPCDRV_PORTS * sizeof(struct mxpcdrv_struct));	memset(&mxvar_log, 0, sizeof(struct mxpcdrv_log));	m = 0;	/* Start finding ISA boards here */	for ( b=0; b<MXPCDRV_BOARDS && m<MXPCDRV_BOARDS; b++ ) {            int cap,vector,irq;	    	    if ( !(cap=mxpcdrvBoardIO[b]) )	        continue;	    if ( !(vector=mxpcdrvBoardVECT[b]) )	        continue;	    if ( !(irq=mxpcdrvBoardIRQ[b]) )	        continue;        	    retval = mxpcdrv_get_ISA_conf(cap, vector, &hwconf, irq);	    if ( retval != 0 ) 	    	printk("Found MOXA %s board (IO=0x%x,Vector=0x%x,IRQ=%d)\n",				mxpcdrv_brdname[hwconf.board_type-1],				mxpcdrvBoardIO[b],mxpcdrvBoardVECT[b],				mxpcdrvBoardIRQ[b]);					    if ( retval <= 0 ) {		if (retval == MXPCDRV_ERR_IRQ)			printk("Invalid interrupt number,board not configured\n");		else if (retval == MXPCDRV_ERR_IRQ_CONFLIT)			printk("Invalid interrupt number,board not configured\n");		else if (retval == MXPCDRV_ERR_VECTOR)			printk("Invalid interrupt vector,board not configured\n");		else if (retval == MXPCDRV_ERR_IOADDR)			printk("Invalid I/O address,board not configured\n");		continue;	    }	    	    hwconf.pciInfo.busNum = 0;	    hwconf.pciInfo.devNum = 0;	    mxpcdrv_getcfg(m,&hwconf);	    	    if(mxpcdrv_initbrd(m,&hwconf)<0)                continue;	    				  	    m++;	}	/* Start finding ISA boards from module arg */	for ( b=0; b<MXPCDRV_BOARDS && m<MXPCDRV_BOARDS; b++ ) {            int cap,vector;	    if ( !(cap=ioaddr[b]) )	        continue;	    if ( !(vector=iovect[b]) )		continue;	    if ( !(irq[b]) )		continue;                	    retval = mxpcdrv_get_ISA_conf(cap, vector, &hwconf, irq[b]);	    if ( retval != 0 ) 	    	printk("Found MOXA %s board (IO=0x%x,Vector=0x%x,IRQ=%d)\n",				mxpcdrv_brdname[hwconf.board_type-1],				ioaddr[b],iovect[b],irq[b]);					    if ( retval <= 0 ) {		if (retval == MXPCDRV_ERR_IRQ)			printk("Invalid interrupt number,board not configured\n");		else if (retval == MXPCDRV_ERR_IRQ_CONFLIT)			printk("Invalid interrupt number,board not configured\n");		else if (retval == MXPCDRV_ERR_VECTOR)			printk("Invalid interrupt vector,board not configured\n");		else if (retval == MXPCDRV_ERR_IOADDR)			printk("Invalid I/O address,board not configured\n");		continue;	    }	    	    hwconf.pciInfo.busNum = 0;	    hwconf.pciInfo.devNum = 0;	    	    mxpcdrv_getcfg(m,&hwconf);	    if(mxpcdrv_initbrd(m,&hwconf)<0)                continue;	    	    m++;	}	for(i=m; i<MXPCDRV_BOARDS; i++){		mxpcdrvcfg[i].board_type = -1;	}        ret1 = 0;        ret2 = 0;        if ( !(ret1=tty_register_driver(DRV_VAR)) ){#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))        	            if ( !(ret2=tty_register_driver(&mxvar_cdriver)) ){                return 0;            }else{                tty_unregister_driver(DRV_VAR);		printk("Couldn't install MOXA PC104 Communication Module callout driver !\n");            }#else    		return 0;	            #endif        }else	    printk("Couldn't install MOXA PC104 Communication Module driver !\n");        if(ret1 || ret2){            for(i=0; i<MXPCDRV_BOARDS; i++){	        if(mxpcdrvcfg[i].board_type == -1)	            continue;                else{		    free_irq(mxpcdrvcfg[i].irq, &mxvar_table[i*MXPCDRV_PORTS_PER_BOARD]);                }            }            return -1;        }        	return(0);}#if (LINUX_VERSION_CODE >  VERSION_CODE(2,6,19))static void mxpcdrv_do_softint(struct work_struct *work){	struct mxpcdrv_struct *	info = container_of(work,struct mxpcdrv_struct, tqueue);#elsestatic void mxpcdrv_do_softint(void *private_){	struct mxpcdrv_struct *	info = (struct mxpcdrv_struct *)private_;#endif	struct tty_struct *	tty;		tty = info->tty;#if (LINUX_VERSION_CODE <  VERSION_CODE(2,1,0))	    if ( clear_bit(MXPCDRV_EVENT_TXLOW, &info->event) ) {	        if ( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&		 tty->ldisc.write_wakeup )		(tty->ldisc.write_wakeup)(tty);	       wake_up_interruptible(&tty->write_wait);	    }	    if ( clear_bit(MXPCDRV_EVENT_HANGUP, &info->event) ) {		tty_hangup(tty);	    }#else#if (LINUX_VERSION_CODE <  VERSION_CODE(2,6,9))	    if ( test_and_clear_bit(MXPCDRV_EVENT_TXLOW, &info->event) ) {	        if ( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&		 tty->ldisc.write_wakeup )		(tty->ldisc.write_wakeup)(tty);	        wake_up_interruptible(&tty->write_wait);	    }#else	    if ( test_and_clear_bit(MXPCDRV_EVENT_TXLOW, &info->event) ) 	    	tty_wakeup(tty);#endif	    	    	    if ( test_and_clear_bit(MXPCDRV_EVENT_HANGUP, &info->event) ) {		tty_hangup(tty);	    }#endif #if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))	MX_MOD_DEC;  #endif}/* * This routine is called whenever a serial port is opened.  It * enables interrupts for a serial port, linking in its async structure into * the IRQ chain.   It also performs the serial-specific * initialization for the tty structure. */static int mxpcdrv_open(struct tty_struct * tty, struct file * filp){	struct mxpcdrv_struct *	info;	int			retval, line;	unsigned long		page;	line = PORTNO(tty);	if ( line == MXPCDRV_PORTS )	    return(0);

⌨️ 快捷键说明

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