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

📄 rio_linux.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
/* rio_linux.c -- Linux driver for the Specialix RIO series cards.  * * *   (C) 1999 R.E.Wolff@BitWizard.nl * * Specialix pays for the development and support of this driver. * Please DO contact support@specialix.co.uk if you require * support. But please read the documentation (rio.txt) first. * * * *      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. * * Revision history: * $Log: rio.c,v $ * Revision 1.1  1999/07/11 10:13:54  wolff * Initial revision * * */#include <linux/module.h>#include <linux/config.h> #include <linux/kdev_t.h>#include <asm/io.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/errno.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/mm.h>#include <linux/serial.h>#include <linux/fcntl.h>#include <linux/major.h>#include <linux/delay.h>#include <linux/pci.h>#include <linux/slab.h>#include <linux/miscdevice.h>#include <linux/init.h>#include <linux/generic_serial.h>#include <asm/uaccess.h>#if BITS_PER_LONG != 32#  error FIXME: this driver only works on 32-bit platforms#endif#include "linux_compat.h"#include "typdef.h"#include "pkt.h"#include "daemon.h"#include "rio.h"#include "riospace.h"#include "top.h"#include "cmdpkt.h"#include "map.h"#include "riotypes.h"#include "rup.h"#include "port.h"#include "riodrvr.h"#include "rioinfo.h"#include "func.h"#include "errors.h"#include "pci.h"#include "parmmap.h"#include "unixrup.h"#include "board.h"#include "host.h"#include "error.h"#include "phb.h"#include "link.h"#include "cmdblk.h"#include "route.h"#include "control.h"#include "cirrus.h"#include "rioioctl.h"#include "param.h"#include "list.h"#include "sam.h"#include "protsts.h"#include "rioboard.h"#include "rio_linux.h"/* I don't think that this driver can handle more than 512 ports onone machine.  Specialix specifies max 4 boards in one machine. I don'tknow why. If you want to try anyway you'll have to increase the numberof boards in rio.h.  You'll have to allocate more majors if you needmore than 512 ports.... */#ifndef RIO_NORMAL_MAJOR0/* This allows overriding on the compiler commandline, or in a "major.h"    include or something like that */#define RIO_NORMAL_MAJOR0  154#define RIO_NORMAL_MAJOR1  156#endif#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000#endif#ifndef RIO_WINDOW_LEN #define RIO_WINDOW_LEN 0x10000#endif/* Configurable options:    (Don't be too sure that it'll work if you toggle them) *//* Am I paranoid or not ? ;-) */#undef RIO_PARANOIA_CHECK/* 20 -> 2000 per second. The card should rate-limit interrupts at 1000   Hz, but it is user configurable. I don't recommend going above 1000   Hz. The interrupt ratelimit might trigger if the interrupt is   shared with a very active other device.    undef this if you want to disable the check....*/#define IRQ_RATE_LIMIT 200#if 0/* Not implemented *//*  * The following defines are mostly for testing purposes. But if you need * some nice reporting in your syslog, you can define them also. */#define RIO_REPORT_FIFO#define RIO_REPORT_OVERRUN#endif /* These constants are derived from SCO Source */static struct ConfRIOConf ={  /* locator */         "RIO Config here",  /* startuptime */     HZ*2,           /* how long to wait for card to run */  /* slowcook */        0,              /* TRUE -> always use line disc. */  /* intrpolltime */    1,              /* The frequency of OUR polls */  /* breakinterval */   25,             /* x10 mS XXX: units seem to be 1ms not 10! -- REW*/  /* timer */           10,             /* mS */  /* RtaLoadBase */     0x7000,  /* HostLoadBase */    0x7C00,  /* XpHz */            5,              /* number of Xprint hits per second */  /* XpCps */           120,            /* Xprint characters per second */  /* XpOn */            "\033d#",       /* start Xprint for a wyse 60 */  /* XpOff */           "\024",         /* end Xprint for a wyse 60 */  /* MaxXpCps */        2000,           /* highest Xprint speed */  /* MinXpCps */        10,             /* slowest Xprint speed */  /* SpinCmds */        1,              /* non-zero for mega fast boots */  /* First Addr */      0x0A0000,       /* First address to look at */  /* Last Addr */       0xFF0000,       /* Last address looked at */  /* BufferSize */      1024,           /* Bytes per port of buffering */  /* LowWater */        256,            /* how much data left before wakeup */  /* LineLength */      80,             /* how wide is the console? */  /* CmdTimeout */      HZ,             /* how long a close command may take */};/* Function prototypes */static void rio_disable_tx_interrupts (void * ptr); static void rio_enable_tx_interrupts (void * ptr); static void rio_disable_rx_interrupts (void * ptr); static void rio_enable_rx_interrupts (void * ptr); static int  rio_get_CD (void * ptr); static void rio_shutdown_port (void * ptr);static int  rio_set_real_termios (void  *ptr);static void rio_hungup (void  *ptr);static void rio_close (void  *ptr);static int rio_chars_in_buffer (void * ptr);static int rio_fw_ioctl (struct inode *inode, struct file *filp,		         unsigned int cmd, unsigned long arg);static int rio_init_drivers(void);static void my_hd (void *addr, int len);static struct tty_driver *rio_driver, *rio_driver2;/* The name "p" is a bit non-descript. But that's what the rio-lynxossources use all over the place. */struct rio_info *p;int rio_debug;/* You can have the driver poll your card.     - Set rio_poll to 1 to poll every timer tick (10ms on Intel).       This is used when the card cannot use an interrupt for some reason.*/static int rio_poll = 1;/* These are the only open spaces in my computer. Yours may have more   or less.... */static int rio_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000};#define NR_RIO_ADDRS (sizeof(rio_probe_addrs)/sizeof (int))/* Set the mask to all-ones. This alas, only supports 32 interrupts.    Some architectures may need more. -- Changed to LONG to   support up to 64 bits on 64bit architectures. -- REW 20/06/99 */long rio_irqmask = -1;MODULE_AUTHOR("Rogier Wolff <R.E.Wolff@bitwizard.nl>, Patrick van de Lageweg <patrick@bitwizard.nl>");MODULE_DESCRIPTION("RIO driver");MODULE_LICENSE("GPL");module_param(rio_poll, int, 0);module_param(rio_debug, int, 0644);module_param(rio_irqmask, long, 0);static struct real_driver rio_real_driver = {  rio_disable_tx_interrupts,  rio_enable_tx_interrupts,  rio_disable_rx_interrupts,  rio_enable_rx_interrupts,  rio_get_CD,  rio_shutdown_port,   rio_set_real_termios,   rio_chars_in_buffer,  rio_close,  rio_hungup,  NULL};/*  *  Firmware loader driver specific routines * */static struct file_operations rio_fw_fops = {	.owner		= THIS_MODULE,	.ioctl		= rio_fw_ioctl,};static struct miscdevice rio_fw_device = {	RIOCTL_MISC_MINOR, "rioctl", &rio_fw_fops};#ifdef RIO_PARANOIA_CHECK/* This doesn't work. Who's paranoid around here? Not me! */static inline int rio_paranoia_check(struct rio_port const * port,				    char *name, const char *routine){  static const char *badmagic =    KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";  static const char *badinfo =    KERN_ERR "rio: Warning: null rio port for device %s in %s\n";   if (!port) {    printk (badinfo, name, routine);    return 1;  }  if (port->magic != RIO_MAGIC) {    printk (badmagic, name, routine);    return 1;  }  return 0;}#else#define rio_paranoia_check(a,b,c) 0#endif#ifdef DEBUGstatic void my_hd (void *ad, int len){  int i, j, ch;  unsigned char *addr = ad;    for (i=0;i<len;i+=16) {    rio_dprintk (RIO_DEBUG_PARAM, "%08x ", (int) addr+i);    for (j=0;j<16;j++) {      rio_dprintk (RIO_DEBUG_PARAM, "%02x %s", addr[j+i], (j==7)?" ":"");    }    for (j=0;j<16;j++) {      ch = addr[j+i];      rio_dprintk (RIO_DEBUG_PARAM, "%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));    }    rio_dprintk (RIO_DEBUG_PARAM, "\n");  }}#else#define my_hd(ad,len) do{/* nothing*/ } while (0)#endif/* Delay a number of jiffies, allowing a signal to interrupt */ int RIODelay (struct Port *PortP, int njiffies){  func_enter ();  rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);    msleep_interruptible(jiffies_to_msecs(njiffies));  func_exit();  if (signal_pending(current))    return RIO_FAIL;  else    return !RIO_FAIL;}/* Delay a number of jiffies, disallowing a signal to interrupt */ int RIODelay_ni (struct Port *PortP, int njiffies){  func_enter ();  rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);    msleep(jiffies_to_msecs(njiffies));  func_exit();  return !RIO_FAIL;}int rio_minor(struct tty_struct *tty){	return tty->index + (tty->driver == rio_driver) ? 0 : 256;}int rio_ismodem(struct tty_struct *tty){	return 1;}void rio_udelay (int usecs){  udelay (usecs);}static int rio_set_real_termios (void *ptr){  int rv, modem;  struct tty_struct *tty;  func_enter();  tty = ((struct Port *)ptr)->gs.tty;  modem = rio_ismodem(tty);  rv = RIOParam( (struct Port *) ptr, CONFIG, modem, 1);  func_exit ();  return rv;}static void rio_reset_interrupt (struct Host *HostP){  func_enter();  switch( HostP->Type ) {  case RIO_AT:  case RIO_MCA:  case RIO_PCI:    WBYTE(HostP->ResetInt , 0xff);  }  func_exit();}static irqreturn_t rio_interrupt (int irq, void *ptr, struct pt_regs *regs){  struct Host *HostP;  func_enter ();  HostP = (struct Host*)ptr; /* &p->RIOHosts[(long)ptr]; */  rio_dprintk (RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n",                irq, HostP->Ivec);   /* AAargh! The order in which to do these things is essential and     not trivial.           - Rate limit goes before "recursive". Otherwise a series of       recursive calls will hang the machine in the interrupt routine.      - hardware twiddling goes before "recursive". Otherwise when we       poll the card, and a recursive interrupt happens, we won't       ack the card, so it might keep on interrupting us. (especially       level sensitive interrupt systems like PCI).     - Rate limit goes before hardware twiddling. Otherwise we won't       catch a card that has gone bonkers.     - The "initialized" test goes after the hardware twiddling. Otherwise       the card will stick us in the interrupt routine again.     - The initialized test goes before recursive.   */#ifdef IRQ_RATE_LIMIT  /* Aaargh! I'm ashamed. This costs more lines-of-code than the     actual interrupt routine!. (Well, used to when I wrote that comment) */  {    static int lastjif;    static int nintr=0;    if (lastjif == jiffies) {      if (++nintr > IRQ_RATE_LIMIT) {        free_irq (HostP->Ivec, ptr);        printk (KERN_ERR "rio: Too many interrupts. Turning off interrupt %d.\n",                 HostP->Ivec);      }    } else {      lastjif = jiffies;      nintr = 0;    }  }#endif  rio_dprintk (RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n");   if (HostP->Ivec == irq) {    /* Tell the card we've noticed the interrupt. */    rio_reset_interrupt (HostP);  }  if ((HostP->Flags & RUN_STATE) != RC_RUNNING)  	return IRQ_HANDLED;  if (test_and_set_bit (RIO_BOARD_INTR_LOCK, &HostP->locks)) {    printk (KERN_ERR "Recursive interrupt! (host %d/irq%d)\n",             (int) ptr, HostP->Ivec);    return IRQ_HANDLED;  }

⌨️ 快捷键说明

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