This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / sys / scsi / scsiconf.c
index 264dc1b..9e2dfef 100644 (file)
  * on the understanding that TFS is not responsible for the correct
  * functioning of this software in any circumstances.
  *
  * on the understanding that TFS is not responsible for the correct
  * functioning of this software in any circumstances.
  *
- */
-
-/*
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- */
-
-/*
- * $Log:
- * 23 May 93  Rodney W. Grimes        ADDED Pioneer DRM-600 cd changer
  *
  *
+ *      $Id: scsiconf.c,v 1.7 1993/11/18 05:02:58 rgrimes Exp $
  */
 
 #include <sys/types.h>
  */
 
 #include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <sys/malloc.h>
 #include "st.h"
 #include "sd.h"
 #include "ch.h"
 #include "cd.h"
 #include "st.h"
 #include "sd.h"
 #include "ch.h"
 #include "cd.h"
+#include "uk.h"
+#include "su.h"
+#ifndef        NSCBUS
+#define        NSCBUS  8
+#endif /* NSCBUS */
 
 
-#ifdef MACH
-#include <i386/machparam.h>
-#endif MACH
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 
-#if !defined(OSF) && !defined(__386BSD__)
+#ifdef TFS
 #include "bll.h"
 #include "cals.h"
 #include "kil.h"
 #include "bll.h"
 #include "cals.h"
 #include "kil.h"
-#else
+#include "scan.h"
+#else /* TFS */
 #define        NBLL 0
 #define        NCALS 0
 #define        NKIL 0
 #define        NBLL 0
 #define        NCALS 0
 #define        NKIL 0
-#endif /* !defined(OSF) && !defined(__386BSD__) */
+#define        NSCAN 0
+#endif /* TFS */
 
 #if NSD > 0
 
 #if NSD > 0
-extern sdattach();
-#endif NSD
+extern  sdattach();
+#endif /* NSD */
 #if NST > 0
 #if NST > 0
-extern stattach();
-#endif NST
+extern  stattach();
+#endif /* NST */
 #if NCH > 0
 #if NCH > 0
-extern chattach();
-#endif NCH
+extern  chattach();
+#endif /* NCH */
 #if NCD > 0
 #if NCD > 0
-extern cdattach();
-#endif NCD
+extern  cdattach();
+#endif /* NCD */
 #if NBLL > 0
 #if NBLL > 0
-extern bllattach();
-#endif NBLL
+extern  bllattach();
+#endif /* NBLL */
 #if NCALS > 0
 #if NCALS > 0
-extern calsattach();
-#endif NCALS
+extern  calsattach();
+#endif /* NCALS */
 #if NKIL > 0
 #if NKIL > 0
-extern kil_attach();
-#endif NKIL
-
-/***************************************************************\
-* The structure of pre-configured devices that might be turned *
-* off and therefore may not show up                            *
-\***************************************************************/
-struct predefined
-{
-       u_char  scsibus;
-       u_char  dev;
-       u_char  lu;
-       int     (*attach_rtn)();
-       char    *devname;
-       char    flags;
-}
-pd[] = 
+extern  kil_attach();
+#endif /* NKIL */
+#if NUK > 0
+extern  ukattach();
+#endif /* NUK */
+
+/*
+ * One of these is allocated and filled in for each scsi bus.
+ * it holds pointers to allow the scsi bus to get to the driver
+ * That is running each LUN on the bus
+ * it also has a template entry which is the prototype struct
+ * supplied by the adapter driver, this is used to initialise
+ * the others, before they have the rest of the fields filled in
+ */
+struct scsibus_data      *scbus_data[NSCBUS];
+
+/*
+ * The structure of pre-configured devices that might be turned
+ * off and therefore may not show up
+ */
+struct predefined {
+       u_char  scsibus;
+       u_char  dev;
+       u_char  lu;
+               errval(*attach_rtn) ();
+       char   *devname;
+       char    flags;
+} pd[] =
+
 {
 #ifdef EXAMPLE_PREDEFINE
 #if NSD > 0
 {
 #ifdef EXAMPLE_PREDEFINE
 #if NSD > 0
-       {0,0,0,sdattach,"sd",0},/* define a disk at scsibus=0 dev=0 lu=0 */
-#endif NSD
-#endif EXAMPLE_PREDEFINE
-       {0,9,9}                 /*illegal dummy end entry */
+       {
+               0, 0, 0, sdattach, "sd", 0
+       },                      /* define a disk at scsibus=0 dev=0 lu=0 */
+#endif /* NSD */
+#endif /* EXAMPLE_PREDEFINE */
+       {
+               0, 9, 9
+       } /*illegal dummy end entry */
 };
 
 };
 
+/*
+ * The structure of known drivers for autoconfiguration
+ */
+struct scsidevs {
+       u_int32 type;
+       boolean removable;
+       char   *manufacturer;
+       char   *model;
+       char   *version;
+               errval(*attach_rtn) ();
+       char   *devname;
+       char    flags;          /* 1 show my comparisons during boot(debug) */
+};
 
 
-/***************************************************************\
-* The structure of known drivers for autoconfiguration         *
-\***************************************************************/
-static struct scsidevs 
-{
-       int type;
-       int removable;
-       char    *manufacturer;
-       char    *model;
-       char    *version;
-       int     (*attach_rtn)();
-       char    *devname;
-       char    flags;          /* 1 show my comparisons during boot(debug) */
-}
 #define SC_SHOWME      0x01
 #define        SC_ONE_LU       0x00
 #define        SC_MORE_LUS     0x02
 #define SC_SHOWME      0x01
 #define        SC_ONE_LU       0x00
 #define        SC_MORE_LUS     0x02
-knowndevs[] = {
+#if    NUK > 0
+
+static struct scsidevs unknowndev = {
+       -1, 0, "standard", "any"
+           ,"any", ukattach, "uk", SC_MORE_LUS
+};
+#endif         /*NUK*/
+static struct scsidevs knowndevs[] =
+{
 #if NSD > 0
 #if NSD > 0
-       { T_DIRECT,T_FIXED,"standard","any"
-                       ,"any",sdattach,"sd",SC_ONE_LU },
-       { T_DIRECT,T_FIXED,"MAXTOR  ","XT-4170S        "
-                       ,"B5A ",sdattach,"mx1",SC_ONE_LU },
-#endif NSD
+       {
+               T_DIRECT, T_FIXED, "standard", "any"
+                   ,"any", sdattach, "sd", SC_ONE_LU
+       },
+       {
+               T_DIRECT, T_FIXED, "MAXTOR  ", "XT-4170S        "
+                   ,"B5A ", sdattach, "mx1", SC_ONE_LU
+       },
+#endif /* NSD */
 #if NST > 0
 #if NST > 0
-       { T_SEQUENTIAL,T_REMOV,"standard","any"
-                       ,"any",stattach,"st",SC_ONE_LU },
-#endif NST
+       {
+               T_SEQUENTIAL, T_REMOV, "standard", "any"
+                   ,"any", stattach, "st", SC_ONE_LU
+       },
+#endif /* NST */
 #if NCALS > 0
 #if NCALS > 0
-       { T_PROCESSOR,T_FIXED,"standard","any"
-                       ,"any",calsattach,"cals",SC_MORE_LUS },
-#endif NCALS
+       {
+               T_PROCESSOR, T_FIXED, "standard", "any"
+                   ,"any", calsattach, "cals", SC_MORE_LUS
+       },
+#endif /* NCALS */
 #if NCH > 0
 #if NCH > 0
-       { T_CHANGER,T_REMOV,"standard","any"
-                       ,"any",chattach,"ch",SC_ONE_LU },
-#endif NCH
+       {
+               T_CHANGER, T_REMOV, "standard", "any"
+                   ,"any", chattach, "ch", SC_ONE_LU
+       },
+#endif /* NCH */
 #if NCD > 0
 #if NCD > 0
-       { T_READONLY,T_REMOV,"SONY    ","CD-ROM CDU-8012 "
-                       ,"3.1a",cdattach,"cd",SC_ONE_LU },
-       { T_READONLY,T_REMOV,"PIONEER ","CD-ROM DRM-600  "
-                       ,"any",cdattach,"cd",SC_MORE_LUS },
-#endif NCD
+#ifndef UKTEST /* make cdroms unrecognised to test the uk driver */
+       {
+               T_READONLY, T_REMOV, "SONY    ", "CD-ROM CDU-8012 "
+                   ,"3.1a", cdattach, "cd", SC_ONE_LU
+       },
+       {
+               T_READONLY, T_REMOV, "PIONEER ", "CD-ROM DRM-600  "
+                   ,"any", cdattach, "cd", SC_MORE_LUS
+       },
+#endif
+#endif /* NCD */
 #if NBLL > 0
 #if NBLL > 0
-       { T_PROCESSOR,T_FIXED,"AEG     ","READER          "
-                       ,"V1.0",bllattach,"bll",SC_MORE_LUS },
-#endif NBLL
+       {
+               T_PROCESSOR, T_FIXED, "AEG     ", "READER          "
+                   ,"V1.0", bllattach, "bll", SC_MORE_LUS
+       },
+#endif /* NBLL */
 #if NKIL > 0
 #if NKIL > 0
-       { T_SCANNER,T_FIXED,"KODAK   ","IL Scanner 900  "
-                       ,"any",kil_attach,"kil",SC_ONE_LU },
-#endif NKIL
+       {
+               T_SCANNER, T_FIXED, "KODAK   ", "IL Scanner 900  "
+                   ,"any", kil_attach, "kil", SC_ONE_LU
+       },
+#endif /* NKIL */
 
 
-{0}
+       {
+               0
+       }
 };
 };
-/***************************************************************\
-* Declarations                                                 *
-\***************************************************************/
-struct predefined      *scsi_get_predef();
-struct scsidevs        *scsi_probedev();
-struct scsidevs        *selectdev();
-
-/* controls debug level within the scsi subsystem */
-/* see scsiconf.h for values                     */
-int    scsi_debug      =       0x0;
-int    scsibus         =       0x0; /* This is the Nth scsibus */
-
-/***************************************************************\
-* The routine called by the adapter boards to get all their    *
-* devices configured in.                                       *
-\***************************************************************/
-scsi_attachdevs( unit, scsi_addr, scsi_switch)
-int    unit,scsi_addr;
-struct scsi_switch     *scsi_switch;
+
+/*
+ * Declarations
+ */
+struct predefined *scsi_get_predef();
+struct scsidevs *scsi_probedev();
+struct scsidevs *selectdev();
+errval scsi_probe_bus __P((int bus, int targ, int lun));
+
+struct scsi_device probe_switch =
 {
 {
-       int     targ,lun;
-       struct  scsidevs        *bestmatch = (struct scsidevs *)0;
-       struct  predefined *predef;
-       int maybe_more;
-
-#ifdef SCSI_DELAY
-#if    SCSI_DELAY > 2
-       printf("waiting for scsi devices to settle\n");
-#else  SCSI_DELAY > 2
-#define        SCSI_DELAY 15
-#endif SCSI_DELAY > 2
-#else
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    "probe",
+    0,
+    { 0, 0 }
+};
+
+/*
+ * controls debug level within the scsi subsystem -
+ * see scsiconf.h for values
+ */
+int32 scsibus = 0x0;           /* This is the Nth scsibus we've seen */
+
+/*
+ * The routine called by the adapter boards to get all their
+ * devices configured in.
+ */
+void
+scsi_attachdevs(sc_link_proto)
+       struct scsi_link *sc_link_proto;
+{
+
+       if(scsibus >= NSCBUS) {
+               printf("too many scsi busses, reconfigure the kernel\n");
+               return;
+       }
+       sc_link_proto->scsibus = scsibus;
+       scbus_data[scsibus] = malloc(sizeof(struct scsibus_data), M_TEMP, M_NOWAIT);
+       if(!scbus_data[scsibus]) {
+               panic("scsi_attachdevs: malloc\n");
+       }
+       bzero(scbus_data[scsibus], sizeof(struct scsibus_data));
+       scbus_data[scsibus]->adapter_link = sc_link_proto;
+#if defined(SCSI_DELAY) && SCSI_DELAY > 2
+       printf("%s%d waiting for scsi devices to settle\n",
+           sc_link_proto->adapter->name, sc_link_proto->adapter_unit);
+#else  /* SCSI_DELAY > 2 */
+#undef SCSI_DELAY
 #define SCSI_DELAY 2
 #define SCSI_DELAY 2
-#endif SCSI_DELAY
-       spinwait(1000 * SCSI_DELAY);
-       targ = 0;
-       while(targ < 8)
-       {
-               maybe_more = 0; /* by default only check 1 lun */
-               if (targ == scsi_addr) 
-               {
-                       targ++;
+#endif /* SCSI_DELAY */
+       DELAY(1000000 * SCSI_DELAY);
+       scsibus++;
+       scsi_probe_bus(scsibus - 1,-1,-1);
+}
+
+/*
+ * Probe the requested scsi bus. It must be already set up.
+ * -1 requests all set up scsi busses.
+ * targ and lun optionally narrow the search if not -1
+ */
+errval
+scsi_probe_busses(int bus, int targ, int lun)
+{
+       if (bus == -1) {
+               for(bus = 0; bus < scsibus; bus++) {
+                       scsi_probe_bus(bus, targ, lun);
+               }
+               return 0;
+       } else {
+               return scsi_probe_bus(bus, targ, lun);
+       }
+}
+
+/*
+ * Probe the requested scsi bus. It must be already set up.
+ * targ and lun optionally narrow the search if not -1
+ */
+errval
+scsi_probe_bus(int bus, int targ, int lun)
+{
+       struct scsibus_data *scsi ;
+       int     maxtarg,mintarg,maxlun,minlun;
+       struct scsi_link *sc_link_proto;
+       u_int8  scsi_addr ;
+       struct scsidevs *bestmatch = NULL;
+       struct predefined *predef = NULL;
+       struct scsi_link *sc_link = NULL;
+       boolean maybe_more;
+
+       if ((bus < 0 ) || ( bus >= scsibus)) {
+               return ENXIO;
+       }
+       scsi = scbus_data[bus];
+       if(!scsi) return ENXIO;
+       sc_link_proto = scsi->adapter_link;
+       scsi_addr = sc_link_proto->adapter_targ;
+       if(targ == -1){
+               maxtarg = 7;
+               mintarg = 0;
+       } else {
+               if((targ < 0 ) || (targ > 7)) return EINVAL;
+               maxtarg = mintarg = targ;
+       }
+
+       if(lun == -1){
+               maxlun = 7;
+               minlun = 0;
+       } else {
+               if((lun < 0 ) || (lun > 7)) return EINVAL;
+               maxlun = minlun = lun;
+       }
+
+
+       for ( targ = mintarg;targ <= maxtarg; targ++) {
+               maybe_more = 0; /* by default only check 1 lun */
+               if (targ == scsi_addr) {
                        continue;
                }
                        continue;
                }
-               lun = 0;
-               while(lun < 8)
-               {
-                       predef = scsi_get_predef(scsibus
-                                               ,targ
-                                               ,lun
-                                               ,&maybe_more);
-                       bestmatch = scsi_probedev(unit
-                                               ,targ
-                                               ,lun 
-                                               ,scsi_switch
-                                               ,&maybe_more);
-                       if((bestmatch) && (predef)) /* both exist */
-                       {
-                               if(bestmatch->attach_rtn 
-                                   != predef->attach_rtn)
-                               {
-                                   printf("Clash in found/expected devices\n");
-                                   printf("will link in FOUND\n");
+               for ( lun = minlun; lun <= maxlun ;lun++) {
+                       /*
+                        * The spot appears to already have something
+                        * linked in, skip past it. Must be doing a 'reprobe'
+                        */
+                       if(scsi->sc_link[targ][lun])
+                       {/* don't do this one, but check other luns */
+                               maybe_more = 1;
+                               continue;
+                       }
+                       /*
+                        * If we presently don't have a link block
+                        * then allocate one to use while probing
+                        */
+                       if (!sc_link) {
+                               sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT);
+                               *sc_link = *sc_link_proto;      /* struct copy */
+                               sc_link->opennings = 1;
+                               sc_link->device = &probe_switch;
+                       }
+                       sc_link->target = targ;
+                       sc_link->lun = lun;
+                       predef = scsi_get_predef(sc_link, &maybe_more);
+                       bestmatch = scsi_probedev(sc_link, &maybe_more);
+                       if ((bestmatch) && (predef)) {  /* both exist */
+                               if (bestmatch->attach_rtn
+                                   != predef->attach_rtn) {
+                                       printf("Clash in found/expected devices\n");
+#if NUK > 0
+                                       if(bestmatch == &unknowndev) {
+                                               printf("will link in PREDEFINED\n");
+                                               (*(predef->attach_rtn)) (sc_link);
+                                       } else 
+#endif /*NUK*/
+                                       {
+                                               printf("will link in FOUND\n");
+                                               (*(bestmatch->attach_rtn)) (sc_link);
+                                       }
+                               } else {
+                                       (*(bestmatch->attach_rtn)) (sc_link);
                                }
                                }
-                               (*(bestmatch->attach_rtn))(unit,
-                                               targ,
-                                               lun,
-                                               scsi_switch);
                        }
                        }
-                       if((bestmatch) && (!predef)) /* just FOUND */
-                       {
-                               (*(bestmatch->attach_rtn))(unit,
-                                               targ,
-                                               lun,
-                                               scsi_switch);
+                       if ((bestmatch) && (!predef)) {         /* just FOUND */
+                               (*(bestmatch->attach_rtn)) (sc_link);
+                       }
+                       if ((!bestmatch) && (predef)) {         /* just predef */
+                               (*(predef->attach_rtn)) (sc_link);
                        }
                        }
-                       if((!bestmatch) && (predef)) /* just predef */
-                       {
-                               (*(predef->attach_rtn))(unit,
-                                               targ,
-                                               lun,
-                                               scsi_switch);
+                       if ((bestmatch) || (predef)) {  /* one exists */
+                               scsi->sc_link[targ][lun] = sc_link;
+                               sc_link = NULL;         /* it's been used */
                        }
                        }
-                       if(!(maybe_more)) /* nothing suggests we'll find more */
-                       {
+                       if (!(maybe_more)) {    /* nothing suggests we'll find more */
                                break;  /* nothing here, skip to next targ */
                        }
                                break;  /* nothing here, skip to next targ */
                        }
-                       /* otherwise something says we should look further*/
-                       lun++;
+                       /* otherwise something says we should look further */
                }
                }
-               targ++;
        }
        }
-#if NGENSCSI > 0
-       /***************************************************************\
-       * If available hook up the generic scsi driver, letting it      *
-       * know which target is US. (i.e. illegal or at least special)   *
-       \***************************************************************/
-       genscsi_attach(unit,scsi_addr,0,scsi_switch);
-#endif
-       scsibus++;      /* next time we are on the NEXT scsi bus */
+       if (sc_link) {
+               free(sc_link, M_TEMP);
+       }
+       return 0;
 }
 
 }
 
-/***********************************************\
-* given a target and lu, check if there is a   *
-* predefined device for that address           *
-\***********************************************/
-struct predefined      *scsi_get_predef(unit,target,lu,maybe_more)
-int    unit,target,lu,*maybe_more;
+/*
+ * given a target and lu, check if there is a predefined device for
+ * that address
+ */
+struct predefined *
+scsi_get_predef(sc_link, maybe_more)
+       struct scsi_link *sc_link;
+       boolean *maybe_more;
 {
 {
-       int upto,numents;
+       u_int8  unit = sc_link->scsibus;
+       u_int8  target = sc_link->target;
+       u_int8  lu = sc_link->lun;
+       struct scsi_adapter *scsi_adapter = sc_link->adapter;
+       u_int32 upto, numents;
 
 
-       numents = (sizeof(pd)/sizeof(struct predefined)) - 1;
-       
-       for(upto = 0;upto < numents;upto++)
-       {
-               if(pd[upto].scsibus != unit)
+       numents = (sizeof(pd) / sizeof(struct predefined)) - 1;
+
+       for (upto = 0; upto < numents; upto++) {
+               if (pd[upto].scsibus != unit)
                        continue;
                        continue;
-               if(pd[upto].dev != target)
+               if (pd[upto].dev != target)
                        continue;
                        continue;
-               if(pd[upto].lu != lu)
+               if (pd[upto].lu != lu)
                        continue;
                        continue;
-               
-               printf("  dev%d,lu%d: %s - PRECONFIGURED -\n"
-                       ,target
-                       ,lu
-                       ,pd[upto].devname);
+
+               printf("%s%d targ %d lun %d: <%s> - PRECONFIGURED -\n"
+                   ,scsi_adapter->name
+                   ,unit
+                   ,target
+                   ,lu
+                   ,pd[upto].devname);
                *maybe_more = pd[upto].flags & SC_MORE_LUS;
                *maybe_more = pd[upto].flags & SC_MORE_LUS;
-               return(&(pd[upto]));
+               return (&(pd[upto]));
        }
        }
-       return((struct predefined *)0);
+       return ((struct predefined *) 0);
 }
 
 }
 
-/***********************************************\
-* given a target and lu, ask the device what   *
-* it is, and find the correct driver table     *
-* entry.                                       *
-\***********************************************/
-struct scsidevs        *scsi_probedev(unit,target,lu,scsi_switch, maybe_more)
-
-struct scsi_switch *scsi_switch;
-int    unit,target,lu;
-int *maybe_more;
+/*
+ * given a target and lu, ask the device what
+ * it is, and find the correct driver table
+ * entry.
+ */
+struct scsidevs *
+scsi_probedev(sc_link, maybe_more)
+       boolean *maybe_more;
+       struct scsi_link *sc_link;
 {
 {
-       struct  scsidevs        *bestmatch = (struct scsidevs *)0;
-       char    *dtype=(char *)0,*desc;
-       char    *qtype;
-       static  struct scsi_inquiry_data        inqbuf; 
-       int     len,qualifier,type,remov;
-       char    manu[32];
-       char    model[32];
-       char    version[32];
-
-
-       bzero(&inqbuf,sizeof(inqbuf));
-       /***********************************************\
-       * Ask the device what it is                     *
-       \***********************************************/
-#ifdef DEBUG
-       if((target == 0) && (lu == 0))
-               scsi_debug = 0xfff;
+       u_int8  unit = sc_link->adapter_unit;
+       u_int8  target = sc_link->target;
+       u_int8  lu = sc_link->lun;
+       struct scsi_adapter *scsi_adapter = sc_link->adapter;
+       struct scsidevs *bestmatch = (struct scsidevs *) 0;
+       char   *dtype = (char *) 0, *desc;
+       char   *qtype;
+       static struct scsi_inquiry_data inqbuf;
+       u_int32 len, qualifier, type;
+       boolean remov;
+       char    manu[32];
+       char    model[32];
+       char    version[32];
+
+       bzero(&inqbuf, sizeof(inqbuf));
+       /*
+        * Ask the device what it is
+        */
+#ifdef SCSIDEBUG
+       if ((target == DEBUGTARG) && (lu == DEBUGLUN))
+               sc_link->flags |= (DEBUGLEVEL);
        else
        else
-               scsi_debug = 0;
-#endif DEBUG
-       if(scsi_ready(  unit,
-                       target,
-                       lu,
-                       scsi_switch,
-                       SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
-       {
-               return(struct scsidevs *)0;
-       }
-       if(scsi_inquire(unit,
-                       target,
-                       lu,
-                       scsi_switch,
-                       &inqbuf,
-                       SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
-       {
-               return(struct scsidevs *)0;
-       }
+               sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2 | SDEV_DB3 | SDEV_DB4);
+#endif /* SCSIDEBUG */
+       /* catch unit attn */
+       scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
+#ifdef DOUBTFULL
+       switch (scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
+       case 0:         /* said it WAS ready */
+       case EBUSY:             /* replied 'NOT READY' but WAS present, continue */
+       case ENXIO:
+               break;
+       case EIO:               /* device timed out */
+       case EINVAL:            /* Lun not supported */
+       default:
+               return (struct scsidevs *) 0;
 
 
-       /***********************************************\
-       * note what BASIC type of device it is          *
-       \***********************************************/
-       if(scsi_debug & SHOWINQUIRY)
-       {
-               desc=(char *)&inqbuf;
-               printf("inq: %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
-               desc[0], desc[1], desc[2], desc[3],
-               desc[4], desc[5], desc[6], desc[7],
-               desc[8], desc[9], desc[10], desc[11],
-               desc[12]);
+       }
+#endif /*DOUBTFULL*/
+#ifdef SCSI_2_DEF
+       /* some devices need to be told to go to SCSI2 */
+       /* However some just explode if you tell them this.. leave it out */
+       scsi_change_def(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
+#endif /*SCSI_2_DEF */
+
+       /* Now go ask the device all about itself */
+       if (scsi_inquire(sc_link, &inqbuf, SCSI_NOSLEEP | SCSI_NOMASK) != 0) {
+               return (struct scsidevs *) 0;
        }
 
        }
 
-       type = inqbuf.device_type;
-       qualifier = inqbuf.device_qualifier;
-       remov = inqbuf.removable;
-
-       /* Check for a non-existent unit.  If the device is returning
-        * this much, then we must set the flag that has
-        * the searcher keep looking on other luns.
+       /*
+        * note what BASIC type of device it is
         */
         */
-       if (qualifier == 3 && type == T_NODEVICE)
-       {
-               *maybe_more = 1;
-               return (struct scsidevs *)0;
-       }
+       type = inqbuf.device & SID_TYPE;
+       qualifier = inqbuf.device & SID_QUAL;
+       remov = inqbuf.dev_qual2 & SID_REMOVABLE;
 
 
-       /* Any device qualifier that has
-        * the top bit set (qualifier&4 != 0) is vendor specific and
-        * won't match in this switch.
+       /*
+        * Any device qualifier that has the top bit set (qualifier&4 != 0)
+        * is vendor specific and won't match in this switch.
         */
 
         */
 
-       switch(qualifier)
-       {
-               case 0:
-               qtype="";
-               break;
-               case 1:
-               qtype=", Unit not Connected!";
+       switch ((int)qualifier) {
+       case SID_QUAL_LU_OK:
+               qtype = "";
                break;
                break;
-               case 2:
-               qtype=", Reserved Peripheral Qualifier!";
+
+       case SID_QUAL_LU_OFFLINE:
+               qtype = ", Unit not Connected!";
                break;
                break;
-               case 3:
-               qtype=", The Target can't support this Unit!";
+
+       case SID_QUAL_RSVD:
+               qtype = ", Reserved Peripheral Qualifier!";
+               *maybe_more = 1;
+               return (struct scsidevs *) 0;
                break;
 
                break;
 
-               default:
-               dtype="vendor specific";
-               qtype="";
+       case SID_QUAL_BAD_LU:
+               /*
+                * Check for a non-existent unit.  If the device is returning
+                * this much, then we must set the flag that has
+                * the searchers keep looking on other luns.
+                */
+               qtype = ", The Target can't support this Unit!";
+               *maybe_more = 1;
+               return (struct scsidevs *) 0;
+
+       default:
+               dtype = "vendor specific";
+               qtype = "";
                *maybe_more = 1;
                break;
        }
                *maybe_more = 1;
                break;
        }
-
-       if (dtype == 0)
-               switch(type)
-               {
-                       case T_DIRECT:
-                               dtype="direct";
-                               break;
-                       case T_SEQUENTIAL:
-                               dtype="sequential";
-                               break;
-                       case T_PRINTER:
-                               dtype="printer";
-                               break;
-                       case T_PROCESSOR:
-                               dtype="processor";
-                               break;
-                       case T_READONLY:
-                               dtype="readonly";
-                               break;
-                       case T_WORM:
-                               dtype="worm";
-                               break;
-                       case T_SCANNER:
-                               dtype="scanner";
-                               break;
-                       case T_OPTICAL:
-                               dtype="optical";
-                               break;
-                       case T_CHANGER:
-                               dtype="changer";
-                               break;
-                       case T_COMM:
-                               dtype="communication";
-                               break;
-                       default:
-                               dtype="unknown";
-                               break;
+       if (dtype == 0) {
+               switch ((int)type) {
+               case T_DIRECT:
+                       dtype = "direct";
+                       break;
+               case T_SEQUENTIAL:
+                       dtype = "sequential";
+                       break;
+               case T_PRINTER:
+                       dtype = "printer";
+                       break;
+               case T_PROCESSOR:
+                       dtype = "processor";
+                       break;
+               case T_READONLY:
+                       dtype = "readonly";
+                       break;
+               case T_WORM:
+                       dtype = "worm";
+                       break;
+               case T_SCANNER:
+                       dtype = "scanner";
+                       break;
+               case T_OPTICAL:
+                       dtype = "optical";
+                       break;
+               case T_CHANGER:
+                       dtype = "changer";
+                       break;
+               case T_COMM:
+                       dtype = "communication";
+                       break;
+               case T_NODEVICE:
+                       *maybe_more = 1;
+                       return (struct scsidevs *) 0;
+               default:
+                       dtype = "unknown";
+                       break;
                }
                }
-
-       /***********************************************\
-       * Then if it's advanced enough, more detailed   *
-       * information                                   *
-       \***********************************************/
-       if(inqbuf.ansii_version > 0) 
-       {
-               if ((len = inqbuf.additional_length 
-                               + ( (char *)inqbuf.unused
-                                 - (char *)&inqbuf))
-                       > (sizeof(struct scsi_inquiry_data) - 1))
-                       len = sizeof(struct scsi_inquiry_data) - 1;
-               desc=inqbuf.vendor;
-               desc[len-(desc - (char *)&inqbuf)] = 0;
-               strncpy(manu,inqbuf.vendor,8);manu[8]=0;
-               strncpy(model,inqbuf.product,16);model[16]=0;
-               strncpy(version,inqbuf.revision,4);version[4]=0;
        }
        }
-       else
-       /***********************************************\
-       * If not advanced enough, use default values    *
-       \***********************************************/
+       /*
+        * Then if it's advanced enough, more detailed
+        * information
+        */
+       if ((inqbuf.version & SID_ANSII) > 0) {
+               if ((len = inqbuf.additional_length
+                       + ((char *) inqbuf.unused
+                           - (char *) &inqbuf))
+                   > (sizeof(struct scsi_inquiry_data) - 1))
+                               len = sizeof(struct scsi_inquiry_data) - 1;
+               desc = inqbuf.vendor;
+               desc[len - (desc - (char *) &inqbuf)] = 0;
+               strncpy(manu, inqbuf.vendor, 8);
+               manu[8] = 0;
+               strncpy(model, inqbuf.product, 16);
+               model[16] = 0;
+               strncpy(version, inqbuf.revision, 4);
+               version[4] = 0;
+       } else
+               /*
+                * If not advanced enough, use default values
+                */
        {
        {
-               desc="early protocol device";
-               strncpy(manu,"unknown",8);
-               strncpy(model,"unknown",16);
-               strncpy(version,"????",4);
+               desc = "early protocol device";
+               strncpy(manu, "unknown", 8);
+               strncpy(model, "unknown", 16);
+               strncpy(version, "????", 4);
        }
        }
-       printf("  dev%d,lu%d: type %d:%d(%s%s),%s '%s%s%s' scsi%d\n"
-               ,target
-               ,lu
-               ,qualifier,type
-               ,dtype,qtype
-               ,remov?"removable":"fixed"
-               ,manu
-               ,model
-               ,version
-               ,inqbuf.ansii_version
-       );
-       /***********************************************\
-       * Try make as good a match as possible with     *
-       * available sub drivers                         *
-       \***********************************************/
-       bestmatch = (selectdev(unit,target,lu,&scsi_switch,
-               qualifier,type,remov,manu,model,version));
-       if((bestmatch) && (bestmatch->flags & SC_MORE_LUS))
-       {
+       printf("%s%d targ %d lun %d: type %d(%s) %s SCSI%d\n"
+           ,scsi_adapter->name
+           ,unit
+           ,target
+           ,lu
+           ,type
+           ,dtype
+           ,remov ? "removable" : "fixed"
+           ,inqbuf.version & SID_ANSII
+           );
+       printf("%s%d targ %d lun %d: <%s%s%s>\n"
+           ,scsi_adapter->name
+           ,unit
+           ,target
+           ,lu
+           ,manu
+           ,model
+           ,version
+           );
+       if (qtype[0]) {
+               printf("%s%d targ %d lun %d: qualifier %d(%s)\n"
+                   ,scsi_adapter->name
+                   ,unit
+                   ,target
+                   ,lu
+                   ,qualifier
+                   ,qtype
+                   );
+       }
+       /*
+        * Try make as good a match as possible with
+        * available sub drivers       
+        */
+       bestmatch = (selectdev(
+               qualifier, type, remov ? T_REMOV : T_FIXED, manu, model, version));
+       if ((bestmatch) && (bestmatch->flags & SC_MORE_LUS)) {
                *maybe_more = 1;
        }
                *maybe_more = 1;
        }
-       return(bestmatch);
+       return (bestmatch);
 }
 }
-
-/***********************************************\
-* Try make as good a match as possible with    *
-* available sub drivers                                *
-\***********************************************/
-struct scsidevs        
-*selectdev(unit,target,lu,dvr_switch,qualifier,type,remov,manu,model,rev)
-int    unit,target,lu;
-struct scsi_switch *dvr_switch;
-int    qualifier,type,remov;
-char   *manu,*model,*rev;
+/*
+ * Try make as good a match as possible with
+ * available sub drivers       
+ */
+struct scsidevs *
+selectdev(qualifier, type, remov, manu, model, rev)
+       u_int32 qualifier, type;
+       boolean remov;
+       char   *manu, *model, *rev;
 {
 {
-       int     numents = (sizeof(knowndevs)/sizeof(struct scsidevs)) - 1;
-       int     count = 0;
-       int                     bestmatches = 0;
-       struct  scsidevs        *bestmatch = (struct scsidevs *)0;
-       struct  scsidevs        *thisentry = knowndevs;
+       u_int32 numents = (sizeof(knowndevs) / sizeof(struct scsidevs)) - 1;
+       u_int32 count = 0;
+       u_int32 bestmatches = 0;
+       struct scsidevs *bestmatch = (struct scsidevs *) 0;
+       struct scsidevs *thisentry = knowndevs;
 
 
-       type |= (qualifier << 5);
+       type |= qualifier;      /* why? */
 
        thisentry--;
 
        thisentry--;
-       while( count++ < numents)
-       {
+       while (count++ < numents) {
                thisentry++;
                thisentry++;
-               if(type != thisentry->type)
-               {
+               if (type != thisentry->type) {
                        continue;
                }
                        continue;
                }
-               if(bestmatches < 1)
-               {
+               if (bestmatches < 1) {
                        bestmatches = 1;
                        bestmatch = thisentry;
                }
                        bestmatches = 1;
                        bestmatch = thisentry;
                }
-               if(remov != thisentry->removable)
-               {
+               if (remov != thisentry->removable) {
                        continue;
                }
                        continue;
                }
-               if(bestmatches < 2)
-               {
+               if (bestmatches < 2) {
                        bestmatches = 2;
                        bestmatch = thisentry;
                }
                        bestmatches = 2;
                        bestmatch = thisentry;
                }
-               if(thisentry->flags & SC_SHOWME)
-                       printf("\n%s-\n%s-",thisentry->manufacturer, manu);
-               if(strcmp(thisentry->manufacturer, manu))
-               {
+               if (thisentry->flags & SC_SHOWME)
+                       printf("\n%s-\n%s-", thisentry->manufacturer, manu);
+               if (strcmp(thisentry->manufacturer, manu)) {
                        continue;
                }
                        continue;
                }
-               if(bestmatches < 3)
-               {
+               if (bestmatches < 3) {
                        bestmatches = 3;
                        bestmatch = thisentry;
                }
                        bestmatches = 3;
                        bestmatch = thisentry;
                }
-               if(thisentry->flags & SC_SHOWME)
-                       printf("\n%s-\n%s-",thisentry->model, model);
-               if(strcmp(thisentry->model, model))
-               {
+               if (thisentry->flags & SC_SHOWME)
+                       printf("\n%s-\n%s-", thisentry->model, model);
+               if (strcmp(thisentry->model, model)) {
                        continue;
                }
                        continue;
                }
-               if(bestmatches < 4)
-               {
+               if (bestmatches < 4) {
                        bestmatches = 4;
                        bestmatch = thisentry;
                }
                        bestmatches = 4;
                        bestmatch = thisentry;
                }
-               if(thisentry->flags & SC_SHOWME)
-                       printf("\n%s-\n%s-",thisentry->version, rev);
-               if(strcmp(thisentry->version, rev))
-               {
+               if (thisentry->flags & SC_SHOWME)
+                       printf("\n%s-\n%s-", thisentry->version, rev);
+               if (strcmp(thisentry->version, rev)) {
                        continue;
                }
                        continue;
                }
-               if(bestmatches < 5)
-               {
+               if (bestmatches < 5) {
                        bestmatches = 5;
                        bestmatch = thisentry;
                        break;
                }
        }
                        bestmatches = 5;
                        bestmatch = thisentry;
                        break;
                }
        }
-
-       if (bestmatch == (struct scsidevs *)0)
-               printf("        No explicit device driver match for \"%s %s\".\n",
-               manu, model);
-
-       return(bestmatch);
-}
-
-static int recurse = 0;
-/***********************************************\
-* Do a scsi operation asking a device if it is *
-* ready. Use the scsi_cmd routine in the switch *
-* table.                                       *
-\***********************************************/
-scsi_ready(unit,target,lu,scsi_switch, flags)
-struct scsi_switch *scsi_switch;
-{
-       struct  scsi_test_unit_ready scsi_cmd;
-       struct  scsi_xfer scsi_xfer;
-       volatile int rval;
-       int     key;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       bzero(&scsi_xfer, sizeof(scsi_xfer));
-       scsi_cmd.op_code = TEST_UNIT_READY;
-
-       scsi_xfer.flags=flags | INUSE;
-       scsi_xfer.adapter=unit;
-       scsi_xfer.targ=target;
-       scsi_xfer.lu=lu;
-       scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd;
-       scsi_xfer.retries=8;
-       scsi_xfer.timeout=10000;
-       scsi_xfer.cmdlen=sizeof(scsi_cmd);
-       scsi_xfer.data=0;
-       scsi_xfer.datalen=0;
-       scsi_xfer.resid=0;
-       scsi_xfer.when_done=0;
-       scsi_xfer.done_arg=0;
-retry: scsi_xfer.error=0;
-       /*******************************************************\
-       * do not use interrupts                                 *
-       \*******************************************************/
-       rval = (*(scsi_switch->scsi_cmd))(&scsi_xfer);
-       if (rval != COMPLETE)
-       {
-               if(scsi_debug)
-               {
-                       printf("scsi error, rval = 0x%x\n",rval);
-                       printf("code from driver: 0x%x\n",scsi_xfer.error);
-               }
-               switch(scsi_xfer.error)
-               {
-               case    XS_SENSE:
-               /*******************************************************\
-               * Any sense value is illegal except UNIT ATTENTION      *
-               * In which case we need to check again to get the       *
-               * correct response.                                     *
-               *( especially exabytes)                                 *
-               \*******************************************************/
-                       if(scsi_xfer.sense.error_class == 7 )
-                       {
-                               key = scsi_xfer.sense.ext.extended.sense_key ;
-                               switch(key)
-                               { 
-                               case    2:      /* not ready BUT PRESENT! */
-                                               return(COMPLETE);
-                               case    6:
-                                       spinwait(1000);
-                                       if(scsi_xfer.retries--)
-                                       {
-                                               scsi_xfer.flags &= ~ITSDONE;
-                                               goto retry;
-                                       }
-                                       return(COMPLETE);
-                               default:
-                                       if(scsi_debug)
-                                               printf("%d:%d,key=%x.",
-                                               target,lu,key);
-                               }
-                       }
-                       return(HAD_ERROR);
-               case    XS_BUSY:
-                       spinwait(1000);
-                       if(scsi_xfer.retries--)
-                       {
-                               scsi_xfer.flags &= ~ITSDONE;
-                               goto retry;
-                       }
-                       return(COMPLETE);       /* it's busy so it's there */
-               case    XS_TIMEOUT:
-               default:
-                       return(HAD_ERROR);
-               }
-       }
-       return(COMPLETE);
-}
-/***********************************************\
-* Do a scsi operation asking a device what it is*
-* Use the scsi_cmd routine in the switch table.        *
-\***********************************************/
-scsi_inquire(unit,target,lu,scsi_switch,inqbuf, flags)
-struct scsi_switch *scsi_switch;
-u_char *inqbuf;
-{
-       struct  scsi_inquiry scsi_cmd;
-       struct  scsi_xfer scsi_xfer;
-       volatile int rval;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       bzero(&scsi_xfer, sizeof(scsi_xfer));
-       scsi_cmd.op_code = INQUIRY;
-       scsi_cmd.length = sizeof(struct scsi_inquiry_data);
-
-       scsi_xfer.flags=flags | SCSI_DATA_IN | INUSE;
-       scsi_xfer.adapter=unit;
-       scsi_xfer.targ=target;
-       scsi_xfer.lu=lu;
-       scsi_xfer.retries=8;
-       scsi_xfer.timeout=10000;
-       scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd;
-       scsi_xfer.cmdlen= sizeof(struct scsi_inquiry);
-       scsi_xfer.data=inqbuf;
-       scsi_xfer.datalen=sizeof(struct scsi_inquiry_data);
-       scsi_xfer.resid=sizeof(struct scsi_inquiry_data);
-       scsi_xfer.when_done=0;
-       scsi_xfer.done_arg=0;
-retry: scsi_xfer.error=0;
-       /*******************************************************\
-       * do not use interrupts                                 *
-       \*******************************************************/
-       if ((*(scsi_switch->scsi_cmd))(&scsi_xfer) != COMPLETE)
-       {
-               if(scsi_debug) printf("inquiry had error(0x%x) ",scsi_xfer.error);
-               switch(scsi_xfer.error)
-               {
-               case    XS_NOERROR:
-                       break;
-               case    XS_SENSE:
-               /*******************************************************\
-               * Any sense value is illegal except UNIT ATTENTION      *
-               * In which case we need to check again to get the       *
-               * correct response.                                     *
-               *( especially exabytes)                                 *
-               \*******************************************************/
-                       if((scsi_xfer.sense.error_class == 7 )
-                        && (scsi_xfer.sense.ext.extended.sense_key == 6))
-                       { /* it's changed so it's there */
-                               spinwait(1000);
-                               {
-                                       if(scsi_xfer.retries--)
-                                       {
-                                               scsi_xfer.flags &= ~ITSDONE;
-                                               goto retry;
-                                       }
-                               }
-                               return( COMPLETE);
-                       }
-                       return(HAD_ERROR);
-               case    XS_BUSY:
-                       spinwait(1000);
-                       if(scsi_xfer.retries--)
-                       {
-                               scsi_xfer.flags &= ~ITSDONE;
-                               goto retry;
-                       }
-               case    XS_TIMEOUT:
-               default:
-                       return(HAD_ERROR);
-               }
+       if (bestmatch == (struct scsidevs *) 0) {
+#if NUK > 0
+               bestmatch = &unknowndev;
+#else
+               printf("No explicit device driver match.\n");
+#endif
        }
        }
-       return(COMPLETE);
+       return (bestmatch);
 }
 }
-
-
-
-
-/***********************************************\
-* Utility routines often used in SCSI stuff    *
-\***********************************************/
-
-/***********************************************\
-* convert a physical address to 3 bytes,       *
-* MSB at the lowest address,                   *
-* LSB at the highest.                          *
-\***********************************************/
-
-lto3b(val, bytes)
-u_char *bytes;
-{
-       *bytes++ = (val&0xff0000)>>16;
-       *bytes++ = (val&0xff00)>>8;
-       *bytes = val&0xff;
-}
-
-/***********************************************\
-* The reverse of lto3b                         *
-\***********************************************/
-_3btol(bytes)
-u_char *bytes;
-{
-       int rc;
-       rc = (*bytes++ << 16);
-       rc += (*bytes++ << 8);
-       rc += *bytes;
-       return(rc);
-}
-