patch-2.2.17 linux/drivers/char/rio/rio_linux.c

Next file: linux/drivers/char/rio/rio_linux.h
Previous file: linux/drivers/char/rio/linux_compat.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.16/drivers/char/rio/rio_linux.c linux/drivers/char/rio/rio_linux.c
@@ -109,108 +109,6 @@
 more than 512 ports.... */
 
 
-/* ************************************************************** */
-/* * This section can be removed when 2.0 becomes outdated....  * */
-/* ************************************************************** */
-
-#if LINUX_VERSION_CODE < 0x020100    /* Less than 2.1.0 */
-#define TWO_ZERO
-#else
-#if LINUX_VERSION_CODE < 0x020209   /* less than 2.2.x */
-#warning "Please use a recent 2.2.x kernel. "
-#endif
-#endif
-
-
-#ifdef TWO_ZERO
-
-/* Here is the section that makes the 2.2 compatible driver source 
-   work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, 
-   and provide for compatibility stuff here if possible. */
-
-#include <linux/bios32.h>
-
-#define Get_user(a,b)                a = get_user(b)
-#define Put_user(a,b)                0,put_user(a,b)
-#define copy_to_user(a,b,c)          memcpy_tofs(a,b,c)
-
-static inline int copy_from_user(void *to,const void *from, int c) 
-{
-  memcpy_fromfs(to, from, c);
-  return 0;
-}
-
-#define pci_present                  pcibios_present
-#define pci_read_config_word         pcibios_read_config_word
-#define pci_read_config_dword        pcibios_read_config_dword
-
-static inline unsigned char get_irq (unsigned char bus, unsigned char fn)
-{
-  unsigned char t; 
-  pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t);
-  return t;
-}
-
-static inline void *ioremap(unsigned long base, long length)
-{
-  if (base < 0x100000) return (void *)base;
-  return vremap (base, length);
-}
-
-#define my_iounmap(x, b)             (((long)x<0x100000)?0:vfree ((void*)x))
-
-#define capable(x)                   suser()
-
-#define queue_task                   queue_task_irq_off
-#define tty_flip_buffer_push(tty)    queue_task(&tty->flip.tqueue, &tq_timer)
-#define signal_pending(current)      (current->signal & ~current->blocked)
-#define schedule_timeout(to)         do {current->timeout = jiffies + (to);schedule ();} while (0)
-#define time_after(t1,t2)            (((long)t1-t2) > 0)
-
-
-#define test_and_set_bit(nr, addr)   set_bit(nr, addr)
-#define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
-
-/* Not yet implemented on 2.0 */
-#define ASYNC_SPD_SHI  -1
-#define ASYNC_SPD_WARP -1
-
-
-/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
-   to the "name" field that does exist. As long as the assignments are
-   done in the right order, there is nothing to worry about. */
-#define driver_name           name 
-
-/* Should be in a header somewhere. They are in tty.h on 2.2 */
-#define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
-#define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
-
-/* The return type of a "close" routine. */
-#define INT                   void
-#define NO_ERROR              /* Nothing */
-
-#else
-
-/* The 2.2.x compatibility section. */
-#include <asm/uaccess.h>
-
-#define Get_user(a,b)         get_user(a,b)
-#define Put_user(a,b)         put_user(a,b)
-#define get_irq(pdev)         pdev->irq
-
-#define INT                   int
-#define NO_ERROR              0              
-
-#define my_iounmap(x,b)       (iounmap((char *)(b)))
-
-#endif
-
-/* ************************************************************** */
-/* *                End of compatibility section..              * */
-/* ************************************************************** */
-
-
-
 /* Why the hell am I defining these here? */
 #define RIO_TYPE_NORMAL 1
 #define RIO_TYPE_CALLOUT 2
@@ -353,6 +251,8 @@
 
 #ifndef TWO_ZERO
 #ifdef MODULE
+MODULE_AUTHOR("Rogier Wolff <R.E.Wolff@bitwizard.nl>, Patrick van de Lageweg <patrick@bitwizard.n>");
+MODULE_DESCRIPTION("RIO driver");
 MODULE_PARM(rio_poll, "i");
 MODULE_PARM(rio_debug, "i");
 MODULE_PARM(rio_irqmask, "i");
@@ -373,55 +273,15 @@
   NULL
 };
 
-
-/* 
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile... 
-*/
-#define DEBUG
-
-#ifdef DEBUG
-#define rio_dprintk(f, str...) if (rio_debug & f) printk (str)
-#else
-#define rio_dprintk(f, str...) /* nothing */
-#endif
-
-
-#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n")
-#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  " __FUNCTION__ "\n")
-
-#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \
-                                  "(port %d)\n", port->line)
-
-
-
-
 /* 
  *  Firmware loader driver specific routines
  *
  */
 
 static struct file_operations rio_fw_fops = {
-	NULL,	/*	lseek	*/
-	NULL,	/*	read	*/
-	NULL,	/*	write	*/
-	NULL,	/*	readdir	*/
-	NULL,	/*	select	*/
-	rio_fw_ioctl,
-	NULL,	/*	mmap	*/
-	rio_fw_open,
-#ifndef TWO_ZERO
-	NULL,	/*	flush	*/
-#endif
-	rio_fw_release,
-	NULL,	/*	fsync	*/
-	NULL,	/*	fasync	*/
-	NULL,	/*	check_media_change	*/
-	NULL,	/*	revalidate	*/
+        open:           rio_fw_open,
+        release:        rio_fw_release,
+	ioctl:		rio_fw_ioctl,
 };
 
 struct miscdevice rio_fw_device = {
@@ -446,11 +306,11 @@
     KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
  
   if (!port) {
-    printk(badinfo, kdevname(device), routine);
+    printk (badinfo, kdevname(device), routine);
     return 1;
   }
   if (port->magic != RIO_MAGIC) {
-    printk(badmagic, kdevname(device), routine);
+    printk (badmagic, kdevname(device), routine);
     return 1;
   }
 
@@ -468,15 +328,15 @@
   unsigned char *addr = ad;
   
   for (i=0;i<len;i+=16) {
-    printk ("%08x ", (int) addr+i);
+    rio_dprintk (RIO_DEBUG_PARAM, "%08x ", (int) addr+i);
     for (j=0;j<16;j++) {
-      printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+      rio_dprintk (RIO_DEBUG_PARAM, "%02x %s", addr[j+i], (j==7)?" ":"");
     }
     for (j=0;j<16;j++) {
       ch = addr[j+i];
-      printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+      rio_dprintk (RIO_DEBUG_PARAM, "%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
     }
-    printk ("\n");
+    rio_dprintk (RIO_DEBUG_PARAM, "\n");
   }
 }
 #else
@@ -539,26 +399,37 @@
 
 void rio_inc_mod_count (void)
 {
+#ifdef MODULE
   func_enter ();
+  rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_inc_mod_count\n");
   MOD_INC_USE_COUNT; 
   func_exit ();
+#endif
 }
 
 
 void rio_dec_mod_count (void)
 {
+#ifdef MODULE
   func_enter ();
+  rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_dec_mod_count\n");
   MOD_DEC_USE_COUNT; 
   func_exit ();
+#endif
 }
 
 
 static int rio_set_real_termios (void *ptr)
 {
-  int rv;
+  int rv, modem;
+  struct tty_struct *tty;
   func_enter();
 
-  rv = RIOParam( (struct Port *) ptr, CONFIG, 0, 1);
+  tty = ((struct Port *)ptr)->gs.tty;
+
+  modem = (MAJOR(tty->device) == RIO_NORMAL_MAJOR0) || (MAJOR(tty->device) == RIO_NORMAL_MAJOR1);
+
+  rv = RIOParam( (struct Port *) ptr, CONFIG, modem, 1);
 
   func_exit ();
 
@@ -568,21 +439,26 @@
 
 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 void rio_interrupt (int irq, void *ptr, struct pt_regs *regs)
 {
   struct Host *HostP;
+  func_enter ();
 
-  HostP = &p->RIOHosts[(long)ptr];
-  /*   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); 
 
@@ -627,7 +503,7 @@
     }
   }
 #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);
@@ -649,7 +525,7 @@
   clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks);
   rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", 
                irq, HostP->Ivec); 
-  /*  func_exit ();  */
+  func_exit ();
 }
 
 
@@ -657,7 +533,7 @@
 {
   func_enter ();
 
-  rio_interrupt (0, (void *)data, NULL);
+  rio_interrupt (0, &p->RIOHosts[data], NULL);
   p->RIOHosts[data].timer.expires = jiffies + rio_poll;
   add_timer (&p->RIOHosts[data].timer);
 
@@ -756,11 +632,11 @@
 #if 0
   port->gs.flags &= ~ GS_ACTIVE;
   if (!port->gs.tty) {
-    printk ("No tty.\n");
+    rio_dprintk (RIO_DBUG_TTY, "No tty.\n");
     return;
   }
   if (!port->gs.tty->termios) {
-    printk ("No termios.\n");
+    rio_dprintk (RIO_DEBUG_TTY, "No termios.\n");
     return;
   }
   if (port->gs.tty->termios->c_cflag & HUPCL) {
@@ -772,7 +648,6 @@
 }
 
 
-
 /* ********************************************************************** *
  *                Here are the routines that actually                     *
  *               interface with the rest of the system                    *
@@ -807,7 +682,7 @@
 static void rio_hungup (void *ptr)
 {
   func_enter ();
-  /* rio_dec_mod_count (); */
+  rio_dec_mod_count (); 
   func_exit ();
 }
 
@@ -818,9 +693,22 @@
  */
 static void rio_close (void *ptr)
 {
+  struct Port *PortP;
+
   func_enter ();
+
+  PortP = (struct Port *)ptr;
+
   riotclose (ptr);
+
+  if(PortP->gs.count) {
+    printk (KERN_ERR "WARNING port count:%d\n", PortP->gs.count);
+    PortP->gs.count = 0; 
+  }                
+
+
   rio_dec_mod_count ();
+
   func_exit ();
 }
 
@@ -1000,6 +888,8 @@
 
   if (rio_debug & RIO_DEBUG_PROBE)
     my_hd ((char *)&vpdp, 0x20);
+  
+  func_exit();
 
   return &vpdp;
 }
@@ -1099,7 +989,7 @@
   /* However, the RIO driver allows users to configure their first
      RTA as the ports numbered 504-511. We therefore need to allocate 
      the whole range. :-(   -- REW */
-
+  
 #define RI_SZ   sizeof(struct rio_info)
 #define HOST_SZ sizeof(struct Host)
 #define PORT_SZ sizeof(struct Port *)
@@ -1138,11 +1028,14 @@
     port->gs.close_delay = HZ/2;
     port->gs.closing_wait = 30 * HZ;
     port->gs.rd = &rio_real_driver;
+    port->portSem = SPIN_LOCK_UNLOCKED;
   }
 #else
   /* We could postpone initializing them to when they are configured. */
 #endif
 
+
+  
   if (rio_debug & RIO_DEBUG_INIT) {
     my_hd (&rio_real_driver, sizeof (rio_real_driver));
   }
@@ -1165,7 +1058,7 @@
   return -ENOMEM;
 }
 
-
+#ifdef MODULE
 static void rio_release_drivers(void)
 {
   func_enter();
@@ -1175,6 +1068,7 @@
   tty_unregister_driver (&rio_driver);
   func_exit();
 }
+#endif 
 
 #ifdef TWO_ZERO
 #define PDEV unsigned char pci_bus, unsigned pci_fun
@@ -1211,7 +1105,7 @@
   unsigned int t;
 
 #define CNTRL_REG_OFFSET        0x50
-#define CNTRL_REG_GOODVALUE     0x00260000
+#define CNTRL_REG_GOODVALUE     0x18260000
 
   pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
   hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
@@ -1292,7 +1186,6 @@
       pci_read_config_dword (pdev, 0x2c, &tint);
       tshort = (tint >> 16) & 0xffff;
       rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
-      /* rio_dprintk (RIO_DEBUG_PROBE, "pdev = %d/%d  (%x)\n", pdev, tint); */ 
       if (tshort != 0x0100) {
         rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", 
                     tshort);
@@ -1305,49 +1198,52 @@
       hp = &p->RIOHosts[p->RIONumHosts];
       hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
       hp->Ivec = get_irq (pdev);
-      if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0;
+      if (((1 << hp->Ivec) & rio_irqmask) == 0)
+              hp->Ivec = 0;
       hp->CardP	= (struct DpRam *)
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy; 
-      hp->Mode  = RIO_PCI_DEFAULT_MODE;
- 
+      hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
+      hp->HostLock = SPIN_LOCK_UNLOCKED;
+      rio_reset_interrupt (hp);
+      rio_start_card_running (hp);
+
       rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
                    (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
                    p->RIOHosts[p->RIONumHosts].Caddr);
       if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
                         p->RIOHosts[p->RIONumHosts].Caddr, 
                         RIO_PCI, 0 ) == RIO_SUCCESS) {
-        WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
-        p->RIOHosts[p->RIONumHosts].UniqueNum  =
-          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
-          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
-          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
-          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
-        rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
-                   p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-#if 1
-        fix_rio_pci (pdev);
-#endif
-        p->RIOLastPCISearch = RIO_SUCCESS;
-        p->RIONumHosts++;
-        found++;
+              rio_dprintk (RIO_DEBUG_INIT, "Done RIOBoardTest\n");
+              WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+              p->RIOHosts[p->RIONumHosts].UniqueNum  =
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
+              rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
+                           p->RIOHosts[p->RIONumHosts].UniqueNum);
+              
+              fix_rio_pci (pdev);
+              p->RIOLastPCISearch = RIO_SUCCESS;
+              p->RIONumHosts++;
+              found++;
       } else {
-        my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
-                    p->RIOHosts[p->RIONumHosts].Caddr);
+              my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
+                          p->RIOHosts[p->RIONumHosts].Caddr);
       }
-
+      
 #ifdef TWO_ZERO
     }  /* We have two variants with the opening brace, so to prevent */
 #else
     }  /* Emacs from getting confused we have two closing braces too. */
 #endif
     
-
     /* Then look for the older PCI card.... : */
 #ifndef TWO_ZERO
 
+
   /* These older PCI cards have problems (only byte-mode access is
      supported), which makes them a bit awkward to support. 
      They also have problems sharing interrupts. Be careful. 
@@ -1372,15 +1268,21 @@
       hp = &p->RIOHosts[p->RIONumHosts];
       hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
       hp->Ivec = get_irq (pdev);
-      if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0;
+      if (((1 << hp->Ivec) & rio_irqmask) == 0) 
+      	hp->Ivec = 0;
       hp->Ivec |= 0x8000; /* Mark as non-sharable */
       hp->CardP	= (struct DpRam *)
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy;
-      hp->Mode  = RIO_PCI_DEFAULT_MODE;
- 
-      rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
+      hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
+
+      rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
+      rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
+
+      rio_reset_interrupt (hp);
+      rio_start_card_running (hp);
+       rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
                    (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
                    p->RIOHosts[p->RIONumHosts].Caddr);
       if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
@@ -1423,11 +1325,15 @@
     hp->CardP = (struct DpRam *)
     hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
     hp->Type = RIO_AT;
-    hp->Copy = rio_pcicopy;
+    hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
+                             * -- YES! this is now a normal copy. Only the 
+                             * old PCI card uses the special PCI copy. 
+                             * Moreover, the ISA card will work with the 
+                             * special PCI copy anyway. -- REW */
     hp->Mode = 0;
 
     vpdp = get_VPD_PROM (hp);
-
+    rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n");
     okboard = 0;
     if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) ||
         (strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) ||
@@ -1458,11 +1364,21 @@
     if (hp->Ivec) {
       int mode = SA_SHIRQ;
       if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;}
-      if (request_irq (hp->Ivec, rio_interrupt, mode, "rio", (void *)i)) {
-        printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
-        hp->Ivec = 0;
+      rio_dprintk (RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp,hp->Ivec, hp->Mode);
+      retval = request_irq (hp->Ivec, rio_interrupt, mode, "rio", hp);
+      rio_dprintk (RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
+      if (retval) {
+              printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
+              hp->Ivec = 0;
       }
       rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
+      if (hp->Ivec != 0){
+              rio_dprintk (RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n"); 
+              hp->Mode |= RIO_PCI_INT_ENABLE;
+      } else
+              hp->Mode &= !RIO_PCI_INT_ENABLE;
+      rio_dprintk (RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
+      rio_start_card_running (hp);
     }
     /* Init the timer "always" to make sure that it can safely be 
        deleted when we unload... */
@@ -1479,7 +1395,7 @@
   }
 
   if (found) {
-    printk (KERN_INFO "rio: total of %d boards detected.\n", found);
+    rio_dprintk (RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
 
     if (misc_register(&rio_fw_device) < 0) {
       printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
@@ -1504,7 +1420,7 @@
   for (i=0,hp=p->RIOHosts;i<p->RIONumHosts;i++, hp++) {
     RIOHostReset (hp->Type, hp->CardP, hp->Slot);
     if (hp->Ivec) {
-      free_irq (hp->Ivec, (void *)i);
+      free_irq (hp->Ivec, hp);
       rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
     }
     /* It is safe/allowed to del_timer a non-active timer */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)