ip2main.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 1,945 行 · 第 1/5 页
C
1,945 行
/*** (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://// Fix the immediate DSS_NOW problem.// Work over the channel stats return logic in ip2_ipl_ioctl so they// make sense for all 256 possible channels and so the user space// utilities will compile and work properly.//// Done://// 1.2.14 /\/\|=mhw=|\/\/// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts.// Changed the definition of ip2trace to be more consistent with kernel style// Thanks to Andreas Dilger <adilger@turbolabs.com> for these updates//// 1.2.13 /\/\|=mhw=|\/\/// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform// to agreed devfs serial device naming convention.//// 1.2.12 /\/\|=mhw=|\/\/// Cleaned up some remove queue cut and paste errors//// 1.2.11 /\/\|=mhw=|\/\/// Clean up potential NULL pointer dereferences// Clean up devfs registration// Add kernel command line parsing for io and irq// Compile defaults for io and irq are now set in ip2.c not ip2.h!// Reworked poll_only hack for explicit parameter setting// You must now EXPLICITLY set poll_only = 1 or set all irqs to 0// Merged ip2_loadmain and old_ip2_init// Converted all instances of interruptible_sleep_on into queue calls// Most of these had no race conditions but better to clean up now//// 1.2.10 /\/\|=mhw=|\/\/// Fixed the bottom half interrupt handler and enabled USE_IQI// to split the interrupt handler into a formal top-half / bottom-half// Fixed timing window on high speed processors that queued messages to// the outbound mail fifo faster than the board could handle.//// 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>#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>#include <linux/devfs_fs_kernel.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/major.h>#include <linux/wait.h>#include <linux/device.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 <linux/bitops.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <linux/vmalloc.h>#include <linux/init.h>#include <asm/uaccess.h>#include "ip2types.h"#include "ip2trace.h"#include "ip2ioctl.h"#include "ip2.h"#include "i2ellis.h"#include "i2lib.h"/***************** * /proc/ip2mem * *****************/#include <linux/proc_fs.h>static int ip2_read_procmem(char *, char **, off_t, int);static 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.14";/* String constants for port names */static char *pcDriver_name = "ip2";static char *pcIpl = "ip2ipl";/* Serial subtype definitions */#define SERIAL_TYPE_NORMAL 1// 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 *//* Private (static) functions */static int ip2_open(PTTY, struct file *);static void ip2_close(PTTY, struct file *);static int ip2_write(PTTY, 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 int ip2_tiocmget(struct tty_struct *tty, struct file *file);static int ip2_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);static void set_irq(int, int);static void ip2_interrupt_bh(i2eBordStrPtr pB);static irqreturn_t 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 void do_input(void *p);static void do_status(void *p);static void ip2_wait_until_sent(PTTY,int);static void set_params (i2ChanStrPtr, struct termios *);static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *);static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *);static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG);static int ip2_ipl_open(struct inode *, struct file *);static int DumpTraceBuffer(char __user *, int);static int DumpFifoBuffer( char __user *, int);static void ip2_init_board(int);static unsigned short find_eisa_board(int);/***************//* Static Data *//***************/static struct tty_driver *ip2_tty_driver;/* 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];/* 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 unsigned long irq_counter = 0;static unsigned long bh_counter = 0;// Use immediate queue to service interrupts#define USE_IQI//#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 DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);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", \ tty->name,(pCh->flags),ip2_tty_driver->refcount, \ tty->count,/*GET_USE_COUNT(module)*/0,s)#else#define DBG_CNT(s)#endif/********//* Code *//********/#include "i2ellis.c" /* Extremely low-level interface services */#include "i2cmd.c" /* Standard loadware command definitions */#include "i2lib.c" /* High level interface services *//* Configuration area for modprobe */MODULE_AUTHOR("Doug McNash");MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");static int poll_only = 0;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};/* for sysfs class support */static struct class *ip2_class;// Some functions to keep track of what irq's we havestatic int __initis_valid_irq(int irq){ int *i = Valid_Irqs; while ((*i != 0) && (*i != irq)) { i++; } return (*i);}static void __initmark_requested_irq( char irq ){ rirqs[iindx++] = irq;}#ifdef MODULEstatic int __initclear_requested_irq( char irq ){ int i; for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { if (rirqs[i] == irq) { rirqs[i] = 0; return 1; } } return 0;}#endifstatic int __inithave_requested_irq( char irq ){ // array init to zeros so 0 irq will not be requested as a side effect int i; for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { if (rirqs[i] == irq) return 1; } return 0;}/******************************************************************************//* Function: init_module() *//* Parameters: None *//* Returns: Success (0) *//* *//* Description: *//* This is a required entry point for an installable module. It simply calls *//* the driver initialisation function and returns what it returns. *//******************************************************************************/#ifdef MODULEintinit_module(void){#ifdef IP2DEBUG_INIT printk (KERN_DEBUG "Loading module ...\n" );#endif return 0;}#endif /* MODULE *//******************************************************************************//* Function: cleanup_module() *//* Parameters: None *//* Returns: Nothing *//* *//* Description: *//* This is a required entry point for an installable module. It has to return *//* the device and the driver to a passive state. It should not be necessary *//* to reset the board fully, especially as the loadware is downloaded *//* externally rather than in the driver. We just want to disable the board *//* and clear the loadware to a reset state. To allow this there has to be a *//* way to detect whether the board has the loadware running at init time to *//* handle subsequent installations of the driver. All memory allocated by the *//* driver should be returned since it may be unloaded from memory. *//******************************************************************************/#ifdef MODULEvoidcleanup_module(void)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?