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

📄 mxser.c

📁 MOXA 串口驱动编程
💻 C
📖 第 1 页 / 共 5 页
字号:
	       pci_resource_len(pdev, 2),	       "mxser(IO)");	for (i = 0; i < hwconf->ports; i++) {		hwconf->ioaddr[i] = ioaddress + 8*i;	}	//vector	ioaddress = pci_resource_start(pdev, 3);	request_region(pci_resource_start(pdev, 3),	       pci_resource_len(pdev, 3),	       "mxser(vector)");	hwconf->vector = ioaddress;		//irq	hwconf->irq = hwconf->pciInfo.pdev->irq;	hwconf->IsMoxaMustChipFlag = CheckIsMoxaMust(hwconf->ioaddr[0]);	hwconf->uart_type = PORT_16550A;	hwconf->vector_mask = 0;			for (i = 0; i < hwconf->ports; i++) {		for(j=0; j<UART_INFO_NUM ;j++){			if(Gpci_uart_info[j].type == hwconf->IsMoxaMustChipFlag) {				hwconf->MaxCanSetBaudRate[i] = Gpci_uart_info[j].max_baud;								//exception....CP-102				if(board_type == MXSER_BOARD_CP102)					hwconf->MaxCanSetBaudRate[i] = 921600;				break;			}		}	}		if(hwconf->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID){		for (i = 0; i < hwconf->ports; i++) {			if ( i < 4 )				hwconf->opmode_ioaddr[i] = ioaddress + 4;			else				hwconf->opmode_ioaddr[i] = ioaddress + 0x0c;		}		outb(0, ioaddress+4);	// default set to RS232 mode		outb(0, ioaddress+0x0c); //default set to RS232 mode	}	        for (i = 0; i < hwconf->ports; i++) {		hwconf->vector_mask |= (1<<i);		hwconf->baud_base[i] = 921600;	}	return(0);}#endifint mxser_init(void){	int			i, m, retval, b;        int                     ret1, ret2;#ifdef CONFIG_PCIstruct pci_dev	*pdev=NULL;	int			index;	unsigned char		busnum,devnum;#endif	struct mxser_hwconf	hwconf;#if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,0))	mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);	if (!mxvar_sdriver)		return -ENOMEM;#endif			spin_lock_init(&gm_lock);	for(i=0; i<MXSER_BOARDS; i++){		mxsercfg[i].board_type = -1;	}		printk("MOXA Smartio/Industio family driver version %s\n",MXSER_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) = "ttyM";	DRV_VAR_P(major) = ttymajor;	DRV_VAR_P(minor_start) = 0;	DRV_VAR_P(num) = MXSER_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, &mxser_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) = mxser_open;	DRV_VAR_P(close) = mxser_close;	DRV_VAR_P(write) = mxser_write;	DRV_VAR_P(put_char) = mxser_put_char;	DRV_VAR_P(flush_chars) = mxser_flush_chars;	DRV_VAR_P(write_room) = mxser_write_room;	DRV_VAR_P(chars_in_buffer) = mxser_chars_in_buffer;	DRV_VAR_P(flush_buffer) = mxser_flush_buffer;	DRV_VAR_P(ioctl) = mxser_ioctl;	DRV_VAR_P(throttle) = mxser_throttle;	DRV_VAR_P(unthrottle) = mxser_unthrottle;	DRV_VAR_P(set_termios) = mxser_set_termios;	DRV_VAR_P(stop) = mxser_stop;	DRV_VAR_P(start) = mxser_start;	DRV_VAR_P(hangup) = mxser_hangup;// added by James 03-12-2004.#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,66)) /* Linux 2.1.66 */    DRV_VAR_P(break_ctl) = mxser_rs_break;#endif// (above) added by James.#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))	DRV_VAR_P(wait_until_sent) = mxser_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 = "cum";	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, MXSER_PORTS * sizeof(struct mxser_struct));	memset(&mxvar_log, 0, sizeof(struct mxser_log));	memset(&mxser_msr, 0, sizeof(unsigned char) * (MXSER_PORTS+1));	memset(&mon_data_ext, 0, sizeof(struct mxser_mon_ext));	memset(&mxser_set_baud_method, 0, sizeof(int) * (MXSER_PORTS+1));	memset(&hwconf, 0, sizeof(struct mxser_hwconf));	m = 0;	/* Start finding ISA boards here */	for ( b=0; b<MXSER_BOARDS && m<MXSER_BOARDS; b++ ) {            int cap;	    if ( !(cap=mxserBoardCAP[b]) )	        continue;	    retval = mxser_get_ISA_conf(cap, &hwconf);	    if ( retval != 0 )	    	printk("Found MOXA %s board (CAP=0x%x)\n",				mxser_brdname[hwconf.board_type-1],				ioaddr[b]);	    if ( retval <= 0 ) {		if (retval == MXSER_ERR_IRQ)			printk("Invalid interrupt number,board not configured\n");		else if (retval == MXSER_ERR_IRQ_CONFLIT)			printk("Invalid interrupt number,board not configured\n");		else if (retval == MXSER_ERR_VECTOR)			printk("Invalid interrupt vector,board not configured\n");		else if (retval == MXSER_ERR_IOADDR)			printk("Invalid I/O address,board not configured\n");		continue;	    }	    hwconf.pciInfo.busNum = 0;	    hwconf.pciInfo.devNum = 0;	    hwconf.pciInfo.pdev = NULL;	    mxser_getcfg(m,&hwconf);	    //init mxsercfg first, or mxsercfg data is not correct on ISR.	    //mxser_initbrd will hook ISR.	    if(mxser_initbrd(m,&hwconf)<0)                continue;	    m++;	}	/* Start finding ISA boards from module arg */	for ( b=0; b<MXSER_BOARDS && m<MXSER_BOARDS; b++ ) {            int cap;	    if ( !(cap=ioaddr[b]) )	        continue;	    retval = mxser_get_ISA_conf(cap, &hwconf);	    if ( retval != 0 )	    	printk("Found MOXA %s board (CAP=0x%x)\n",				mxser_brdname[hwconf.board_type-1],				ioaddr[b]);	    if ( retval <= 0 ) {		if (retval == MXSER_ERR_IRQ)			printk("Invalid interrupt number,board not configured\n");		else if (retval == MXSER_ERR_IRQ_CONFLIT)			printk("Invalid interrupt number,board not configured\n");		else if (retval == MXSER_ERR_VECTOR)			printk("Invalid interrupt vector,board not configured\n");		else if (retval == MXSER_ERR_IOADDR)			printk("Invalid I/O address,board not configured\n");		continue;	    }	    hwconf.pciInfo.busNum = 0;	    hwconf.pciInfo.devNum = 0;	    hwconf.pciInfo.pdev = NULL;	    mxser_getcfg(m,&hwconf);	    //init mxsercfg first, or mxsercfg data is not correct on ISR.	    //mxser_initbrd will hook ISR.	    if(mxser_initbrd(m,&hwconf)<0)                continue;	    m++;	}	/* start finding PCI board here */#ifdef CONFIG_PCI#if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))	if (pcibios_present()) {#else#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))	if (pci_present()) {#else	{		#endif		#endif		int n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1;		index = 0;		b = 0;		while (b < n) {		       pdev = pci_find_device(mxser_pcibrds[b].vendor,		       		mxser_pcibrds[b].device, pdev);		       					if(pdev==NULL){				b++;				continue;			}			hwconf.pciInfo.busNum = busnum = pdev->bus->number;			hwconf.pciInfo.devNum = devnum = PCI_SLOT(pdev->devfn)<<3;			hwconf.pciInfo.pdev = pdev;			printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",mxser_brdname[(int)(mxser_pcibrds[b].driver_data)-1],busnum,devnum >> 3);			index++;			if ( m >= MXSER_BOARDS) {				printk("Too many Smartio/Industio family boards find (maximum %d),board not configured\n",MXSER_BOARDS);			}			else {				if ( pci_enable_device(pdev) ) {					printk("Moxa SmartI/O PCI enable fail !\n");					continue;				}				retval = mxser_get_PCI_conf(busnum,devnum,					(int)mxser_pcibrds[b].driver_data,&hwconf);				if (retval < 0) {					if (retval == MXSER_ERR_IRQ)						printk("Invalid interrupt number,board not configured\n");					else if (retval == MXSER_ERR_IRQ_CONFLIT)						printk("Invalid interrupt number,board not configured\n");					else if (retval == MXSER_ERR_VECTOR)						printk("Invalid interrupt vector,board not configured\n");					else if (retval == MXSER_ERR_IOADDR)						printk("Invalid I/O address,board not configured\n");					continue;				}	    			mxser_getcfg(m,&hwconf);	    			//init mxsercfg first, or mxsercfg data is not correct on ISR.	    			//mxser_initbrd will hook ISR.	    			if(mxser_initbrd(m,&hwconf)<0)                                    continue;				m++;			}		}	}#endif        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)) ){//                init_timer(&moxaTimer);//                moxaTimer.function = mxser_poll;//                moxaTimer.expires = jiffies + (HZ / 10);    /* 0.1 sec *///                moxaTimer_on = 1;//                add_timer(&moxaTimer);                return 0;            }else{                tty_unregister_driver(DRV_VAR);		printk("Couldn't install MOXA Smartio/Industio family callout driver !\n");            }#else	    return 0;	            #endif                    }else	    printk("Couldn't install MOXA Smartio/Industio family driver !\n");        if(ret1 || ret2){            for(i=0; i<MXSER_BOARDS; i++){	        if(mxsercfg[i].board_type == -1)	            continue;                else{		    free_irq(mxsercfg[i].irq, &mxvar_table[i*MXSER_PORTS_PER_BOARD]);		    //todo: release io, vector                }            }            return -1;        }	return(0);}static void mxser_do_softint(void *private_){	struct mxser_struct *	info = (struct mxser_struct *)private_;	struct tty_struct *	tty;	tty = info->tty;	if (tty) {#if (LINUX_VERSION_CODE <  VERSION_CODE(2,1,0))	    if ( clear_bit(MXSER_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(MXSER_EVENT_HANGUP, &info->event) ) {		tty_hangup(tty);	    }#else	    if ( test_and_clear_bit(MXSER_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 ( test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event) ) {		tty_hangup(tty);	    }#endif	}#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))	MX_MOD_DEC;#endif}static unsigned char mxser_get_msr(int baseaddr, int mode, int port, struct mxser_struct *info){	unsigned char	status=0;	status = inb(baseaddr + UART_MSR);	mxser_msr[port] &= 0x0F;	mxser_msr[port] |= status;	status = mxser_msr[port];	if( mode )		mxser_msr[port] = 0;			return status;}/* * 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 mxser_open(struct tty_struct * tty, struct file * filp){	struct mxser_struct *	info;	int			retval, line;	unsigned long		page;	//unsigned char 		status;		line = PORTNO(tty);	if ( line == MXSER_PORTS )	    return(0);	if ( (line < 0) || (line > MXSER_PORTS) )	    return(-ENODEV);	info = mxvar_table + line;	if ( !info->base )	    return(-ENODEV);	tty->driver_data = info;	info->tty = tty;	if ( !mxvar_tmp_buf ) {	    page = GET_FPAGE(GFP_KERNEL);	    if ( !page )		return(-ENOMEM);	    if ( mxvar_tmp_buf )		free_page(page);	    else		mxvar_tmp_buf = (unsigned char *)page;	}//printk("port %d, mxser_open\r\n", info->port);	/*	 * Start up serial port	 */	retval = mxser_startup(info);	if ( retval )	    return(retval);	retval = mxser_block_til_ready(tty, filp, info);	if ( retval )	    return(retval);	info->count++;	MX_MOD_INC;	if ( (info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS) ) {	    if ( MX_TTY_DRV(subtype) == SERIAL_TYPE_NORMAL )		*tty->termios = info->normal_termios;	    else		*tty->termios = info->callout_termios;	    mxser_change_speed(info, 0);	}	info->session = MX_SESSION();	info->pgrp = MX_CGRP();	clear_bit(TTY_DONT_FLIP, &tty->flags);	//status = mxser_get_msr(info->base, 0, info->port);	//mxser_check_modem_status(info, status);/* unmark here for very high baud rate (ex. 921600 bps) used*/#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))	tty->low_latency = 1;#endif	return(0);}/* * This routine is called when the serial port gets closed.  First, we * wait for the last remaining data to be sent.  Then, we unlink its * async structure from the interrupt chain if necessary, and we free * that IRQ if nothing is left in the chain. */static void mxser_close(struct tty_struct * tty, struct file * filp){	struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;	unsigned long	timeout;	MX_LOCK_INIT();

⌨️ 快捷键说明

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