📄 ip2main.c
字号:
/*** (c) 1999 by Computone Corporation*********************************************************************************** PACKAGE: Linux tty Device Driver for IntelliPort family of multiport* serial I/O controllers.** DESCRIPTION: Mainline code for the device driver********************************************************************************/// ToDo://// Done://// 1.2.9// Four box EX was barfing on >128k kmalloc, made structure smaller by// reducing output buffer size//// 1.2.8// Device file system support (MHW)//// 1.2.7 // Fixed// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules//// 1.2.6//Fixes DCD problems// DCD was not reported when CLOCAL was set on call to TIOCMGET////Enhancements:// TIOCMGET requests and waits for status return// No DSS interrupts enabled except for DCD when needed//// For internal use only////#define IP2DEBUG_INIT//#define IP2DEBUG_OPEN//#define IP2DEBUG_WRITE//#define IP2DEBUG_READ//#define IP2DEBUG_IOCTL//#define IP2DEBUG_IPL//#define IP2DEBUG_TRACE//#define DEBUG_FIFO/************//* Includes *//************/#include <linux/config.h>// Uncomment the following if you want it compiled with modversions#ifdef MODULE# if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)# define MODVERSIONS# endif# ifdef MODVERSIONS# include <linux/modversions.h># endif#endif#include <linux/version.h>#include <linux/ctype.h>#include <linux/string.h>#include <linux/fcntl.h>#include <linux/errno.h>#include <linux/module.h>#include <linux/signal.h>#include <linux/sched.h>#ifdef CONFIG_DEVFS_FS#include <linux/devfs_fs_kernel.h>#endif#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/mm.h>#include <linux/malloc.h>#include <linux/major.h>#include <linux/wait.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/termios.h>#include <linux/tty_driver.h>#include <linux/serial.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/cdk.h>#include <linux/comstats.h>#include <linux/delay.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/bitops.h>#ifndef KERNEL_VERSION#define KERNEL_VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)# include <linux/vmalloc.h># include <linux/init.h># include <asm/serial.h>#else# include <linux/bios32.h>#endif// These VERSION switches maybe inexact because I simply don't know// when the various features appeared in the 2.1.XX kernels.// They are good enough for 2.0 vs 2.2 and if you are fooling with// the 2.1.XX stuff then it would be trivial for you to fix.// Most of these macros were stolen from some other drivers// so blame them.#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,4)# include <asm/segment.h># 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# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,5)# include <asm/uaccess.h># define pcibios_strerror(status) \ printk( KERN_ERR "IP2: PCI error 0x%x \n", status );# endif#else /* 2.0.x and 2.1.x before 2.1.4 */# define proc_register_dynamic(a,b) proc_register(a,b) # define GET_USER(error,value,addr) \ do { \ error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \ if (error == 0) \ value = get_user(addr); \ } while (0)# define COPY_FROM_USER(error,dest,src,size) \ do { \ error = verify_area (VERIFY_READ, (void *) src, size); \ if (error == 0) \ memcpy_fromfs (dest, src, size); \ } while (0)# define PUT_USER(error,value,addr) \ do { \ error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \ if (error == 0) \ put_user (value, addr); \ } while (0)# define COPY_TO_USER(error,dest,src,size) \ do { \ error = verify_area (VERIFY_WRITE, (void *) dest, size); \ if (error == 0) \ memcpy_tofs (dest, src, size); \ } while (0)#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)#define __init#define __initfunc(a) a#define __initdata#define ioremap(a,b) vremap((a),(b))#define iounmap(a) vfree((a))#define SERIAL_TYPE_NORMAL 1#define SERIAL_TYPE_CALLOUT 2#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();}#define signal_pending(a) ((a)->signal & ~(a)->blocked)#define in_interrupt() intr_count#endif#include "./ip2/ip2types.h"#include "./ip2/ip2trace.h"#include "./ip2/ip2ioctl.h"#include "./ip2/ip2.h"#include "./ip2/i2ellis.h"#include "./ip2/i2lib.h"/***************** * /proc/ip2mem * *****************/#include <linux/proc_fs.h>static int ip2_read_procmem(char *, char **, off_t, int);int ip2_read_proc(char *, char **, off_t, int, int *, void * );/********************//* Type Definitions *//********************//*************//* Constants *//*************//* String constants to identify ourselves */static char *pcName = "Computone IntelliPort Plus multiport driver";static char *pcVersion = "1.2.9";/* String constants for port names */static char *pcDriver_name = "ip2";#ifdef CONFIG_DEVFS_FSstatic char *pcTty = "ttf/%d";static char *pcCallout = "cuf/%d";#elsestatic char *pcTty = "ttyF";static char *pcCallout = "cuf";#endifstatic char *pcIpl = "ip2ipl";/* Serial subtype definitions */#define SERIAL_TYPE_NORMAL 1#define SERIAL_TYPE_CALLOUT 2// cheezy kludge or genius - you decide?int ip2_loadmain(int *, int *, unsigned char *, int);static unsigned char *Fip_firmware;static int Fip_firmware_size;/***********************//* Function Prototypes *//***********************//* Global module entry functions */#ifdef MODULEint init_module(void);void cleanup_module(void);#endifint old_ip2_init(void);/* Private (static) functions */static int ip2_open(PTTY, struct file *);static void ip2_close(PTTY, struct file *);static int ip2_write(PTTY, int, const unsigned char *, int);static void ip2_putchar(PTTY, unsigned char);static void ip2_flush_chars(PTTY);static int ip2_write_room(PTTY);static int ip2_chars_in_buf(PTTY);static void ip2_flush_buffer(PTTY);static int ip2_ioctl(PTTY, struct file *, UINT, ULONG);static void ip2_set_termios(PTTY, struct termios *);static void ip2_set_line_discipline(PTTY);static void ip2_throttle(PTTY);static void ip2_unthrottle(PTTY);static void ip2_stop(PTTY);static void ip2_start(PTTY);static void ip2_hangup(PTTY);static void set_irq(int, int);static void ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs);static void ip2_poll(unsigned long arg);static inline void service_all_boards(void);static inline void do_input(i2ChanStrPtr pCh);static inline void do_status(i2ChanStrPtr pCh);static void ip2_wait_until_sent(PTTY,int);static void set_params (i2ChanStrPtr, struct termios *);static int set_modem_info(i2ChanStrPtr, unsigned int, unsigned int *);static int get_serial_info(i2ChanStrPtr, struct serial_struct *);static int set_serial_info(i2ChanStrPtr, struct serial_struct *);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)static int ip2_ipl_read(struct inode *, char *, size_t , loff_t *);#elsestatic ssize_t ip2_ipl_read(struct file *, char *, size_t, loff_t *) ;#endifstatic ssize_t ip2_ipl_write(struct file *, const char *, size_t, loff_t *);static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG);static int ip2_ipl_open(struct inode *, struct file *);void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...);static int DumpTraceBuffer(char *, int);static int DumpFifoBuffer( char *, int);static void ip2_init_board(int);static unsigned short find_eisa_board(int);/***************//* Static Data *//***************/static struct tty_driver ip2_tty_driver;static struct tty_driver ip2_callout_driver;static int ref_count;/* Here, then is a table of board pointers which the interrupt routine should * scan through to determine who it must service. */static unsigned short i2nBoards; // Number of boards herestatic i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS];static i2ChanStrPtr DevTable[IP2_MAX_PORTS];//DevTableMem just used to save addresses for kfreestatic void *DevTableMem[IP2_MAX_BOARDS];static struct tty_struct * TtyTable[IP2_MAX_PORTS];static struct termios * Termios[IP2_MAX_PORTS];static struct termios * TermiosLocked[IP2_MAX_PORTS];/* This is the driver descriptor for the ip2ipl device, which is used to * download the loadware to the boards. */static struct file_operations ip2_ipl = { owner: THIS_MODULE, read: ip2_ipl_read, write: ip2_ipl_write, ioctl: ip2_ipl_ioctl, open: ip2_ipl_open,}; static long irq_counter;static long bh_counter;// Use immediate queue to service interrupts//#define USE_IQI // PCI&2.2 needs work//#define USE_IQ // PCI&2.2 needs work/* The timer_list entry for our poll routine. If interrupt operation is not * selected, the board is serviced periodically to see if anything needs doing. */#define POLL_TIMEOUT (jiffies + 1)static struct timer_list PollTimer = { function: ip2_poll };static char TimerOn;#ifdef IP2DEBUG_TRACE/* Trace (debug) buffer data */#define TRACEMAX 1000static unsigned long tracebuf[TRACEMAX];static int tracestuff;static int tracestrip;static int tracewrap;#endif/**********//* Macros *//**********/#if defined(MODULE) && defined(IP2DEBUG_OPEN)#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \ kdevname(tty->device),(pCh->flags),ref_count, \ tty->count,/*GET_USE_COUNT(module)*/0,s)#else#define DBG_CNT(s)#endif#define MIN(a,b) ( ( (a) < (b) ) ? (a) : (b) )#define MAX(a,b) ( ( (a) > (b) ) ? (a) : (b) )/********//* Code *//********/#include "./ip2/i2ellis.c" /* Extremely low-level interface services */#include "./ip2/i2cmd.c" /* Standard loadware command definitions */#include "./ip2/i2lib.c" /* High level interface services *//* Configuration area for modprobe */#ifdef MODULE# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) MODULE_AUTHOR("Doug McNash"); MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");# endif /* LINUX_VERSION */#endif /* MODULE */static int poll_only;static int Eisa_irq;static int Eisa_slot;static int iindx;static char rirqs[IP2_MAX_BOARDS];static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};/******************************************************************************//* Initialisation Section *//******************************************************************************/int ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) { int i; /* process command line arguments to modprobe or insmod i.e. iop & irqp */ /* otherwise ip2config is initialized by what's in ip2/ip2.h */ /* command line trumps initialization in ip2.h */ /* first two args are null if builtin to kernel */ if ((irqp != NULL) || (iop != NULL)) { for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { if (irqp && irqp[i]) { ip2config.irq[i] = irqp[i]; } if (iop && iop[i]) { ip2config.addr[i] = iop[i]; } } } Fip_firmware = firmware; Fip_firmware_size = firmsize; return old_ip2_init();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -