patch-2.1.105 linux/drivers/scsi/g_NCR5380.c

Next file: linux/drivers/scsi/g_NCR5380.h
Previous file: linux/drivers/scsi/aha1542.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.104/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c
@@ -10,6 +10,12 @@
  * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin
  *    K.Lentin@cs.monash.edu.au
  *
+ * NCR53C400A extensions (c) 1996, Ingmar Baumgart
+ *    ingmar@gonzo.schwaben.de
+ *
+ * DTC3181E extensions (c) 1997, Ronald van Cuijlenborg
+ * ronald.van.cuijlenborg@tip.nl or nutty@dds.nl
+ *
  * ALPHA RELEASE 1. 
  *
  * For more information, please consult 
@@ -73,6 +79,12 @@
  * $Log: generic_NCR5380.c,v $
  */
 
+/* settings for DTC3181E card with only Mustek scanner attached */
+#define USLEEP
+#define USLEEP_POLL	1
+#define USLEEP_SLEEP	20
+#define USLEEP_WAITLONG	500
+
 #define AUTOPROBE_IRQ
 #define AUTOSENSE
 
@@ -105,6 +117,7 @@
 #include "sd.h"
 #include <linux/stat.h>
 #include <linux/init.h>
+#include<linux/ioport.h>
 
 struct proc_dir_entry proc_scsi_g_ncr5380 = {
     PROC_SCSI_GENERIC_NCR5380, 9, "g_NCR5380",
@@ -117,6 +130,8 @@
 static int ncr_addr=NCR_NOT_SET;
 static int ncr_5380=NCR_NOT_SET;
 static int ncr_53c400=NCR_NOT_SET;
+static int ncr_53c400a=NCR_NOT_SET;
+static int dtc_3181e=NCR_NOT_SET;
 
 static struct override {
 	NCR5380_implementation_fields;
@@ -156,6 +171,16 @@
 	    printk("generic_NCR53C400_setup : usage ncr53c400=" STRVAL(NCR5380_map_name) ",irq\n");
 	    return;
 	}
+    case BOARD_NCR53C400A:
+	if (ints[0] != 2) {
+	    printk("generic_NCR53C400A_setup : usage ncr53c400a=" STRVAL(NCR5380_map_name) ",irq\n");
+	    return;
+	}
+    case BOARD_DTC3181E:
+	if (ints[0] != 2) {
+	    printk("generic_DTC3181E_setup : usage dtc3181e=" STRVAL(NCR5380_map_name) ",irq\n");
+	    return;
+	}
     }
 
     if (commandline_current < NO_OVERRIDES) {
@@ -196,6 +221,32 @@
     internal_setup (BOARD_NCR53C400, str, ints);
 }
 
+/*
+ * Function : generic_NCR53C400A_setup (char *str, int *ints)
+ *
+ * Purpose : LILO command line initialization of the overrides array,
+ * 
+ * Inputs : str - unused, ints - array of integer parameters with ints[0] 
+ * 	equal to the number of ints.
+ */
+
+void generic_NCR53C400A_setup (char *str, int *ints) {
+    internal_setup (BOARD_NCR53C400A, str, ints);
+}
+
+/*
+ * Function : generic_DTC3181E_setup (char *str, int *ints)
+ *
+ * Purpose : LILO command line initialization of the overrides array,
+ * 
+ * Inputs : str - unused, ints - array of integer parameters with ints[0] 
+ * 	equal to the number of ints.
+ */
+
+void generic_DTC3181E_setup (char *str, int *ints) {
+    internal_setup (BOARD_DTC3181E, str, ints);
+}
+
 /* 
  * Function : int generic_NCR5380_detect(Scsi_Host_Template * tpnt)
  *
@@ -210,7 +261,12 @@
 
 __initfunc(int generic_NCR5380_detect(Scsi_Host_Template * tpnt)) {
     static int current_override = 0;
-    int count;
+    int count, i;
+    u_int *ports;
+    u_int ncr_53c400a_ports[] = {0x280, 0x290, 0x300, 0x310, 0x330,
+    		     		0x340, 0x348, 0x350, 0};
+    u_int dtc_3181e_ports[] = {0x220, 0x240, 0x280, 0x2a0, 0x2c0,
+    			     0x300, 0x320, 0x340, 0};
     int flags = 0;
     struct Scsi_Host *instance;
 
@@ -224,6 +280,10 @@
 	overrides[0].board=BOARD_NCR5380;
     else if (ncr_53c400 != NCR_NOT_SET)
 	overrides[0].board=BOARD_NCR53C400;
+    else if (ncr_53c400a != NCR_NOT_SET)
+        overrides[0].board=BOARD_NCR53C400A;
+    else if (dtc_3181e != NCR_NOT_SET)
+        overrides[0].board=BOARD_DTC3181E;
 
     tpnt->proc_dir = &proc_scsi_g_ncr5380;
 
@@ -231,6 +291,7 @@
 	if (!(overrides[current_override].NCR5380_map_name))
 	    continue;
 
+	ports = 0;
 	switch (overrides[current_override].board) {
 	case BOARD_NCR5380:
 	    flags = FLAG_NO_PSEUDO_DMA;
@@ -238,8 +299,56 @@
 	case BOARD_NCR53C400:
 	    flags = FLAG_NCR53C400;
 	    break;
+	case BOARD_NCR53C400A:
+	    flags = FLAG_NO_PSEUDO_DMA;
+            ports = ncr_53c400a_ports;
+	    break;
+	case BOARD_DTC3181E:
+	    flags = FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E;
+	    ports = dtc_3181e_ports;
+	    break;
 	}
 
+	if (ports) {
+	    /* wakeup sequence for the NCR53C400A and DTC3181E*/
+
+	    /* Disable the adapter and look for a free io port */
+	    outb(0x59, 0x779);
+	    outb(0xb9, 0x379);
+	    outb(0xc5, 0x379);
+	    outb(0xae, 0x379);
+	    outb(0xa6, 0x379);
+	    outb(0x00, 0x379);
+
+	    if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
+	        for(i=0; ports[i]; i++) {
+	            if (overrides[current_override].NCR5380_map_name == ports[i])
+	                break;
+	        }
+	    else
+	        for(i=0; ports[i]; i++) {
+	            if ((!check_region(ports[i], 16)) && (inb(ports[i]) == 0xff))
+	                break;
+		}
+	    if (ports[i]) {
+	        outb(0x59, 0x779);
+	        outb(0xb9, 0x379);
+	        outb(0xc5, 0x379);
+	        outb(0xae, 0x379);
+	        outb(0xa6, 0x379);
+	        outb(0x80 | i, 0x379);          /* set io port to be used */
+        	outb(0xc0, ports[i] + 9);
+	        if (inb(ports[i] + 9) != 0x80)
+	            continue;
+	        else
+	            overrides[current_override].NCR5380_map_name=ports[i];
+	    } else
+	        continue;
+	}
+
+	request_region(overrides[current_override].NCR5380_map_name,
+					NCR5380_region_size, "ncr5380");
+
 	instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
 	instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name;
 
@@ -289,6 +398,8 @@
 
     NCR5380_setup(instance);
 
+    release_region(instance->NCR5380_instance_name, NCR5380_region_size);
+
     if (instance->irq != IRQ_NONE)
 	free_irq(instance->irq, NULL);
 
@@ -742,5 +853,7 @@
 MODULE_PARM(ncr_addr, "i");
 MODULE_PARM(ncr_5380, "i");
 MODULE_PARM(ncr_53c400, "i");
+MODULE_PARM(ncr_53c400a, "i");
+MODULE_PARM(dtc_3181e, "i");
 
 #endif

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