patch-2.2.0-pre2 linux/drivers/scsi/fdomain.c

Next file: linux/drivers/scsi/ibmmca.c
Previous file: linux/drivers/scsi/eata_pio_proc.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
@@ -1,10 +1,8 @@
 /* fdomain.c -- Future Domain TMC-16x0 SCSI driver
  * Created: Sun May  3 18:53:19 1992 by faith@cs.unc.edu
- * Revised: Wed Oct  2 11:10:55 1996 by faith@acm.org
+ * Revised: Mon Dec 28 21:59:02 1998 by faith@acm.org
  * Author: Rickard E. Faith, faith@cs.unc.edu
- * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
- *
- * Version 5.46 (23-04-1998)
+ * Copyright 1992-1996, 1998 Rickard E. Faith (faith@acm.org)
 
  * 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
@@ -32,13 +30,34 @@
     Future Domain TMC-1650, TMC-1660, TMC-1670, TMC-1680, TMC-1610M/MER/MEX
     Future Domain TMC-3260 (PCI)
     Quantum ISA-200S, ISA-250MG
-    Adaptec AHA-2920 (PCI)
+    Adaptec AHA-2920A (PCI) [BUT *NOT* AHA-2920C -- use aic7xxx instead]
     IBM ?
- LILO command-line options:
+ LILO/INSMOD command-line options:
     fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]
 
 
+    
+ NOTE:
+
+ The Adaptec AHA-2920C has an Adaptec AIC-7850 chip on it.
+ Use the aic7xxx driver for this board.
+       
+ The Adaptec AHA-2920A has a Future Domain chip on it, so this is the right
+ driver for that card.  Unfortunately, the boxes will probably just say
+ "2920", so you'll have to look on the card for a Future Domain logo, or a
+ letter after the 2920.
+
+ 
+ 
+ THANKS:
+
+ Thanks to Adaptec for providing PCI boards for testing.  This finally
+ enabled me to test the PCI detection and correct it for PCI boards that do
+ not have a BIOS at a standard ISA location.  For PCI boards, LILO/INSMOD
+ command-line options should no longer be needed.  --RF 18Nov98
+
 
+ 
  DESCRIPTION:
  
  This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680
@@ -70,7 +89,7 @@
  your board.  Please refer to the Seagate driver for more information and
  possible support.
 
-
+ 
  
  HISTORY:
 
@@ -108,7 +127,8 @@
  2.1.1       5.45         2 Oct 1996  Update ROM accesses for 2.1.x
  2.1.97      5.46	 23 Apr 1998  Rewritten PCI detection routines [mj]
  2.1.11x     5.47	  9 Aug 1998  Touched for 8 SCSI disk majors support
-
+             5.48        18 Nov 1998  BIOS no longer needed for PCI detection
+ 2.2.0       5.50        28 Dec 1998  Support insmod parameters
  
 
  REFERENCES USED:
@@ -207,6 +227,9 @@
  patches.
 
  New PCI detection code written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+
+ Insmod parameter code based on patches from Daniel Graham
+ <graham@balance.uoregon.edu>. 
  
  All of the alpha testers deserve much thanks.
 
@@ -282,7 +305,7 @@
     S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
   
-#define VERSION          "$Revision: 5.45 $"
+#define VERSION          "$Revision: 5.50 $"
 
 /* START OF USER DEFINABLE OPTIONS */
 
@@ -406,6 +429,15 @@
 extern void              do_fdomain_16x0_intr( int irq, void *dev_id,
 					    struct pt_regs * regs );
 
+#ifdef MODULE
+				/* Allow insmod parameters to be like LILO
+                                   parameters.  For example:
+				   insmod fdomain fdomain=0x140,11
+				*/
+static int               fdomain[]={ 0, 0, 0 };
+MODULE_PARM(fdomain, "2-3i");
+#endif
+
 static unsigned long addresses[] = {
    0xc8000,
    0xca000,
@@ -504,10 +536,10 @@
    if (!shpnt) return;		/* This won't ever happen */
 
    if (bios_major < 0 && bios_minor < 0) {
-      printk( "scsi%d <fdomain>: No BIOS; using scsi id %d\n",
+      printk( "scsi%d: <fdomain> No BIOS; using scsi id %d\n",
 	      shpnt->host_no, shpnt->this_id );
    } else {
-      printk( "scsi%d <fdomain>: BIOS version ", shpnt->host_no );
+      printk( "scsi%d: <fdomain> BIOS version ", shpnt->host_no );
 
       if (bios_major >= 0) printk( "%d.", bios_major );
       else                 printk( "?." );
@@ -523,7 +555,7 @@
 				   boards, we will have to modify banner
 				   for additional PCI cards, but for now if
 				   it's PCI it's a TMC-3260 - JTM */
-   printk( "scsi%d <fdomain>: %s chip at 0x%x irq ",
+   printk( "scsi%d: <fdomain> %s chip at 0x%x irq ",
 	   shpnt->host_no,
 	   chip == tmc1800 ? "TMC-1800"
 	   : (chip == tmc18c50 ? "TMC-18C50"
@@ -541,8 +573,9 @@
 void fdomain_setup( char *str, int *ints )
 {
    if (setup_called++ || ints[0] < 2 || ints[0] > 3) {
-      printk( "fdomain: usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" );
-      printk( "fdomain: bad LILO parameters?\n" );
+      printk( "scsi: <fdomain>"
+	      " Usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" );
+      printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
    }
 
    port_base       = ints[0] >= 1 ? ints[1] : 0;
@@ -591,8 +624,6 @@
       if (inb( port + MSB_ID_Code ) != 0x60) return 0;
       chip = tmc18c50;
 
-#if 1
-
 				/* Try to toggle 32-bit mode.  This only
 				   works on an 18c30 chip.  (User reports
 				   say this works, so we should switch to
@@ -606,17 +637,6 @@
 	    FIFO_Size = 0x800;	/* 2k FIFO */
 	 }
       }
-#else
-
-				/* That should have worked, but appears to
-				   have problems.  Let's assume it is an
-				   18c30 if the RAM is disabled. */
-
-      if (inb( port + Configuration2 ) & 0x02) {
-	 chip      = tmc18c30;
-	 FIFO_Size = 0x800;	/* 2k FIFO */
-      }
-#endif
 				/* If that failed, we are an 18c50. */
    }
 
@@ -656,7 +676,7 @@
    int options = inb( base + Configuration1 );
 
 #if DEBUG_DETECT
-   printk( " Options = %x\n", options );
+   printk( "scsi: <fdomain> Options = %x\n", options );
 #endif
    
 				/* Check for board with lowest bios_base --
@@ -673,10 +693,31 @@
 
 static int fdomain_isa_detect( int *irq, int *iobase )
 {
-   int i;
+   int i, j;
    int base;
    int flag = 0;
 
+#if DEBUG_DETECT
+   printk( "scsi: <fdomain> fdomain_isa_detect:" );
+#endif
+
+   for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
+#if DEBUG_DETECT
+      printk( " %lx(%lx),", addresses[i], bios_base );
+#endif
+      for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
+	 if (check_signature(addresses[i] + signatures[j].sig_offset,
+			     signatures[j].signature,
+			     signatures[j].sig_length )) {
+	    bios_major = signatures[j].major_bios_version;
+	    bios_minor = signatures[j].minor_bios_version;
+	    PCI_bus    = (signatures[j].flag == 1);
+	    Quantum    = (signatures[j].flag > 1) ? signatures[j].flag : 0;
+	    bios_base  = addresses[i];
+	 }
+      }
+   }
+   
    if (bios_major == 2) {
       /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
 	 Assuming the ROM is enabled (otherwise we wouldn't have been
@@ -746,6 +787,11 @@
       if ((flag = fdomain_is_valid_port( base ))) break;
    }
 
+#if DEBUG_DETECT
+   if (flag) printk( " SUCCESS\n" );
+   else      printk( " FAILURE\n" );
+#endif
+
    if (!flag) return 0;		/* iobase not found */
 
    *irq    = fdomain_get_irq( base );
@@ -771,18 +817,21 @@
    /* Tell how to print a list of the known PCI devices from bios32 and
       list vendor and device IDs being used if in debug mode.  */
       
-   printk( "\nINFO: use lspci -v to see list of PCI devices\n" );
-   printk( "\nTMC-3260 detect:"
-	   " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n",
+   printk( "scsi: <fdomain> INFO: use lspci -v to see list of PCI devices\n" );
+   printk( "scsi: <fdomain> TMC-3260 detect:"
+	   " Using Vendor ID: 0x%x and Device ID: 0x%x\n",
 	   PCI_VENDOR_ID_FD, 
 	   PCI_DEVICE_ID_FD_36C70 );
 #endif 
 
-   if ((pdev = pci_find_device(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL)
+   if ((pdev = pci_find_device(PCI_VENDOR_ID_FD,
+			       PCI_DEVICE_ID_FD_36C70,
+			       pdev)) == NULL)
      return 0;
        
 #if DEBUG_DETECT
-   printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n",
+   printk( "scsi: <fdomain> TMC-3260 detect:"
+	   " PCI bus %u, device %u, function %u\n",
 	   pdev->bus->number,
 	   PCI_SLOT(pdev->devfn),
 	   PCI_FUNC(pdev->devfn));
@@ -793,10 +842,6 @@
 
    pci_base = pdev->base_address[0];
    pci_irq = pdev->irq;
-#if DEBUG_DETECT
-      printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n", 
-	      pci_irq, pci_base );
-#endif
 
    /* Now we have the I/O base address and interrupt from the PCI
       configuration registers. */
@@ -805,18 +850,28 @@
    *iobase = (pci_base & PCI_BASE_ADDRESS_IO_MASK);
 
 #if DEBUG_DETECT
-   printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" ); 
-   printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
+   printk( "scsi: <fdomain> TMC-3260 detect:"
+	   " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base );
 #endif
 
-   if (!fdomain_is_valid_port( *iobase )) return 0;
+   if (!fdomain_is_valid_port( *iobase )) {
+      printk( "scsi: <fdomain>"
+	      " PCI card detected, but driver not loaded (invalid port)\n" );
+      return 0;
+   }
+
+				/* Fill in a few global variables.  Ugh. */
+   bios_major = bios_minor = -1;
+   PCI_bus    = 1;
+   Quantum    = 0;
+   bios_base  = 0;
+   
    return 1;
 }
 #endif
 
 int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
 {
-   int              i, j;
    int              retcode;
    struct Scsi_Host *shpnt;
 #if DO_DETECT
@@ -829,68 +884,44 @@
    unsigned char    buf[buflen];
 #endif
 
-#if DEBUG_DETECT
-   printk( "fdomain_16x0_detect()," );
-#endif
    tpnt->proc_dir = &proc_scsi_fdomain;
 
+#ifdef MODULE
+   if (fdomain[0] || fdomain[1] || fdomain[2]) {
+      port_base       = fdomain[0];
+      interrupt_level = fdomain[1];
+      this_id         = fdomain[2];
+      bios_major = bios_minor = -1;
+      ++setup_called;
+   }
+#endif
+   
    if (setup_called) {
 #if DEBUG_DETECT
-      printk( "no BIOS, using port_base = 0x%x, irq = %d\n",
+      printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
 	      port_base, interrupt_level );
 #endif
       if (!fdomain_is_valid_port( port_base )) {
-	 printk( "fdomain: cannot locate chip at port base 0x%x\n",
+	 printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
 		 port_base );
-	 printk( "fdomain: bad LILO parameters?\n" );
+	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
 	 return 0;
       }
    } else {
       int flag = 0;
-      
-      for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
-#if DEBUG_DETECT
-	 printk( " %lx(%lx),", addresses[i], bios_base );
-#endif
-	 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
-	    if (check_signature(addresses[i] + signatures[j].sig_offset,
-				signatures[j].signature,
-				signatures[j].sig_length )) {
-	       bios_major = signatures[j].major_bios_version;
-	       bios_minor = signatures[j].minor_bios_version;
-	       PCI_bus    = (signatures[j].flag == 1);
-	       Quantum    = (signatures[j].flag > 1) ? signatures[j].flag : 0;
-	       bios_base  = addresses[i];
-	    }
-	 }
-      }
-
-      if (!bios_base) {
-#if DEBUG_DETECT
-	 printk( " FAILED: NO BIOS\n" );
-#endif
-	 return 0;
-      }
 
-      if (!PCI_bus) {
-	 flag = fdomain_isa_detect( &interrupt_level, &port_base );
-      } else {
 #ifdef CONFIG_PCI
-	 flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
-#else
-	 printk(KERN_ERR "No PCI support in this kernel, giving up.\n");
-	 flag = 0;
+				/* Try PCI detection first */
+      flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
 #endif
-      }
-	 
       if (!flag) {
-#if DEBUG_DETECT
-	 printk( " FAILED: NO PORT\n" );
-#endif
-#ifdef CONFIG_PCI
-	 printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" );
-#endif
-	 return 0;		/* Cannot find valid set of ports */
+				/* Then try ISA bus detection */
+	 flag = fdomain_isa_detect( &interrupt_level, &port_base );
+
+	 if (!flag) {
+	    printk( "scsi: <fdomain> Detection failed (no card)\n" );
+	    return 0;
+	 }
       }
    }
 
@@ -911,13 +942,10 @@
    fdomain_16x0_reset( NULL, 0 );
 
    if (fdomain_test_loopback()) {
-#if DEBUG_DETECT
-      printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
-#endif
+      printk( "scsi: <fdomain> Detection failed"
+	      " (loopback test failed at port base 0x%x)\n", port_base );
       if (setup_called) {
-	 printk( "fdomain: loopback test failed at port base 0x%x\n",
-		 port_base );
-	 printk( "fdomain: bad LILO parameters?\n" );
+	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
       }
       return 0;
    }
@@ -946,7 +974,9 @@
 
 				/* Log IRQ with kernel */   
    if (!interrupt_level) {
-      panic( "fdomain: *NO* interrupt level selected!\n" );
+      printk( "scsi: <fdomain>"
+	      " Card Detected, but driver not loaded (no IRQ)\n" );
+      return 0;
    } else {
       /* Register the IRQ with the kernel */
 
@@ -955,18 +985,21 @@
 
       if (retcode < 0) {
 	 if (retcode == -EINVAL) {
-	    printk( "fdomain: IRQ %d is bad!\n", interrupt_level );
-	    printk( "         This shouldn't happen!\n" );
-	    printk( "         Send mail to faith@acm.org\n" );
+	    printk( "scsi: <fdomain> IRQ %d is bad!\n", interrupt_level );
+	    printk( "                This shouldn't happen!\n" );
+	    printk( "                Send mail to faith@acm.org\n" );
 	 } else if (retcode == -EBUSY) {
-	    printk( "fdomain: IRQ %d is already in use!\n", interrupt_level );
-	    printk( "         Please use another IRQ!\n" );
+	    printk( "scsi: <fdomain> IRQ %d is already in use!\n",
+		    interrupt_level );
+	    printk( "                Please use another IRQ!\n" );
 	 } else {
-	    printk( "fdomain: Error getting IRQ %d\n", interrupt_level );
-	    printk( "         This shouldn't happen!\n" );
-	    printk( "         Send mail to faith@acm.org\n" );
+	    printk( "scsi: <fdomain> Error getting IRQ %d\n",
+		    interrupt_level );
+	    printk( "                This shouldn't happen!\n" );
+	    printk( "                Send mail to faith@acm.org\n" );
 	 }
-	 panic( "fdomain: Driver requires interruptions\n" );
+	 printk( "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
+	 return 0;
       }
    }
 
@@ -987,7 +1020,7 @@
    SCinit.use_sg          = 0;
    SCinit.lun             = 0;
 
-   printk( "fdomain: detection routine scanning for devices:\n" );
+   printk( "scsi: <fdomain> detection routine scanning for devices:\n" );
    for (i = 0; i < 8; i++) {
       SCinit.target = i;
       if (i == tpnt->this_id)	/* Skip host adapter */
@@ -1031,10 +1064,10 @@
 
 const char *fdomain_16x0_info( struct Scsi_Host *ignore )
 {
-   static char buffer[80];
+   static char buffer[128];
    char        *pt;
    
-   strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" );
+   strcpy( buffer, "Future Domain 16-bit SCSI Driver Version" );
    if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */
       strcat( buffer, strchr( VERSION, ':' ) + 1 );
       pt = strrchr( buffer, '$') - 1;
@@ -1118,7 +1151,7 @@
    printk( "Arbitration failed, status = %x\n", status );
 #endif
 #if ERRORS_ONLY
-   printk( "fdomain: Arbitration failed, status = %x\n", status );
+   printk( "scsi: <fdomain> Arbitration failed, status = %x\n", status );
 #endif
    return 1;
 }
@@ -1158,7 +1191,7 @@
       if (!flag) /* Skip first failure for all chips. */
 	    ++flag;
       else
-	    printk( "fdomain: Selection failed\n" );
+	    printk( "scsi: <fdomain> Selection failed\n" );
    }
 #endif
    return 1;
@@ -1173,9 +1206,9 @@
       current_SC->result = error;
       if (current_SC->scsi_done)
 	    current_SC->scsi_done( current_SC );
-      else panic( "fdomain: current_SC->scsi_done() == NULL" );
+      else panic( "scsi: <fdomain> current_SC->scsi_done() == NULL" );
    } else {
-      panic( "fdomain: my_done() called outside of command\n" );
+      panic( "scsi: <fdomain> my_done() called outside of command\n" );
    }
 #if DEBUG_RACE
    in_interrupt_flag = 0;
@@ -1211,7 +1244,7 @@
    /* Abort calls my_done, so we do nothing here. */
    if (current_SC->SCp.phase & aborted) {
 #if DEBUG_ABORT
-      printk( "Interrupt after abort, ignoring\n" );
+      printk( "scsi: <fdomain> Interrupt after abort, ignoring\n" );
 #endif
       /*
       return; */
@@ -1311,7 +1344,7 @@
 	 if (current_SC->SCp.Status
 	     && current_SC->SCp.Status != 2
 	     && current_SC->SCp.Status != 8) {
-	    printk( "fdomain: target = %d, command = %x, status = %x\n",
+	    printk( "scsi: <fdomain> target = %d, command = %x, status = %x\n",
 		    current_SC->target,
 		    current_SC->cmnd[0],
 		    current_SC->SCp.Status );
@@ -1329,7 +1362,8 @@
 	 if (!current_SC->SCp.Message) ++done;
 #if DEBUG_MESSAGES || EVERY_ACCESS
 	 if (current_SC->SCp.Message) {
-	    printk( "fdomain: message = %x\n", current_SC->SCp.Message );
+	    printk( "scsi: <fdomain> message = %x\n",
+		    current_SC->SCp.Message );
 	 }
 #endif
 	 break;
@@ -1590,8 +1624,8 @@
 						|| code == 0x24
 						|| !code)))
 		  
-		  printk( "fdomain: REQUEST SENSE "
-			  "Key = %x, Code = %x, Qualifier = %x\n",
+		  printk( "scsi: <fdomain> REQUEST SENSE"
+			  " Key = %x, Code = %x, Qualifier = %x\n",
 			  key, code, qualifier );
 	 }
       }
@@ -1624,7 +1658,7 @@
 int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 {
    if (in_command) {
-      panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" );
+      panic( "scsi: <fdomain> fdomain_16x0_queue() NOT REENTRANT!\n" );
    }
 #if EVERY_ACCESS
    printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
@@ -1704,7 +1738,8 @@
    unsigned int isr;
 
    if (!SCpnt || !SCpnt->host) {
-      printk( "fdomain: cannot provide detailed information\n" );
+      printk( "scsi: <fdomain> Cannot provide detailed information\n" );
+      return;
    }
    
    printk( "%s\n", fdomain_16x0_info( SCpnt->host ) );
@@ -1770,7 +1805,7 @@
 {
    unsigned long flags;
 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
-   printk( "fdomain: abort " );
+   printk( "scsi: <fdomain> abort " );
 #endif
 
    save_flags( flags );
@@ -1808,7 +1843,7 @@
 #endif
 
 #if ERRORS_ONLY
-   if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" );
+   if (SCpnt) printk( "scsi: <fdomain> SCSI Bus Reset\n" );
 #endif
 
 #if DEBUG_RESET
@@ -1893,7 +1928,7 @@
     */
 
    if (MAJOR(dev) != SCSI_DISK0_MAJOR) {
-      printk("fdomain_16x0_biosparam: too many disks");
+      printk("scsi: <fdomain> fdomain_16x0_biosparam: too many disks");
       return 0;
    }
    drive = MINOR(dev) >> 4;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov