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

📄 mxpcdrv.c

📁 isa总线设备
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *          mxpcdrv.c  -- MOXA PC104 Communication Module Linux driver. * *      Copyright (C) 1999-2007  Moxa Technologies (support@moxa.com.tw). * *      This code is loosely based on the Linux serial driver, written by *      Linus Torvalds, Theodore T'so and others. * *      This program is free software; you can redistribute it and/or modify *      it under the terms of the GNU General Public License as published by *      the Free Software Foundation; either version 2 of the License, or *      (at your option) any later version. * *      This program is distributed in the hope that it will be useful, *      but WITHOUT ANY WARRANTY; without even the implied warranty of *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *      GNU General Public License for more details. * *      You should have received a copy of the GNU General Public License *      along with this program; if not, write to the Free Software *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *	 *	Original release	03/20/03 * *	03/20/03	Support MOXA PC104 Communication Module. *			 */#ifdef 		MODVERSIONS#ifndef 	MODULE#define 	MODULE#endif#endif#include <linux/version.h>#define	VERSION_CODE(ver,rel,seq)	((ver << 16) | (rel << 8) | seq)#ifdef MODULE#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,18))#include <linux/config.h>#endif#ifdef MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#else#define	MOD_INC_USE_COUNT#define MOD_DEC_USE_COUNT#endif#include <linux/autoconf.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/serial.h>#include <linux/serial_reg.h>#include <linux/major.h>#include <linux/string.h>#include <linux/fcntl.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/smp_lock.h>#include <linux/delay.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/segment.h>#include <asm/bitops.h>#include "mxpcdrv.h"#define	MXPCDRV_VERSION	"1.2"#define	MXPCDRVMAJOR	 34#define	MXPCDRVCUMAJOR	 41	#if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))#define copy_from_user memcpy_fromfs#define copy_to_user memcpy_tofs#define put_to_user(arg1, arg2) put_fs_long(arg1, (unsigned long *)arg2)#define get_from_user(arg1, arg2) arg1 = get_fs_long((unsigned long *)arg2)#define schedule_timeout(x) {current->timeout = jiffies + (x); schedule();}#define signal_pending(x) ((x)->signal & ~(x)->blocked)#else#include <asm/uaccess.h>#define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)#define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2)#endif#define	MXPCDRV_EVENT_TXLOW	 1#define	MXPCDRV_EVENT_HANGUP	 2#define SERIAL_DO_RESTART#define MXPCDRV_BOARDS		4	/* Max. boards */#define MXPCDRV_PORTS		32	/* Max. ports */#define MXPCDRV_PORTS_PER_BOARD	8	/* Max. ports per board*/#define MXPCDRV_ISR_PASS_LIMIT	99999L#define MXPCDRV_BOARD_INDEX			4#define	MXPCDRV_ERR_IOADDR	-1#define	MXPCDRV_ERR_IRQ		-2#define	MXPCDRV_ERR_IRQ_CONFLIT	-3#define	MXPCDRV_ERR_VECTOR	-4#define SERIAL_TYPE_NORMAL	1#define SERIAL_TYPE_CALLOUT	2#define WAKEUP_CHARS		256#define UART_MCR_AFE		0x20#define UART_LSR_SPECIAL	0x1E#define	UART_CLK_DIV		921600#define MX_LOCK_INIT()		unsigned long flags=0#define MX_LOCK(lock)		{\				if(!in_interrupt())\					spin_lock_irqsave(lock, flags);\				}#define MX_UNLOCK(lock)		{\				if(!in_interrupt())\					spin_unlock_irqrestore(lock, flags);\				}#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0))#define PORTNO(x)	(MINOR((x)->device) - (x)->driver.minor_start)#else#define PORTNO(x)	((x)->index)#endif#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|IXON|IXOFF))#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)#ifndef MIN#define MIN(a,b)	((a) < (b) ? (a) : (b))#endif/* *	Define the Moxa device IDs. */#define CA104_ID    	1#define CA132_ID    	2#define CA132I_ID	3#define	CA108_ID			4#define	CA114_ID			5#define	CA134I_ID			6enum	{	MXPCDRV_BOARD_CA104 = 1,	MXPCDRV_BOARD_CA132,	MXPCDRV_BOARD_CA132I,	MXPCDRV_BOARD_CA108,	MXPCDRV_BOARD_CA114,	MXPCDRV_BOARD_CA134I};static char *mxpcdrv_brdname[] = {	"CA-104 series",	"CA-132 series",	"CA-132I series",	"CA-108 series",	"CA-114 series",	"CA-134I series"};static int mxpcdrv_numports[] = {	4,	// CA104	2,	// CA132	2,	// CA132I	8,	// CA108	4,	// CA114	4		// CA134I};	/* *	MOXA ioctls */#define MOXA			0x400#define MOXA_GETDATACOUNT     (MOXA + 23)#define	MOXA_GET_CONF         (MOXA + 35)#define MOXA_DIAGNOSE         (MOXA + 50)#define MOXA_CHKPORTENABLE    (MOXA + 60)#define MOXA_HighSpeedOn      (MOXA + 61)#define MOXA_GET_MAJOR        (MOXA + 63)#define MOXA_GET_CUMAJOR      (MOXA + 64)#define MOXA_GETMSTATUS       (MOXA + 65)#define MOXA_SET_SPECIAL_BAUD_RATE	(MOXA + 66)#define MOXA_GET_SPECIAL_BAUD_RATE	(MOXA + 67)typedef struct _moxa_pci_info {	unsigned short busNum;	unsigned short devNum;} moxa_pci_info;static int ioaddr[MXPCDRV_BOARDS]={0,0,0,0};static int iovect[MXPCDRV_BOARDS]={0,0,0,0};static int irq[MXPCDRV_BOARDS]={0,0,0,0};static int ttymajor=MXPCDRVMAJOR;static int calloutmajor=MXPCDRVCUMAJOR;static int verbose=0;#ifdef MODULE/* Variables for insmod */# if (LINUX_VERSION_CODE > VERSION_CODE(2,1,11))MODULE_AUTHOR("Eric Lo");MODULE_DESCRIPTION("MOXA PC104 Communication Module Device Driver");#if defined SP2 || (LINUX_VERSION_CODE > VERSION_CODE(2,6,9))int mx_ioaddr_array_num;int mx_iovect_array_num;int mx_irq_array_num;module_param_array(ioaddr, int, &mx_ioaddr_array_num, 0);module_param_array(iovect, int, &mx_iovect_array_num, 0);module_param_array(irq, int, &mx_irq_array_num, 0);module_param(ttymajor, int, 0);module_param(calloutmajor, int, 0);module_param(verbose, int, 0);#elseMODULE_PARM(ioaddr,     "1-4i");MODULE_PARM(iovect,     "1-4i");MODULE_PARM(irq,     	"1-4i");MODULE_PARM(ttymajor,   "i");MODULE_PARM(calloutmajor,    "i");MODULE_PARM(verbose,        "i");#endif#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endif# endif#endif /* MODULE */struct mxpcdrv_hwconf {	int		board_type;	int		ports;	int		irq;	int		vector;	int		vector_mask;	int		uart_type;	int		ioaddr[MXPCDRV_PORTS_PER_BOARD];	int		baud_base[MXPCDRV_PORTS_PER_BOARD];	moxa_pci_info	pciInfo;	int		IsMoxaMustChipFlag;	// add by Victor Yu. 08-30-2002	int		MaxCanSetBaudRate[MXPCDRV_PORTS_PER_BOARD];	// add by Victor Yu. 09-04-2002};struct mxpcdrv_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_trigger;	/* Rx fifo trigger level */	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#if (LINUX_VERSION_CODE > VERSION_CODE(2,6,19))	struct ktermios		normal_termios;	struct ktermios		callout_termios;#else	struct termios		normal_termios;	struct termios		callout_termios;#endif#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	unsigned char       	ldisc_stop_rx;	spinlock_t		slock;	int 			cur_baud;};struct mxpcdrv_log {	int	tick;	int	rxcnt[MXPCDRV_PORTS];	int	txcnt[MXPCDRV_PORTS];};struct mxpcdrv_mstatus{       tcflag_t	cflag;       int  	cts;       int  	dsr;       int  	ri;       int  	dcd;};static  struct mxpcdrv_mstatus GMStatus[MXPCDRV_PORTS];static int mxpcdrvBoardIO[MXPCDRV_BOARDS]  = {	0,0,0,0	       /*  0x180, 0x280, 0x200, 0x320   */};static int mxpcdrvBoardIRQ[MXPCDRV_BOARDS]  = {	0,0,0,0	};static int mxpcdrvBoardVECT[MXPCDRV_BOARDS]  = {	0,0,0,0	};#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;#endif//static struct tty_driver	mxvar_sdriver, mxvar_cdriver;//static int			mxvar_refcount;static struct mxpcdrv_struct	mxvar_table[MXPCDRV_PORTS];static struct tty_struct *	mxvar_tty[MXPCDRV_PORTS+1];#if (LINUX_VERSION_CODE > VERSION_CODE(2,6,19))static struct ktermios * 	mxvar_termios[MXPCDRV_PORTS+1];static struct ktermios * 	mxvar_termios_locked[MXPCDRV_PORTS+1];#elsestatic struct termios * 	mxvar_termios[MXPCDRV_PORTS+1];static struct termios * 	mxvar_termios_locked[MXPCDRV_PORTS+1];#endifstatic struct mxpcdrv_log 	mxvar_log;static int			mxvar_diagflag;/* * 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 */static int mxvar_baud_table[] = {	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,	9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 0 };	struct mxpcdrv_hwconf mxpcdrvcfg[MXPCDRV_BOARDS];/* * static functions: */#ifdef MODULEint		init_module(void);void		cleanup_module(void);#endifstatic void 	mxpcdrv_getcfg(int board,struct mxpcdrv_hwconf *hwconf);int		mxpcdrv_init(void);static int	mxpcdrv_get_ISA_conf(int, int, struct mxpcdrv_hwconf *, int);#if (LINUX_VERSION_CODE > VERSION_CODE(2,6,19))static void	mxpcdrv_do_softint(struct work_struct *work);#elsestatic void	mxpcdrv_do_softint(void *);#endifstatic int	mxpcdrv_open(struct tty_struct *, struct file *);static void	mxpcdrv_close(struct tty_struct *, struct file *);#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,10))static int	mxpcdrv_write(struct tty_struct *, int, const unsigned char *, int);#elsestatic int	mxpcdrv_write(struct tty_struct *, const unsigned char *, int);#endifstatic int	mxpcdrv_write_room(struct tty_struct *);static void	mxpcdrv_flush_buffer(struct tty_struct *);static int	mxpcdrv_chars_in_buffer(struct tty_struct *);static void	mxpcdrv_flush_chars(struct tty_struct *);static void	mxpcdrv_put_char(struct tty_struct *, unsigned char);static int	mxpcdrv_ioctl(struct tty_struct *, struct file *, uint, ulong);static int	mxpcdrv_ioctl_special(unsigned int, unsigned long);static void	mxpcdrv_throttle(struct tty_struct *);static void	mxpcdrv_unthrottle(struct tty_struct *);#if (LINUX_VERSION_CODE > VERSION_CODE(2,6,19))static void	mxpcdrv_set_termios(struct tty_struct *, struct ktermios *);#elsestatic void	mxpcdrv_set_termios(struct tty_struct *, struct termios *);#endifstatic void	mxpcdrv_stop(struct tty_struct *);static void	mxpcdrv_start(struct tty_struct *);static void	mxpcdrv_hangup(struct tty_struct *);#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, void *, struct pt_regs *);#endifstatic void mxpcdrv_receive_chars(struct mxpcdrv_struct *, int *);static void mxpcdrv_transmit_chars(struct mxpcdrv_struct *);static void mxpcdrv_check_modem_status(struct mxpcdrv_struct *, int);static int	mxpcdrv_block_til_ready(struct tty_struct *, struct file *, struct mxpcdrv_struct *);static int	mxpcdrv_startup(struct mxpcdrv_struct *);static void	mxpcdrv_shutdown(struct mxpcdrv_struct *);#if (LINUX_VERSION_CODE > VERSION_CODE(2,6,19))static int	mxpcdrv_change_speed(struct mxpcdrv_struct *, struct ktermios *old_termios);#elsestatic int	mxpcdrv_change_speed(struct mxpcdrv_struct *, struct termios *old_termios);#endifstatic int	mxpcdrv_get_serial_info(struct mxpcdrv_struct *, struct serial_struct *);static int	mxpcdrv_set_serial_info(struct mxpcdrv_struct *, struct serial_struct *);static int	mxpcdrv_get_lsr_info(struct mxpcdrv_struct *, unsigned int *);static void	mxpcdrv_send_break(struct mxpcdrv_struct *, int);#if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,0))static int mxpcdrv_tiocmget(struct tty_struct *, struct file *);static int mxpcdrv_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int);#elsestatic int	mxpcdrv_get_modem_info(struct mxpcdrv_struct *, unsigned int *);static int	mxpcdrv_set_modem_info(struct mxpcdrv_struct *, unsigned int, unsigned int *);#endif#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))static void mxpcdrv_wait_until_sent(struct tty_struct *tty, int timeout);#endifstatic void mxpcdrv_startrx(struct tty_struct * tty);static void mxpcdrv_stoprx(struct tty_struct * tty);static void mxpcdrv_set_special_baudrate(struct mxpcdrv_struct * info, int baud);

⌨️ 快捷键说明

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