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

📄 synclink_cs.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * linux/drivers/char/pcmcia/synclink_cs.c * * $Id: synclink_cs.c,v 4.34 2005/09/08 13:20:54 paulkf Exp $ * * Device driver for Microgate SyncLink PC Card * multiprotocol serial adapter. * * written by Paul Fulghum for Microgate Corporation * paulkf@microgate.com * * Microgate and SyncLink are trademarks of Microgate Corporation * * This code is released under the GNU General Public License (GPL) * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))#if defined(__i386__)#  define BREAKPOINT() asm("   int $3");#else#  define BREAKPOINT() { }#endif#define MAX_DEVICE_COUNT 4#include <linux/config.h>	#include <linux/module.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/time.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/serial.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/slab.h>#include <linux/netdevice.h>#include <linux/vmalloc.h>#include <linux/init.h>#include <asm/serial.h>#include <linux/delay.h>#include <linux/ioctl.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/dma.h>#include <linux/bitops.h>#include <asm/types.h>#include <linux/termios.h>#include <linux/workqueue.h>#include <linux/hdlc.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/cisreg.h>#include <pcmcia/ds.h>#ifdef CONFIG_HDLC_MODULE#define CONFIG_HDLC 1#endif#define GET_USER(error,value,addr) error = get_user(value,addr)#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0#define PUT_USER(error,value,addr) error = put_user(value,addr)#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0#include <asm/uaccess.h>#include "linux/synclink.h"static MGSL_PARAMS default_params = {	MGSL_MODE_HDLC,			/* unsigned long mode */	0,				/* unsigned char loopback; */	HDLC_FLAG_UNDERRUN_ABORT15,	/* unsigned short flags; */	HDLC_ENCODING_NRZI_SPACE,	/* unsigned char encoding; */	0,				/* unsigned long clock_speed; */	0xff,				/* unsigned char addr_filter; */	HDLC_CRC_16_CCITT,		/* unsigned short crc_type; */	HDLC_PREAMBLE_LENGTH_8BITS,	/* unsigned char preamble_length; */	HDLC_PREAMBLE_PATTERN_NONE,	/* unsigned char preamble; */	9600,				/* unsigned long data_rate; */	8,				/* unsigned char data_bits; */	1,				/* unsigned char stop_bits; */	ASYNC_PARITY_NONE		/* unsigned char parity; */};typedef struct{	int count;	unsigned char status;	char data[1];} RXBUF;/* The queue of BH actions to be performed */#define BH_RECEIVE  1#define BH_TRANSMIT 2#define BH_STATUS   4#define IO_PIN_SHUTDOWN_LIMIT 100#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))struct _input_signal_events {	int	ri_up;		int	ri_down;	int	dsr_up;	int	dsr_down;	int	dcd_up;	int	dcd_down;	int	cts_up;	int	cts_down;};/* * Device instance data structure */ typedef struct _mgslpc_info {	void *if_ptr;	/* General purpose pointer (used by SPPP) */	int			magic;	int			flags;	int			count;		/* count of opens */	int			line;	unsigned short		close_delay;	unsigned short		closing_wait;	/* time to wait before closing */		struct mgsl_icount	icount;		struct tty_struct 	*tty;	int			timeout;	int			x_char;		/* xon/xoff character */	int			blocked_open;	/* # of blocked opens */	unsigned char		read_status_mask;	unsigned char		ignore_status_mask;		unsigned char *tx_buf;	int            tx_put;	int            tx_get;	int            tx_count;	/* circular list of fixed length rx buffers */	unsigned char  *rx_buf;        /* memory allocated for all rx buffers */	int            rx_buf_total_size; /* size of memory allocated for rx buffers */	int            rx_put;         /* index of next empty rx buffer */	int            rx_get;         /* index of next full rx buffer */	int            rx_buf_size;    /* size in bytes of single rx buffer */	int            rx_buf_count;   /* total number of rx buffers */	int            rx_frame_count; /* number of full rx buffers */		wait_queue_head_t	open_wait;	wait_queue_head_t	close_wait;		wait_queue_head_t	status_event_wait_q;	wait_queue_head_t	event_wait_q;	struct timer_list	tx_timer;	/* HDLC transmit timeout timer */	struct _mgslpc_info	*next_device;	/* device list link */	unsigned short imra_value;	unsigned short imrb_value;	unsigned char  pim_value;	spinlock_t lock;	struct work_struct task;		/* task structure for scheduling bh */	u32 max_frame_size;	u32 pending_bh;	int bh_running;	int bh_requested;		int dcd_chkcount; /* check counts to prevent */	int cts_chkcount; /* too many IRQs if a signal */	int dsr_chkcount; /* is floating */	int ri_chkcount;	int rx_enabled;	int rx_overflow;	int tx_enabled;	int tx_active;	int tx_aborting;	u32 idle_mode;	int if_mode; /* serial interface selection (RS-232, v.35 etc) */	char device_name[25];		/* device instance name */	unsigned int io_base;	/* base I/O address of adapter */	unsigned int irq_level;		MGSL_PARAMS params;		/* communications parameters */	unsigned char serial_signals;	/* current serial signal states */	char irq_occurred;		/* for diagnostics use */	char testing_irq;	unsigned int init_error;	/* startup error (DIAGS)	*/	char flag_buf[MAX_ASYNC_BUFFER_SIZE];	BOOLEAN drop_rts_on_tx_done;	struct	_input_signal_events	input_signal_events;	/* PCMCIA support */	struct pcmcia_device	*p_dev;	dev_node_t	      node;	int		      stop;	/* SPPP/Cisco HDLC device parts */	int netcount;	int dosyncppp;	spinlock_t netlock;#ifdef CONFIG_HDLC	struct net_device *netdev;#endif} MGSLPC_INFO;#define MGSLPC_MAGIC 0x5402/* * The size of the serial xmit buffer is 1 page, or 4096 bytes */#define TXBUFSIZE 4096    #define CHA     0x00   /* channel A offset */#define CHB     0x40   /* channel B offset *//* *  FIXME: PPC has PVR defined in asm/reg.h.  For now we just undef it. */#undef PVR#define RXFIFO  0#define TXFIFO  0#define STAR    0x20#define CMDR    0x20#define RSTA    0x21#define PRE     0x21#define MODE    0x22#define TIMR    0x23#define XAD1    0x24#define XAD2    0x25#define RAH1    0x26#define RAH2    0x27#define DAFO    0x27#define RAL1    0x28#define RFC     0x28#define RHCR    0x29#define RAL2    0x29#define RBCL    0x2a#define XBCL    0x2a#define RBCH    0x2b#define XBCH    0x2b#define CCR0    0x2c#define CCR1    0x2d#define CCR2    0x2e#define CCR3    0x2f#define VSTR    0x34#define BGR     0x34#define RLCR    0x35#define AML     0x36#define AMH     0x37#define GIS     0x38#define IVA     0x38#define IPC     0x39#define ISR     0x3a#define IMR     0x3a#define PVR     0x3c#define PIS     0x3d#define PIM     0x3d#define PCR     0x3e#define CCR4    0x3f    // IMR/ISR    #define IRQ_BREAK_ON    BIT15   // rx break detected#define IRQ_DATAOVERRUN BIT14	// receive data overflow#define IRQ_ALLSENT     BIT13	// all sent#define IRQ_UNDERRUN    BIT12	// transmit data underrun#define IRQ_TIMER       BIT11	// timer interrupt#define IRQ_CTS         BIT10	// CTS status change#define IRQ_TXREPEAT    BIT9	// tx message repeat#define IRQ_TXFIFO      BIT8	// transmit pool ready#define IRQ_RXEOM       BIT7	// receive message end#define IRQ_EXITHUNT    BIT6	// receive frame start#define IRQ_RXTIME      BIT6    // rx char timeout#define IRQ_DCD         BIT2	// carrier detect status change#define IRQ_OVERRUN     BIT1	// receive frame overflow#define IRQ_RXFIFO      BIT0	// receive pool full    // STAR    #define XFW   BIT6		// transmit FIFO write enable#define CEC   BIT2		// command executing#define CTS   BIT1		// CTS state    #define PVR_DTR      BIT0#define PVR_DSR      BIT1#define PVR_RI       BIT2#define PVR_AUTOCTS  BIT3#define PVR_RS232    0x20   /* 0010b */#define PVR_V35      0xe0   /* 1110b */#define PVR_RS422    0x40   /* 0100b */    /* Register access functions */     #define write_reg(info, reg, val) outb((val),(info)->io_base + (reg))#define read_reg(info, reg) inb((info)->io_base + (reg))#define read_reg16(info, reg) inw((info)->io_base + (reg))  #define write_reg16(info, reg, val) outw((val), (info)->io_base + (reg))    #define set_reg_bits(info, reg, mask) \    write_reg(info, (reg), \		 (unsigned char) (read_reg(info, (reg)) | (mask)))  #define clear_reg_bits(info, reg, mask) \    write_reg(info, (reg), \		 (unsigned char) (read_reg(info, (reg)) & ~(mask)))  /* * interrupt enable/disable routines */ static void irq_disable(MGSLPC_INFO *info, unsigned char channel, unsigned short mask) {	if (channel == CHA) {		info->imra_value |= mask;		write_reg16(info, CHA + IMR, info->imra_value);	} else {		info->imrb_value |= mask;		write_reg16(info, CHB + IMR, info->imrb_value);	}}static void irq_enable(MGSLPC_INFO *info, unsigned char channel, unsigned short mask) {	if (channel == CHA) {		info->imra_value &= ~mask;		write_reg16(info, CHA + IMR, info->imra_value);	} else {		info->imrb_value &= ~mask;		write_reg16(info, CHB + IMR, info->imrb_value);	}}#define port_irq_disable(info, mask) \  { info->pim_value |= (mask); write_reg(info, PIM, info->pim_value); }#define port_irq_enable(info, mask) \  { info->pim_value &= ~(mask); write_reg(info, PIM, info->pim_value); }static void rx_start(MGSLPC_INFO *info);static void rx_stop(MGSLPC_INFO *info);static void tx_start(MGSLPC_INFO *info);static void tx_stop(MGSLPC_INFO *info);static void tx_set_idle(MGSLPC_INFO *info);static void get_signals(MGSLPC_INFO *info);static void set_signals(MGSLPC_INFO *info);static void reset_device(MGSLPC_INFO *info);static void hdlc_mode(MGSLPC_INFO *info);static void async_mode(MGSLPC_INFO *info);static void tx_timeout(unsigned long context);static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg);#ifdef CONFIG_HDLC#define dev_to_port(D) (dev_to_hdlc(D)->priv)static void hdlcdev_tx_done(MGSLPC_INFO *info);static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size);static int  hdlcdev_init(MGSLPC_INFO *info);static void hdlcdev_exit(MGSLPC_INFO *info);#endifstatic void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit);static BOOLEAN register_test(MGSLPC_INFO *info);static BOOLEAN irq_test(MGSLPC_INFO *info);static int adapter_test(MGSLPC_INFO *info);static int claim_resources(MGSLPC_INFO *info);static void release_resources(MGSLPC_INFO *info);static void mgslpc_add_device(MGSLPC_INFO *info);static void mgslpc_remove_device(MGSLPC_INFO *info);static int  rx_get_frame(MGSLPC_INFO *info);static void rx_reset_buffers(MGSLPC_INFO *info);static int  rx_alloc_buffers(MGSLPC_INFO *info);static void rx_free_buffers(MGSLPC_INFO *info);static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs);/* * Bottom half interrupt handlers */static void bh_handler(void* Context);static void bh_transmit(MGSLPC_INFO *info);static void bh_status(MGSLPC_INFO *info);/* * ioctl handlers */static int tiocmget(struct tty_struct *tty, struct file *file);static int tiocmset(struct tty_struct *tty, struct file *file,		    unsigned int set, unsigned int clear);static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount);static int get_params(MGSLPC_INFO *info, MGSL_PARAMS __user *user_params);static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params);static int get_txidle(MGSLPC_INFO *info, int __user *idle_mode);static int set_txidle(MGSLPC_INFO *info, int idle_mode);static int set_txenable(MGSLPC_INFO *info, int enable);static int tx_abort(MGSLPC_INFO *info);static int set_rxenable(MGSLPC_INFO *info, int enable);static int wait_events(MGSLPC_INFO *info, int __user *mask);static MGSLPC_INFO *mgslpc_device_list = NULL;static int mgslpc_device_count = 0;/* * Set this param to non-zero to load eax with the * .text section address and breakpoint on module load. * This is useful for use with gdb and add-symbol-file command. */static int break_on_load=0;/* * Driver major number, defaults to zero to get auto * assigned major number. May be forced as module parameter. */static int ttymajor=0;static int debug_level = 0;static int maxframe[MAX_DEVICE_COUNT] = {0,};static int dosyncppp[MAX_DEVICE_COUNT] = {1,1,1,1};module_param(break_on_load, bool, 0);module_param(ttymajor, int, 0);module_param(debug_level, int, 0);module_param_array(maxframe, int, NULL, 0);module_param_array(dosyncppp, int, NULL, 0);MODULE_LICENSE("GPL");static char *driver_name = "SyncLink PC Card driver";static char *driver_version = "$Revision: 4.34 $";static struct tty_driver *serial_driver;/* number of characters left in xmit buffer before we ask for more */#define WAKEUP_CHARS 256static void mgslpc_change_params(MGSLPC_INFO *info);static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);/* PCMCIA prototypes */static int mgslpc_config(struct pcmcia_device *link);static void mgslpc_release(u_long arg);static void mgslpc_detach(struct pcmcia_device *p_dev);/* * 1st function defined in .text section. Calling this function in * init_module() followed by a breakpoint allows a remote debugger * (gdb) to get the .text address for the add-symbol-file command. * This allows remote debugging of dynamically loadable modules. */static void* mgslpc_get_text_ptr(void){

⌨️ 快捷键说明

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