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

📄 mxser.c

📁 MOXA 串口驱动编程
💻 C
📖 第 1 页 / 共 5 页
字号:
	unsigned long	txcnt[MXSER_PORTS];};struct mxser_mon{        unsigned long   rxcnt;        unsigned long   txcnt;		unsigned long	up_rxcnt;		unsigned long	up_txcnt;        int             modem_status;        unsigned char   hold_reason;};struct mxser_mon_ext{	unsigned long rx_cnt[32];	unsigned long tx_cnt[32];	unsigned long up_rxcnt[32];	unsigned long up_txcnt[32];	int	modem_status[32];	long baudrate[32];	int databits[32];	int stopbits[32];	int parity[32];	int flowctrl[32];	int fifo[32];	int iftype[32];};struct mxser_hwconf {	int		board_type;	int		ports;	int		irq;	int		vector;	int		vector_mask;	int		uart_type;	int		ioaddr[MXSER_PORTS_PER_BOARD];	int		baud_base[MXSER_PORTS_PER_BOARD];	moxa_pci_info	pciInfo;	int		IsMoxaMustChipFlag;	// add by Victor Yu. 08-30-2002	int		MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD];	// add by Victor Yu. 09-04-2002	int		opmode_ioaddr[MXSER_PORTS_PER_BOARD];	// add by Victor Yu. 01-05-2004};struct mxser_struct {	int			port;	int			base;		/* port base address */	int			irq;		/* port using irq no. */	int			vector; 	/* port irq vector */	int			vectormask;	/* port vector mask */	int			rx_high_water;	int			rx_trigger;	/* Rx fifo trigger level */	int			rx_low_water;	int			baud_base;	/* max. speed */	int			flags;		/* defined in tty.h */	int			type;		/* UART type */	struct tty_struct *	tty;	int			read_status_mask;	int			ignore_status_mask;	int			xmit_fifo_size;	int			custom_divisor;	int			x_char; 	/* xon/xoff character */	int			close_delay;	unsigned short		closing_wait;	int			IER;		/* Interrupt Enable Register */	int			MCR;		/* Modem control register */	unsigned long		event;	int			count;		/* # of fd on device */	int			blocked_open;	/* # of blocked opens */	long			session;	/* Session of opening process */	long			pgrp;		/* pgrp of opening process */	unsigned char		*xmit_buf;	int			xmit_head;	int			xmit_tail;	int			xmit_cnt;#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))		struct tq_struct	tqueue;#else	struct work_struct tqueue;#endif		struct termios		normal_termios;	struct termios		callout_termios;#if (LINUX_VERSION_CODE < VERSION_CODE(2,4,0))	struct wait_queue	*open_wait;	struct wait_queue	*close_wait;	struct wait_queue	*delta_msr_wait;#else	wait_queue_head_t open_wait;	wait_queue_head_t close_wait;	wait_queue_head_t delta_msr_wait;#endif	struct async_icount	icount; 	/* kernel counters for the 4 input interrupts */	int			timeout;	int			IsMoxaMustChipFlag;	// add by Victor Yu. 08-30-2002	int			MaxCanSetBaudRate;	// add by Victor Yu. 09-04-2002	int		opmode_ioaddr;	// add by Victor Yu. 01-05-2004	unsigned char		stop_rx;	unsigned char       ldisc_stop_rx;	long    realbaud;	struct mxser_mon        mon_data;	unsigned char           err_shadow;	spinlock_t		slock;};struct mxser_mstatus{       tcflag_t	cflag;       int  	cts;       int  	dsr;       int  	ri;       int  	dcd;};static  struct mxser_mstatus GMStatus[MXSER_PORTS];static int mxserBoardCAP[MXSER_BOARDS]  = {	0,0,0,0       /*  0x180, 0x280, 0x200, 0x320   */};#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))static struct tty_driver	mxvar_sdriver;static struct tty_driver	mxvar_cdriver;#elsestatic struct tty_driver	*mxvar_sdriver;#endif#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))static int			mxvar_refcount;#endifstatic struct mxser_struct	mxvar_table[MXSER_PORTS];static struct tty_struct *	mxvar_tty[MXSER_PORTS+1];static struct termios * 	mxvar_termios[MXSER_PORTS+1];static struct termios * 	mxvar_termios_locked[MXSER_PORTS+1];static struct mxser_log 	mxvar_log;static int			mxvar_diagflag;static unsigned char mxser_msr[MXSER_PORTS+1];static struct mxser_mon_ext mon_data_ext;static int mxser_set_baud_method[MXSER_PORTS+1];static spinlock_t		gm_lock;//static int                      moxaTimer_on;//static struct timer_list        moxaTimer;/* * mxvar_tmp_buf is used as a temporary buffer by serial_write. We need * to lock it in case the memcpy_fromfs blocks while swapping in a page, * and some other program tries to do a serial write at the same time. * Since the lock will only come under contention when the system is * swapping and available memory is low, it makes sense to share one * buffer across all the serial ports, since it significantly saves * memory if large numbers of serial ports are open. */#if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0))static unsigned char *		mxvar_tmp_buf;static struct semaphore 	mxvar_tmp_buf_sem;#elsestatic unsigned char *		mxvar_tmp_buf = 0;static struct semaphore 	mxvar_tmp_buf_sem = MUTEX;#endif/* * This is used to figure out the divisor speeds and the timeouts */struct mxser_hwconf mxsercfg[MXSER_BOARDS];/* * static functions: */#ifdef MODULEint		init_module(void);void		cleanup_module(void);#endifstatic void 	mxser_getcfg(int board,struct mxser_hwconf *hwconf);int		mxser_init(void);//static void	mxser_poll(unsigned long);static int	mxser_get_ISA_conf(int, struct mxser_hwconf *);#ifdef CONFIG_PCIstatic int      mxser_get_PCI_conf(int ,int ,int ,struct mxser_hwconf *);#endifstatic void	mxser_do_softint(void *);static int	mxser_open(struct tty_struct *, struct file *);static void	mxser_close(struct tty_struct *, struct file *);static int	mxser_write(struct tty_struct *, int, const unsigned char *, int);static int	mxser_write_room(struct tty_struct *);static void	mxser_flush_buffer(struct tty_struct *);static int	mxser_chars_in_buffer(struct tty_struct *);static void	mxser_flush_chars(struct tty_struct *);static void	mxser_put_char(struct tty_struct *, unsigned char);static int	mxser_ioctl(struct tty_struct *, struct file *, uint, ulong);static int	mxser_ioctl_special(unsigned int, unsigned long);static void	mxser_throttle(struct tty_struct *);static void	mxser_unthrottle(struct tty_struct *);static void	mxser_set_termios(struct tty_struct *, struct termios *);static void	mxser_stop(struct tty_struct *);static void	mxser_start(struct tty_struct *);static void	mxser_hangup(struct tty_struct *);static void mxser_rs_break(struct tty_struct *, int);static IRQ_RET	mxser_interrupt(int, void *, struct pt_regs *);static inline void mxser_receive_chars(struct mxser_struct *, int *);static inline void mxser_transmit_chars(struct mxser_struct *);static inline void mxser_check_modem_status(struct mxser_struct *, int);static int	mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);static int	mxser_startup(struct mxser_struct *);static void	mxser_shutdown(struct mxser_struct *);static int	mxser_change_speed(struct mxser_struct *, struct termios *old_termios);static int	mxser_get_serial_info(struct mxser_struct *, struct serial_struct *);static int	mxser_set_serial_info(struct mxser_struct *, struct serial_struct *);static int	mxser_get_lsr_info(struct mxser_struct *, unsigned int *);static void	mxser_send_break(struct mxser_struct *, int);#if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,0))static int mxser_tiocmget(struct tty_struct *, struct file *);static int mxser_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int);#elsestatic int	mxser_get_modem_info(struct mxser_struct *, unsigned int *);static int	mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned int *);#endifstatic int mxser_set_baud(struct mxser_struct *info, long newspd);#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))static void 	mxser_wait_until_sent(struct tty_struct *tty, int timeout);#endifstatic void mxser_startrx(struct tty_struct * tty);static void mxser_stoprx(struct tty_struct * tty);static int CheckIsMoxaMust(int io){	UCHAR	oldmcr, hwid;	int	i;	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(MOXA_OTHER_UART);	}		GET_MOXA_MUST_HARDWARE_ID(io, &hwid);	for(i=0; i<UART_TYPE_NUM; i++){		if(hwid == Gmoxa_uart_id[i])			return (int)hwid;	}	return MOXA_OTHER_UART;}// above is modified by Victor Yu. 08-15-2002#if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,0))static struct tty_operations mxser_ops = {	.open = mxser_open,	.close = mxser_close,	.write = mxser_write,	.put_char = mxser_put_char,	.flush_chars = mxser_flush_chars,	.write_room = mxser_write_room,	.chars_in_buffer = mxser_chars_in_buffer,	.flush_buffer = mxser_flush_buffer,	.ioctl = mxser_ioctl,	.throttle = mxser_throttle,	.unthrottle = mxser_unthrottle,	.set_termios = mxser_set_termios,	.stop = mxser_stop,	.start = mxser_start,	.hangup = mxser_hangup,	.tiocmget = mxser_tiocmget,	.tiocmset = mxser_tiocmset,};#endif/* * The MOXA Smartio/Industio serial driver boot-time initialization code! */#ifdef MODULEINIT_FUNC_RET	INIT_FUNC(void){	int	ret;	if (verbose)		printk("Loading module mxser ...\n");	ret = mxser_init();	if (verbose)		printk("Done.\n");	return (ret);}CLEAR_FUNC_RET	CLEAR_FUNC(void){	int i,err = 0;	if (verbose)		printk("Unloading module mxser ...\n");#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))	if ((err |= tty_unregister_driver(&mxvar_cdriver)))		printk("Couldn't unregister MOXA Smartio/Industio family callout driver\n");#endif			if ((err |= tty_unregister_driver(DRV_VAR)))		printk("Couldn't unregister MOXA Smartio/Industio family serial driver\n");        for(i=0; i<MXSER_BOARDS; i++){	    struct pci_dev *pdev;	    if(mxsercfg[i].board_type == -1)	        continue;            else{		pdev = mxsercfg[i].pciInfo.pdev;	        free_irq(mxsercfg[i].irq, &mxvar_table[i*MXSER_PORTS_PER_BOARD]);		if(pdev!=NULL){ //PCI			release_region(pci_resource_start(pdev, 2),	       			pci_resource_len(pdev, 2));			release_region(pci_resource_start(pdev, 3),		       		pci_resource_len(pdev, 3));		}else{			release_region(mxsercfg[i].ioaddr[0],					8*mxsercfg[i].ports);			release_region(mxsercfg[i].vector, 1);		}            }        }		if (verbose)		printk("Done.\n");}#endifstatic void process_txrx_fifo(struct mxser_struct *info){	int i;		if ( (info->type == PORT_16450) || (info->type == PORT_8250) ){		info->rx_trigger = 1;		info->rx_high_water = 1;		info->rx_low_water = 1;		info->xmit_fifo_size = 1;	}else{		for(i=0; i<UART_INFO_NUM; i++){			if(info->IsMoxaMustChipFlag == Gpci_uart_info[i].type){				info->rx_trigger = Gpci_uart_info[i].rx_trigger;				info->rx_low_water = Gpci_uart_info[i].rx_low_water;				info->rx_high_water = Gpci_uart_info[i].rx_high_water;					info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size;					break;			}		}	}}int mxser_initbrd(int board,struct mxser_hwconf *hwconf){	struct mxser_struct *	info;	unsigned long	flags;                int     retval;	int	i,n;#if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0))	init_MUTEX(&mxvar_tmp_buf_sem);#endif	n = board*MXSER_PORTS_PER_BOARD;	info = &mxvar_table[n];	/*if (verbose)*/ {#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))		printk("        ttyM%d/cum%d - ttyM%d/cum%d  ", 			n, n, n+hwconf->ports-1, n+hwconf->ports-1);#else		printk("        ttyM%d - ttyM%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->opmode_ioaddr = hwconf->opmode_ioaddr[i];	// add by Victor Yu. 01-05-2004		info->stop_rx = 0;	        info->ldisc_stop_rx = 0;		info->IsMoxaMustChipFlag = hwconf->IsMoxaMustChipFlag;		//Enhance mode enabled here		if(info->IsMoxaMustChipFlag!=MOXA_OTHER_UART){			ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base);		}		info->flags = ASYNC_SHARE_IRQ;		info->type = hwconf->uart_type;		info->baud_base = hwconf->baud_base[i];				info->MaxCanSetBaudRate = hwconf->MaxCanSetBaudRate[i];		process_txrx_fifo(info);				info->custom_divisor = hwconf->baud_base[i] * 16;		info->close_delay = 5*HZ/10;		info->closing_wait = 30*HZ;		INIT_WORK(&info->tqueue, mxser_do_softint, info);#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                memset(&info->mon_data, 0, sizeof(struct mxser_mon));		info->err_shadow = 0;		spin_lock_init(&info->slock);	}	/*	 * 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*MXSER_PORTS_PER_BOARD;	info = &mxvar_table[n];	        MX_LOCK(&info->slock);        retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info),				 "mxser", info);	if ( retval ) {	    MX_UNLOCK(&info->slock);	    printk("Board %d: %s", board, mxser_brdname[hwconf->board_type-1]);	    printk("  Request irq fail,IRQ (%d) may be conflit with another device.\n",info->irq);	    return(retval);	}		MX_UNLOCK(&info->slock);	        return 0;}static void mxser_getcfg(int board,struct mxser_hwconf *hwconf){	mxsercfg[board] = *hwconf;}#ifdef CONFIG_PCIstatic int mxser_get_PCI_conf(int busnum,int devnum,int board_type,struct mxser_hwconf *hwconf){	int		i, j;//	unsigned int	val;	unsigned int	ioaddress;	struct pci_dev	*pdev=hwconf->pciInfo.pdev;	//io address	hwconf->board_type = board_type;	hwconf->ports = mxser_numports[board_type-1];	ioaddress = pci_resource_start(pdev, 2);	request_region(pci_resource_start(pdev, 2),

⌨️ 快捷键说明

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