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

📄 moxa.c

📁 moxa多串口卡linux下的驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	    ch->blocked_open = 0;	    ch->callout_termios = moxaCallout.init_termios;	    ch->normal_termios = moxaDriver.init_termios;#if (LINUX_VERSION_CODE < VERSION_CODE(2,4,0))	    ch->open_wait = 0;	    ch->close_wait = 0;#else	   init_waitqueue_head(&ch->open_wait);	   init_waitqueue_head(&ch->close_wait);#endif	}	for ( i=0; i< MAX_BOARDS; i++ ) {	    moxa_boards[i].boardType = 0;	    moxa_boards[i].numPorts = 0;	    moxa_boards[i].baseAddr = 0;	    moxa_boards[i].busType = 0;	    moxa_boards[i].pciInfo.busNum = 0;	    moxa_boards[i].pciInfo.devNum = 0;	}	MoxaDriverInit();	printk("Tty devices major number = %d, callout devices major number = %d\n", ttymajor, calloutmajor);        ret1 = 0;        ret2 = 0;	if ((ret1 = tty_register_driver(&moxaDriver))) {		printk(KERN_ERR "Couldn't install MOXA Intellio family driver !\n");	} else if ((ret2 = tty_register_driver(&moxaCallout))) {		tty_unregister_driver(&moxaDriver);		printk(KERN_ERR "Couldn't install MOXA Intellio family callout driver !\n");	}	if (ret1 || ret2) {		return -1;	}	for (i = 0; i < MAX_PORTS; i++) {		init_timer(&moxaEmptyTimer[i]);		moxaEmptyTimer[i].function = check_xmit_empty;		moxaEmptyTimer[i].data = (unsigned long) & moxaChannels[i];		moxaEmptyTimer_on[i] = 0;	}	init_timer(&moxaTimer);	moxaTimer.function = moxa_poll;	moxaTimer.expires = jiffies + (HZ / 50);	moxaTimer_on = 1;	add_timer(&moxaTimer);	/* Find the boards defined in source code */	numBoards = 0;	for (i = 0; i < MAX_BOARDS; i++) {	    if ((moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) ||	        (moxa_isa_boards[i].boardType == MOXA_BOARD_C320_ISA)) {	        moxa_boards[numBoards].boardType = moxa_isa_boards[i].boardType;		if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)	            moxa_boards[numBoards].numPorts = 8;		else				moxa_boards[numBoards].numPorts = moxa_isa_boards[i].numPorts;	        moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;	        moxa_boards[numBoards].baseAddr = moxa_isa_boards[i].baseAddr;		if (verbose)	            printk("Board %2d: %s board(baseAddr=%lx)\n",				       numBoards + 1,				       moxa_brdname[moxa_boards[numBoards].boardType - 1],			moxa_boards[numBoards].baseAddr);		numBoards++;	    }	}/* Find the boards defined form module args. */#ifdef MODULE	for (i = 0; i < MAX_BOARDS; i++) {		if ((type[i] == MOXA_BOARD_C218_ISA) ||		(type[i] == MOXA_BOARD_C320_ISA)) {		if (verbose)	            printk("Board %2d: %s board(baseAddr=%lx)\n",				       numBoards + 1,				       moxa_brdname[type[i] - 1],				       (unsigned long) baseaddr[i]);			if (numBoards >= MAX_BOARDS) {				if (verbose)					printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);		    continue;		}	        moxa_boards[numBoards].boardType = type[i];		if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)	            moxa_boards[numBoards].numPorts = 8;		else	            moxa_boards[numBoards].numPorts = numports[i];	        moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;	        moxa_boards[numBoards].baseAddr = baseaddr[i];		numBoards++;	    }	}#endif/* start to finding PCI board here */#ifdef CONFIG_PCI#if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))	if (pcibios_present()) {#else	if (pci_present()) {#endif	    n = sizeof (moxa_pcibrds)/sizeof (moxa_pciinfo);	    index = 0;	    i = 0;	    while (i < n) {	          if (pcibios_find_device(moxa_pcibrds[i].vendor_id,				moxa_pcibrds[i].device_id,				index,				&busnum,				&devnum) != 0) {	               i++;		       index = 0;		       continue;	           }		   if (verbose)	               printk("Board %2d: %s board(BusNo=%d,DevNo=%d)\n",                                numBoards+1,				moxa_brdname[moxa_pcibrds[i].board_type-1],				busnum,				devnum >> 3);	           index++;	           if ( numBoards >= MAX_BOARDS) {		       if (verbose)		           printk("More than %d MOXA Intellio family boards found. Board is ignored.",MAX_BOARDS);		    }		    else {		        moxa_get_PCI_conf(busnum,devnum,		        			moxa_pcibrds[i].board_type,						&moxa_boards[numBoards]);		        numBoards++;		    }	    }	}#endif#if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))	for ( i = 0; i < numBoards; i++) {#ifndef __alpha__	    if (moxa_boards[i].baseAddr >= 0x100000) { 		moxaBaseAddr[i] = (unsigned long) 			ioremap((unsigned long)moxa_boards[i].baseAddr,0x4000);	    }	    else #endif		moxaBaseAddr[i] = moxa_boards[i].baseAddr;	}#else	for ( i = 0; i < numBoards; i++) {		moxaBaseAddr[i] = (unsigned long) 			ioremap((unsigned long)moxa_boards[i].baseAddr,0x4000);	}#endif	return(0);}#ifdef	CONFIG_PCIstatic int moxa_get_PCI_conf(int busnum,int devnum,int board_type,moxa_board_conf *board){	unsigned int	val;	pcibios_read_config_dword(busnum,devnum,PCI_BASE_ADDRESS_2,&val);	if (val == 0xffffffff)		return (-1);	else 		board->baseAddr = val & PCI_BASE_ADDRESS_MEM_MASK;	board->boardType = board_type;	switch (board_type) {	case 	MOXA_BOARD_C218_ISA :	case 	MOXA_BOARD_C218_PCI :		board->numPorts = 8;		break;	case 	MOXA_BOARD_CP204J :		board->numPorts = 4;		break;	default :		board->numPorts = 0;		break;	}	board->busType = MOXA_BUS_TYPE_PCI;	board->pciInfo.busNum = busnum;	board->pciInfo.devNum = devnum >> 3;	return (0);}#endifstatic void do_moxa_softint(void *private_){	struct moxa_str 	*ch = (struct moxa_str *)private_;	struct tty_struct	*tty;	if (ch && (tty = ch->tty)) {#if (LINUX_VERSION_CODE <  VERSION_CODE(2,1,0))		if ( clear_bit(MOXA_EVENT_HANGUP, &ch->event) ) {#else		if ( test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event) ) {#endif			tty_hangup(tty);	/* FIXME: module removal race here - AKPM */			wake_up_interruptible(&ch->open_wait);			ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);		}	}	MOD_DEC_USE_COUNT;}     static int moxa_open(struct tty_struct *tty, struct file * filp){	struct moxa_str *ch;	int		port;	int		retval;	unsigned long	page;	port = PORTNO(tty);	if ( port == MAX_PORTS ) {	    MOD_INC_USE_COUNT;	    return(0);	}	if ( !MoxaPortIsValid(port) ) {	    tty->driver_data = NULL;	    return(-ENODEV);	}	down(&moxaBuffSem);	if ( !moxaXmitBuff ) {	    page = get_free_page(GFP_KERNEL);	    if ( !page ) {		up(&moxaBuffSem);		return(-ENOMEM);	    }	    if ( moxaXmitBuff )		free_page(page);	    else		moxaXmitBuff = (unsigned char *)page;	}	up(&moxaBuffSem);	MOD_INC_USE_COUNT;	ch = &moxaChannels[port];	ch->count++;	tty->driver_data = ch;	ch->tty = tty;	if (ch->count == 1 && (ch->asyncflags & ASYNC_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)		*tty->termios = ch->normal_termios;	    else		*tty->termios = ch->callout_termios;	}	ch->session = current->session;	ch->pgrp = current->pgrp;	if (!(ch->asyncflags & ASYNC_INITIALIZED)) {	    ch->statusflags = 0;	    set_tty_param(tty);	    MoxaPortLineCtrl(ch->port, 1, 1);	    MoxaPortEnable(ch->port);	    ch->asyncflags |= ASYNC_INITIALIZED;	}	retval = block_till_ready(tty, filp, ch);	moxa_unthrottle(tty);	if (ch->type == PORT_16550A) {		MoxaSetFifo(ch->port, 1);	} else {		MoxaSetFifo(ch->port, 0);	}	return (retval);}static void close_wait_until_sent(struct tty_struct *tty, signed long timeout){	long MoxaPortGetCurBaud(int port);	int MoxaPortExtTxQueue(int port);	int 	port;	long	baud;	int	tx_tout;	long	now;	struct	moxa_str *ch;	port = PORTNO(tty);	ch = (struct moxa_str*)tty->driver_data;	now = 0;	tx_tout = 0;	now = jiffies;	baud = MoxaPortGetCurBaud(port);	if(!baud)		baud = 9600;	tx_tout = 16*HZ*10/baud; /* for 16 bytes FIFO */	tx_tout++; /* for safe */	do{		int len;		current->state = TASK_INTERRUPTIBLE;		len = MoxaPortExtTxQueue(port);		if(len == 0){			break;		}		if (signal_pending(current))			break;		if(timeout>0)			if(jiffies-now > timeout)				break;		/* wait 16 bytes fifo time */		schedule_timeout(tx_tout);	}while(1);	current->state = TASK_RUNNING;	if(tx_tout)		schedule_timeout(tx_tout);}                         static void moxa_close(struct tty_struct *tty, struct file *filp){	struct moxa_str *ch;	int port;	port = PORTNO(tty);	if (port == MAX_PORTS) {		MOD_DEC_USE_COUNT;		return;	}	if (!MoxaPortIsValid(port)) {#ifdef SERIAL_DEBUG_CLOSE	    printk("Invalid portno in moxa_close\n");#endif	    tty->driver_data = NULL;	    return;	}	if (tty->driver_data == NULL) {		return;	}	if (tty_hung_up_p(filp)) {		MOD_DEC_USE_COUNT;		return;	}	ch = (struct moxa_str *) tty->driver_data;	if ((tty->count == 1) && (ch->count != 1)) {	    printk("moxa_close: bad serial port count; tty->count is 1, "		   "ch->count is %d\n", ch->count);	    ch->count = 1;	}	if (--ch->count < 0) {	    printk("moxa_close: bad serial port count, minor=%d\n",		   MINOR(tty->device));	    ch->count = 0;	}	if (ch->count) {		MOD_DEC_USE_COUNT;		return;	}	ch->asyncflags |= ASYNC_CLOSING;	/*	 * Save the termios structure, since this port may have	 * separate termios for callout and dialin.	 */	if ( ch->asyncflags & ASYNC_NORMAL_ACTIVE )	    ch->normal_termios = *tty->termios;	if ( ch->asyncflags & ASYNC_CALLOUT_ACTIVE )	    ch->callout_termios = *tty->termios;/* added by casper, 2/16/2000, for serial printer */	if ( ch->closing_wait != ASYNC_CLOSING_WAIT_NONE){	    close_wait_until_sent(tty, ch->closing_wait);  	}/*  */	if ( ch->asyncflags & ASYNC_INITIALIZED ) {	    setup_empty_event(tty);/* modified by casper, 2/16/2000, for serial printer */            close_wait_until_sent(tty, ch->closing_wait);	    //tty_wait_until_sent(tty, 30*HZ);	/* 30 seconds timeout *//*  */	    moxaEmptyTimer_on[ch->port] = 0;	    del_timer(&moxaEmptyTimer[ch->port]);	}	shut_down(ch);	MoxaPortFlushData(port, 2);	if ( tty->driver.flush_buffer )	    tty->driver.flush_buffer(tty);	if ( tty->ldisc.flush_buffer )	    tty->ldisc.flush_buffer(tty);	tty->closing = 0;	ch->event = 0;	ch->tty = 0;	/*********** delete by Linux 2.0.0 serial.c, why ???? *******	if ( tty->ldisc.num != ldiscs[N_TTY].num ) {	    if ( tty->ldisc.close )		(tty->ldisc.close)(tty);	    tty->ldisc = ldiscs[N_TTY];	    tty->termios->c_line = N_TTY;	    if ( tty->ldisc.open )		(tty->ldisc.open)(tty);	}	***************************************************************/	if ( ch->blocked_open ) {	    if ( ch->close_delay ) {		current->state = TASK_INTERRUPTIBLE;		schedule_timeout(ch->close_delay);	    }	    wake_up_interruptible(&ch->open_wait);	}	ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |			    ASYNC_CLOSING);	wake_up_interruptible(&ch->close_wait);        MOD_DEC_USE_COUNT;}        #if (LINUX_VERSION_CODE > VERSION_CODE(2,1,0))static void mx_wait_until_sent(struct tty_struct *tty, int timeout){	long MoxaPortGetCurBaud(int port);	int MoxaPortExtTxQueue(int port);	int 	port;	long	baud;	int	tx_tout;	long	now;	struct	moxa_str *ch;	port = PORTNO(tty);	ch = (struct moxa_str*)tty->driver_data;	now = 0;	tx_tout = 0;	now = jiffies;	baud = MoxaPortGetCurBaud(port);	if(!baud)		baud = 9600;	tx_tout = 16*HZ*10/baud; /* for 16 bytes FIFO */	tx_tout++; /* for safe */	do{		int len;		current->state = TASK_INTERRUPTIBLE;		len = MoxaPortExtTxQueue(port);		if(len == 0){			break;		}		if (signal_pending(current))			break;		if(timeout>0)			if(jiffies-now > timeout)				break;		/* wait 16 bytes fifo time */		schedule_timeout(tx_tout);	}while(1);	current->state = TASK_RUNNING;	if(tx_tout)		schedule_timeout(tx_tout);}                         #endif  static int moxa_write(struct tty_struct *tty, int from_user,		      const unsigned char *buf, int count){	struct moxa_str *ch;	int len, port;	unsigned long flags;	unsigned char *temp;

⌨️ 快捷键说明

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