[BACK]Return to scsiconf.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / scsipi

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/scsipi/scsiconf.c between version 1.156 and 1.156.2.21

version 1.156, 2001/02/26 22:31:27 version 1.156.2.21, 2003/01/15 18:44:24
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
 /*-  /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.   * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
  * All rights reserved.   * All rights reserved.
  *   *
  * This code is derived from software contributed to The NetBSD Foundation   * This code is derived from software contributed to The NetBSD Foundation
Line 54 
Line 54 
  * 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
  */   */
   
 #include <sys/types.h>  #include <sys/cdefs.h>
   __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/kernel.h>  #include <sys/kernel.h>
 #include <sys/proc.h>  #include <sys/proc.h>
   #include <sys/kthread.h>
 #include <sys/malloc.h>  #include <sys/malloc.h>
 #include <sys/device.h>  #include <sys/device.h>
 #include <sys/conf.h>  #include <sys/conf.h>
 #include <sys/fcntl.h>  #include <sys/fcntl.h>
 #include <sys/scsiio.h>  #include <sys/scsiio.h>
   #include <sys/queue.h>
   #include <sys/lock.h>
   
 #include <dev/scsipi/scsi_all.h>  #include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsipi_all.h>  #include <dev/scsipi/scsipi_all.h>
Line 71 
Line 76 
   
 #include "locators.h"  #include "locators.h"
   
 #if 0  const struct scsipi_periphsw scsi_probe_dev = {
 #if NCALS > 0  
         { T_PROCESSOR, T_FIXED, 1,  
           0, 0, 0 },  
 #endif  /* NCALS */  
 #if NBLL > 0  
         { T_PROCESSOR, T_FIXED, 1,  
           "AEG     ", "READER          ", "V1.0" },  
 #endif  /* NBLL */  
 #if NKIL > 0  
         { T_SCANNER, T_FIXED, 0,  
           "KODAK   ", "IL Scanner 900  ", 0 },  
 #endif  /* NKIL */  
 #endif  
   
 /*  
  * Declarations  
  */  
 int scsi_probedev __P((struct scsibus_softc *, int, int));  
 int scsi_probe_bus __P((int bus, int target, int lun));  
   
 struct scsipi_device probe_switch = {  
         NULL,          NULL,
         NULL,          NULL,
         NULL,          NULL,
         NULL,          NULL,
 };  };
   
 int scsibusmatch __P((struct device *, struct cfdata *, void *));  struct scsi_initq {
 void scsibusattach __P((struct device *, struct device *, void *));          struct scsipi_channel *sc_channel;
 int scsibusactivate __P((struct device *, enum devact));          TAILQ_ENTRY(scsi_initq) scsi_initq;
 int scsibusdetach __P((struct device *, int flags));  
   
 int scsibussubmatch __P((struct device *, struct cfdata *, void *));  
   
 struct cfattach scsibus_ca = {  
         sizeof(struct scsibus_softc), scsibusmatch, scsibusattach,  
             scsibusdetach, scsibusactivate,  
 };  };
   
   static TAILQ_HEAD(, scsi_initq) scsi_initq_head =
       TAILQ_HEAD_INITIALIZER(scsi_initq_head);
   static struct simplelock scsibus_interlock = SIMPLELOCK_INITIALIZER;
   
   int     scsi_probe_device __P((struct scsibus_softc *, int, int));
   
   int     scsibusmatch __P((struct device *, struct cfdata *, void *));
   void    scsibusattach __P((struct device *, struct device *, void *));
   int     scsibusactivate __P((struct device *, enum devact));
   int     scsibusdetach __P((struct device *, int flags));
   
   int     scsibussubmatch __P((struct device *, struct cfdata *, void *));
   
   CFATTACH_DECL(scsibus, sizeof(struct scsibus_softc),
       scsibusmatch, scsibusattach, scsibusdetach, scsibusactivate);
   
 extern struct cfdriver scsibus_cd;  extern struct cfdriver scsibus_cd;
   
 int scsibusprint __P((void *, const char *));  dev_type_open(scsibusopen);
 void scsibus_config_interrupts __P((struct device *));  dev_type_close(scsibusclose);
   dev_type_ioctl(scsibusioctl);
   
   const struct cdevsw scsibus_cdevsw = {
           scsibusopen, scsibusclose, noread, nowrite, scsibusioctl,
           nostop, notty, nopoll, nommap, nokqfilter,
   };
   
 cdev_decl(scsibus);  int     scsibusprint __P((void *, const char *));
   void    scsibus_config __P((struct scsipi_channel *, void *));
   
   const struct scsipi_bustype scsi_bustype = {
           SCSIPI_BUSTYPE_SCSI,
           scsi_scsipi_cmd,
           scsipi_interpret_sense,
           scsi_print_addr,
           scsi_kill_pending,
   };
   
   int
   scsiprint(aux, pnp)
           void *aux;
           const char *pnp;
   {
           struct scsipi_channel *chan = aux;
           struct scsipi_adapter *adapt = chan->chan_adapter;
   
           /* only "scsibus"es can attach to "scsi"s; easy. */
           if (pnp)
                   aprint_normal("scsibus at %s", pnp);
   
           /* don't print channel if the controller says there can be only one. */
           if (adapt->adapt_nchannels != 1)
                   aprint_normal(" channel %d", chan->chan_channel);
   
           return (UNCONF);
   }
   
 int  int
 scsibusmatch(parent, cf, aux)  scsibusmatch(parent, cf, aux)
Line 124  scsibusmatch(parent, cf, aux)
Line 151  scsibusmatch(parent, cf, aux)
         struct cfdata *cf;          struct cfdata *cf;
         void *aux;          void *aux;
 {  {
         struct scsipi_link *l = aux;          struct scsipi_channel *chan = aux;
         int channel;  
   
         if (l->type != BUS_SCSI)          if (chan->chan_bustype->bustype_type != SCSIPI_BUSTYPE_SCSI)
                 return (0);                  return 0;
   
         /*  
          * Allow single-channel controllers to specify their channel  
          * in a special way, so that it's not printed.  
          */  
         channel = (l->scsipi_scsi.channel != SCSI_CHANNEL_ONLY_ONE) ?  
             l->scsipi_scsi.channel : 0;  
   
         if (cf->cf_loc[SCSICF_CHANNEL] != channel &&          if (cf->cf_loc[SCSICF_CHANNEL] != chan->chan_channel &&
             cf->cf_loc[SCSICF_CHANNEL] != SCSICF_CHANNEL_DEFAULT)              cf->cf_loc[SCSICF_CHANNEL] != SCSICF_CHANNEL_DEFAULT)
                 return (0);                  return (0);
   
         return (1);          return (1);
 }  }
   
 /*  
  * The routine called by the adapter boards to get all their  
  * devices configured in.  
  */  
 void  void
 scsibusattach(parent, self, aux)  scsibusattach(parent, self, aux)
         struct device *parent, *self;          struct device *parent, *self;
         void *aux;          void *aux;
 {  {
         struct scsibus_softc *sb = (struct scsibus_softc *)self;          struct scsibus_softc *sc = (void *) self;
         struct scsipi_link *sc_link_proto = aux;          struct scsipi_channel *chan = aux;
         size_t nbytes;          struct scsi_initq *scsi_initq;
         int i;  
           sc->sc_channel = chan;
         sc_link_proto->scsipi_scsi.scsibus = sb->sc_dev.dv_unit;          chan->chan_name = sc->sc_dev.dv_xname;
         sc_link_proto->scsipi_cmd = scsi_scsipi_cmd;  
         sc_link_proto->scsipi_interpret_sense = scsipi_interpret_sense;          printf(": %d target%s, %d lun%s per target\n",
         sc_link_proto->sc_print_addr = scsi_print_addr;              chan->chan_ntargets,
         sc_link_proto->scsipi_kill_pending = scsi_kill_pending;              chan->chan_ntargets == 1 ? "" : "s",
               chan->chan_nluns,
         sb->adapter_link = sc_link_proto;              chan->chan_nluns == 1 ? "" : "s");
         sb->sc_maxtarget = sc_link_proto->scsipi_scsi.max_target;  
         sb->sc_maxlun = sc_link_proto->scsipi_scsi.max_lun;          /* Initialize the channel structure first */
         printf(": %d targets, %d luns per target\n",          chan->chan_init_cb = scsibus_config;
             sb->sc_maxtarget + 1, sb->sc_maxlun + 1);          chan->chan_init_cb_arg = sc;
   
         /* Initialize shared data. */          scsi_initq = malloc(sizeof(struct scsi_initq), M_DEVBUF, M_WAITOK);
         scsipi_init();          scsi_initq->sc_channel = chan;
           TAILQ_INSERT_TAIL(&scsi_initq_head, scsi_initq, scsi_initq);
         nbytes = (sb->sc_maxtarget + 1) * sizeof(struct scsipi_link **);          config_pending_incr();
         sb->sc_link = (struct scsipi_link ***)malloc(nbytes, M_DEVBUF,          if (scsipi_channel_init(chan)) {
             M_NOWAIT);                  printf(": failed to init channel\n");
         if (sb->sc_link == NULL)                  return;
                 panic("scsibusattach: can't allocate target links");  
   
         nbytes = (((int) sb->sc_maxlun) + 1) * sizeof(struct scsipi_link *);  
         for (i = 0; i <= sb->sc_maxtarget; i++) {  
                 sb->sc_link[i] = (struct scsipi_link **)malloc(nbytes,  
                     M_DEVBUF, M_NOWAIT);  
                 if (sb->sc_link[i] == NULL)  
                         panic("scsibusattach: can't allocate lun links");  
                 bzero(sb->sc_link[i], nbytes);  
         }          }
   
         /*  
          * Defer configuration of the children until interrupts  
          * are enabled.  
          */  
         config_interrupts(self, scsibus_config_interrupts);  
 }  }
   
 void  void
 scsibus_config_interrupts(self)  scsibus_config(chan, arg)
         struct device *self;          struct scsipi_channel *chan;
           void *arg;
 {  {
           struct scsibus_softc *sc = arg;
           struct scsi_initq *scsi_initq;
   
 #ifndef SCSI_DELAY  #ifndef SCSI_DELAY
 #define SCSI_DELAY 2  #define SCSI_DELAY 2
 #endif  #endif
         if (SCSI_DELAY > 0) {  
           /* Make sure the devices probe in scsibus order to avoid jitter. */
           simple_lock(&scsibus_interlock);
           for (;;) {
                   scsi_initq = TAILQ_FIRST(&scsi_initq_head);
                   if (scsi_initq->sc_channel == chan)
                           break;
                   ltsleep(&scsi_initq_head, PRIBIO, "scsi_initq", 0,
                       &scsibus_interlock);
           }
   
           simple_unlock(&scsibus_interlock);
   
           if ((chan->chan_flags & SCSIPI_CHAN_NOSETTLE) == 0 &&
               SCSI_DELAY > 0) {
                 printf("%s: waiting %d seconds for devices to settle...\n",                  printf("%s: waiting %d seconds for devices to settle...\n",
                     self->dv_xname, SCSI_DELAY);                      sc->sc_dev.dv_xname, SCSI_DELAY);
                 /* ...an identifier we know no one will use... */                  /* ...an identifier we know no one will use... */
                 (void) tsleep(scsibus_config_interrupts, PRIBIO,                  (void) tsleep(scsibus_config, PRIBIO,
                     "scsidly", SCSI_DELAY * hz);                      "scsidly", SCSI_DELAY * hz);
         }          }
   
         scsi_probe_bus(self->dv_unit, -1, -1);          scsi_probe_bus(sc, -1, -1);
   
           simple_lock(&scsibus_interlock);
           TAILQ_REMOVE(&scsi_initq_head, scsi_initq, scsi_initq);
           simple_unlock(&scsibus_interlock);
   
           free(scsi_initq, M_DEVBUF);
           wakeup(&scsi_initq_head);
   
           config_pending_decr();
 }  }
   
 int  int
Line 220  scsibussubmatch(parent, cf, aux)
Line 248  scsibussubmatch(parent, cf, aux)
         void *aux;          void *aux;
 {  {
         struct scsipibus_attach_args *sa = aux;          struct scsipibus_attach_args *sa = aux;
         struct scsipi_link *sc_link = sa->sa_sc_link;          struct scsipi_periph *periph = sa->sa_periph;
   
         if (cf->cf_loc[SCSIBUSCF_TARGET] != SCSIBUSCF_TARGET_DEFAULT &&          if (cf->cf_loc[SCSIBUSCF_TARGET] != SCSIBUSCF_TARGET_DEFAULT &&
             cf->cf_loc[SCSIBUSCF_TARGET] != sc_link->scsipi_scsi.target)              cf->cf_loc[SCSIBUSCF_TARGET] != periph->periph_target)
                 return (0);                  return (0);
         if (cf->cf_loc[SCSIBUSCF_LUN] != SCSIBUSCF_LUN_DEFAULT &&          if (cf->cf_loc[SCSIBUSCF_LUN] != SCSIBUSCF_LUN_DEFAULT &&
             cf->cf_loc[SCSIBUSCF_LUN] != sc_link->scsipi_scsi.lun)              cf->cf_loc[SCSIBUSCF_LUN] != periph->periph_lun)
                 return (0);                  return (0);
         return ((*cf->cf_attach->ca_match)(parent, cf, aux));          return (config_match(parent, cf, aux));
 }  }
   
 int  int
Line 236  scsibusactivate(self, act)
Line 264  scsibusactivate(self, act)
         struct device *self;          struct device *self;
         enum devact act;          enum devact act;
 {  {
         struct scsibus_softc *sc = (struct scsibus_softc *) self;          struct scsibus_softc *sc = (void *) self;
         struct scsipi_link *sc_link;          struct scsipi_channel *chan = sc->sc_channel;
           struct scsipi_periph *periph;
         int target, lun, error = 0, s;          int target, lun, error = 0, s;
   
         s = splbio();          s = splbio();
Line 247  scsibusactivate(self, act)
Line 276  scsibusactivate(self, act)
                 break;                  break;
   
         case DVACT_DEACTIVATE:          case DVACT_DEACTIVATE:
                 for (target = 0; target <= sc->sc_maxtarget; target++) {                  for (target = 0; target < chan->chan_ntargets;
                         if (target ==                       target++) {
                             sc->adapter_link->scsipi_scsi.adapter_target)                          if (target == chan->chan_id)
                                 continue;                                  continue;
                         for (lun = 0; lun <= sc->sc_maxlun; lun++) {                          for (lun = 0; lun < chan->chan_nluns; lun++) {
                                 sc_link = sc->sc_link[target][lun];                                  periph = scsipi_lookup_periph(chan,
                                 if (sc_link == NULL)                                      target, lun);
                                   if (periph == NULL)
                                         continue;                                          continue;
                                 error =                                  error = config_deactivate(periph->periph_dev);
                                     config_deactivate(sc_link->device_softc);  
                                 if (error)                                  if (error)
                                         goto out;                                          goto out;
                         }                          }
Line 273  scsibusdetach(self, flags)
Line 302  scsibusdetach(self, flags)
         struct device *self;          struct device *self;
         int flags;          int flags;
 {  {
         struct scsibus_softc *sc = (struct scsibus_softc *) self;          struct scsibus_softc *sc = (void *) self;
         struct scsipi_link *sc_link;          struct scsipi_channel *chan = sc->sc_channel;
         int target, lun, error;  
   
         for (target = 0; target <= sc->sc_maxtarget; target++) {          /*
                 if (target == sc->adapter_link->scsipi_scsi.adapter_target)           * Shut down the channel.
                         continue;           */
                 for (lun = 0; lun <= sc->sc_maxlun; lun++) {          scsipi_channel_shutdown(chan);
                         sc_link = sc->sc_link[target][lun];  
                         if (sc_link == NULL)  
                                 continue;  
                         error = config_detach(sc_link->device_softc, flags);  
                         if (error)  
                                 return (error);  
                         free(sc_link, M_DEVBUF);  
                         sc->sc_link[target][lun] = NULL;  
                 }  
         }  
         return (0);  
 }  
   
 /*  
  * Probe the requested scsi bus. It must be already set up.  
  * -1 requests all set up scsi busses.  
  * target and lun optionally narrow the search if not -1  
  */  
 int  
 scsi_probe_busses(bus, target, lun)  
         int bus, target, lun;  
 {  
   
         if (bus == -1) {          /*
                 for (bus = 0; bus < scsibus_cd.cd_ndevs; bus++)           * Now detach all of the periphs.
                         if (scsibus_cd.cd_devs[bus])           */
                                 scsi_probe_bus(bus, target, lun);          return scsipi_target_detach(chan, -1, -1, flags);
                 return (0);  
         } else  
                 return (scsi_probe_bus(bus, target, lun));  
 }  }
   
 /*  /*
Line 318  scsi_probe_busses(bus, target, lun)
Line 321  scsi_probe_busses(bus, target, lun)
  * target and lun optionally narrow the search if not -1   * target and lun optionally narrow the search if not -1
  */   */
 int  int
 scsi_probe_bus(bus, target, lun)  scsi_probe_bus(sc, target, lun)
         int bus, target, lun;          struct scsibus_softc *sc;
           int target, lun;
 {  {
         struct scsibus_softc *scsi;          struct scsipi_channel *chan = sc->sc_channel;
         struct scsipi_link *sc_link;  
         int maxtarget, mintarget, maxlun, minlun;          int maxtarget, mintarget, maxlun, minlun;
         u_int8_t scsi_addr;  
         int error;          int error;
   
         if (bus < 0 || bus >= scsibus_cd.cd_ndevs)  
                 return (ENXIO);  
         scsi = scsibus_cd.cd_devs[bus];  
         if (scsi == NULL)  
                 return (ENXIO);  
   
         sc_link = scsi->adapter_link;  
         scsi_addr = sc_link->scsipi_scsi.adapter_target;  
   
         if (target == -1) {          if (target == -1) {
                 maxtarget = scsi->sc_maxtarget;                  maxtarget = chan->chan_ntargets - 1;
                 mintarget = 0;                  mintarget = 0;
         } else {          } else {
                 if (target < 0 || target > scsi->sc_maxtarget)                  if (target < 0 || target >= chan->chan_ntargets)
                         return (EINVAL);                          return (EINVAL);
                 maxtarget = mintarget = target;                  maxtarget = mintarget = target;
         }          }
   
         if (lun == -1) {          if (lun == -1) {
                 maxlun = scsi->sc_maxlun;                  maxlun = chan->chan_nluns - 1;
                 minlun = 0;                  minlun = 0;
         } else {          } else {
                 if (lun < 0 || lun > scsi->sc_maxlun)                  if (lun < 0 || lun >= chan->chan_nluns)
                         return (EINVAL);                          return (EINVAL);
                 maxlun = minlun = lun;                  maxlun = minlun = lun;
         }          }
Line 358  scsi_probe_bus(bus, target, lun)
Line 351  scsi_probe_bus(bus, target, lun)
          * Some HBAs provide an abstracted view of the bus; give them an           * Some HBAs provide an abstracted view of the bus; give them an
          * oppertunity to re-scan it before we do.           * oppertunity to re-scan it before we do.
          */           */
         if (sc_link->adapter->scsipi_ioctl != NULL)          if (chan->chan_adapter->adapt_ioctl != NULL)
                 (*sc_link->adapter->scsipi_ioctl)(sc_link, SCBUSIOLLSCAN, NULL,                  (*chan->chan_adapter->adapt_ioctl)(chan, SCBUSIOLLSCAN, NULL,
                     0, curproc);                      0, curproc);
   
         if ((error = scsipi_adapter_addref(sc_link)) != 0)          if ((error = scsipi_adapter_addref(chan->chan_adapter)) != 0)
                 return (error);                  return (error);
         for (target = mintarget; target <= maxtarget; target++) {          for (target = mintarget; target <= maxtarget; target++) {
                 if (target == scsi_addr)                  if (target == chan->chan_id)
                         continue;                          continue;
                 for (lun = minlun; lun <= maxlun; lun++) {                  for (lun = minlun; lun <= maxlun; lun++) {
                         /*                          /*
                          * See if there's a device present, and configure it.                           * See if there's a device present, and configure it.
                          */                           */
                         if (scsi_probedev(scsi, target, lun) == 0) {                          if (scsi_probe_device(sc, target, lun) == 0)
                                 break;                                  break;
                         }  
                         /* otherwise something says we should look further */                          /* otherwise something says we should look further */
                 }                  }
   
                   /*
                    * Now that we've discovered all of the LUNs on this
                    * I_T Nexus, update the xfer mode for all of them
                    * that we know about.
                    */
                   scsipi_set_xfer_mode(chan, target, 1);
         }          }
         scsipi_adapter_delref(sc_link);          scsipi_adapter_delref(chan->chan_adapter);
         return (0);          return (0);
 }  }
   
Line 399  scsibusprint(aux, pnp)
Line 398  scsibusprint(aux, pnp)
         struct scsipibus_attach_args *sa = aux;          struct scsipibus_attach_args *sa = aux;
         struct scsipi_inquiry_pattern *inqbuf;          struct scsipi_inquiry_pattern *inqbuf;
         u_int8_t type;          u_int8_t type;
         char *dtype, *qtype;          const char *dtype;
         char vendor[33], product[65], revision[17];          char vendor[33], product[65], revision[17];
         int target, lun;          int target, lun;
   
         if (pnp != NULL)          if (pnp != NULL)
                 printf("%s", pnp);                  aprint_normal("%s", pnp);
   
         inqbuf = &sa->sa_inqbuf;          inqbuf = &sa->sa_inqbuf;
   
         target = sa->sa_sc_link->scsipi_scsi.target;          target = sa->sa_periph->periph_target;
         lun = sa->sa_sc_link->scsipi_scsi.lun;          lun = sa->sa_periph->periph_lun;
   
         type = inqbuf->type & SID_TYPE;          type = inqbuf->type & SID_TYPE;
   
         /*          dtype = scsipi_dtype(type);
          * Figure out basic device type and qualifier.  
          */  
         dtype = 0;  
         switch (inqbuf->type & SID_QUAL) {  
         case SID_QUAL_LU_OK:  
                 qtype = "";  
                 break;  
   
         case SID_QUAL_LU_OFFLINE:  
                 qtype = " offline";  
                 break;  
   
         case SID_QUAL_RSVD:  
         case SID_QUAL_BAD_LU:  
                 panic("scsibusprint: impossible qualifier");  
   
         default:  
                 qtype = "";  
                 dtype = "vendor-unique";  
                 break;  
         }  
         if (dtype == 0)  
                 dtype = scsipi_dtype(type);  
   
         scsipi_strvis(vendor, 33, inqbuf->vendor, 8);          scsipi_strvis(vendor, 33, inqbuf->vendor, 8);
         scsipi_strvis(product, 65, inqbuf->product, 16);          scsipi_strvis(product, 65, inqbuf->product, 16);
         scsipi_strvis(revision, 17, inqbuf->revision, 4);          scsipi_strvis(revision, 17, inqbuf->revision, 4);
   
         printf(" target %d lun %d: <%s, %s, %s> SCSI%d %d/%s %s%s",          aprint_normal(" target %d lun %d: <%s, %s, %s> %s %s",
             target, lun, vendor, product, revision,              target, lun, vendor, product, revision, dtype,
             sa->scsipi_info.scsi_version & SID_ANSII, type, dtype,              inqbuf->removable ? "removable" : "fixed");
             inqbuf->removable ? "removable" : "fixed", qtype);  
   
         return (UNCONF);          return (UNCONF);
 }  }
   
 const struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = {  const struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = {
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "CHINON  ", "CD-ROM CDS-431  ", ""},     SDEV_NOLUNS},           "CHINON  ", "CD-ROM CDS-431  ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "Chinon  ", "CD-ROM CDS-525  ", ""},     SDEV_NOLUNS},           "Chinon  ", "CD-ROM CDS-525  ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "CHINON  ", "CD-ROM CDS-535  ", ""},     SDEV_NOLUNS},           "CHINON  ", "CD-ROM CDS-535  ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "DEC     ", "RRD42   (C) DEC ", ""},     SDEV_NOLUNS},           "DEC     ", "RRD42   (C) DEC ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "DENON   ", "DRD-25X         ", "V"},    SDEV_NOLUNS},           "DENON   ", "DRD-25X         ", "V"},    PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "GENERIC ", "CRD-BP2         ", ""},     SDEV_NOLUNS},           "GENERIC ", "CRD-BP2         ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "HP      ", "C4324/C4325     ", ""},     SDEV_NOLUNS},           "HP      ", "C4324/C4325     ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "IMS     ", "CDD521/10       ", "2.06"}, SDEV_NOLUNS},           "IMS     ", "CDD521/10       ", "2.06"}, PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "MATSHITA", "CD-ROM CR-5XX   ", "1.0b"}, SDEV_NOLUNS},           "MATSHITA", "CD-ROM CR-5XX   ", "1.0b"}, PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "MEDAVIS ", "RENO CD-ROMX2A  ", ""},     SDEV_NOLUNS},           "MEDAVIS ", "RENO CD-ROMX2A  ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "MEDIAVIS", "CDR-H93MV       ", "1.3"},  SDEV_NOLUNS},           "MEDIAVIS", "CDR-H93MV       ", "1.3"},  PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "NEC     ", "CD-ROM DRIVE:55 ", ""},     SDEV_NOLUNS},           "NEC     ", "CD-ROM DRIVE:55 ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "NEC     ", "CD-ROM DRIVE:83 ", ""},     SDEV_NOLUNS},           "NEC     ", "CD-ROM DRIVE:83 ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "NEC     ", "CD-ROM DRIVE:84 ", ""},     SDEV_NOLUNS},           "NEC     ", "CD-ROM DRIVE:84 ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "NEC     ", "CD-ROM DRIVE:841", ""},     SDEV_NOLUNS},           "NEC     ", "CD-ROM DRIVE:841", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "PIONEER ", "CD-ROM DR-124X  ", "1.01"}, SDEV_NOLUNS},           "PIONEER ", "CD-ROM DR-124X  ", "1.01"}, PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "SONY    ", "CD-ROM CDU-541  ", ""},     SDEV_NOLUNS},           "SONY    ", "CD-ROM CDU-541  ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "SONY    ", "CD-ROM CDU-55S  ", ""},     SDEV_NOLUNS},           "SONY    ", "CD-ROM CDU-55S  ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "SONY    ", "CD-ROM CDU-561  ", ""},     SDEV_NOLUNS},           "SONY    ", "CD-ROM CDU-561  ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "SONY    ", "CD-ROM CDU-8003A", ""},     SDEV_NOLUNS},           "SONY    ", "CD-ROM CDU-76S", ""},
                                   PQUIRK_NOLUNS|PQUIRK_NOSYNC|PQUIRK_NOWIDE},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "SONY    ", "CD-ROM CDU-8012 ", ""},     SDEV_NOLUNS},           "SONY    ", "CD-ROM CDU-8003A", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "TEAC    ", "CD-ROM          ", "1.06"}, SDEV_NOLUNS},           "SONY    ", "CD-ROM CDU-8012 ", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "TEAC    ", "CD-ROM CD-56S   ", "1.0B"}, SDEV_NOLUNS},           "TEAC    ", "CD-ROM          ", "1.06"}, PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "TEXEL   ", "CD-ROM          ", "1.06"}, SDEV_NOLUNS},           "TEAC    ", "CD-ROM CD-56S   ", "1.0B"}, PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "TEXEL   ", "CD-ROM DM-XX24 K", "1.09"}, SDEV_NOLUNS},           "TEXEL   ", "CD-ROM          ", "1.06"}, PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "TEXEL   ", "CD-ROM DM-XX24 K", "1.10"}, SDEV_NOLUNS},           "TEXEL   ", "CD-ROM DM-XX24 K", "1.09"}, PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "TOSHIBA ", "XM-4101TASUNSLCD", "1755"}, SDEV_NOLUNS|SDEV_NOSYNC},           "TEXEL   ", "CD-ROM DM-XX24 K", "1.10"}, PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "ShinaKen", "CD-ROM DM-3x1S", "1.04"}, SDEV_NOLUNS},           "TOSHIBA ", "XM-4101TASUNSLCD", "1755"}, PQUIRK_NOLUNS|PQUIRK_NOSYNC},
           /* "IBM CDRM00201     !F" 0724 is an IBM OEM Toshiba XM-4101BME */
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "JVC     ", "R2626",            ""},     SDEV_NOLUNS},           "IBM     ", "CDRM00201     !F", "0724"}, PQUIRK_NOLUNS|PQUIRK_NOSYNC},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "YAMAHA", "CRW8424S",           ""},     SDEV_NOLUNS},           "ShinaKen", "CD-ROM DM-3x1S",   "1.04"}, PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,          {{T_CDROM, T_REMOV,
          "VMware", "Virtual",           "1.0"},           "JVC     ", "R2626",            ""},     PQUIRK_NOLUNS},
                                 SDEV_NOSTARTUNIT|ADEV_NODOORLOCK},          {{T_CDROM, T_REMOV,
            "YAMAHA", "CRW8424S",           ""},     PQUIRK_NOLUNS},
           {{T_CDROM, T_REMOV,
            "VMware", "Virtual",            "1.0"},
                                   PQUIRK_NOSTARTUNIT|PQUIRK_NODOORLOCK},
           {{T_CDROM, T_REMOV,
            "NEC     ", "CD-ROM DRIVE:222", ""},     PQUIRK_NOLUNS|PQUIRK_NOSYNC},
   
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MICROP  ", "1588-15MBSUN0669", ""},     SDEV_AUTOSAVE},           "MICROP  ", "1588-15MBSUN0669", ""},     PQUIRK_AUTOSAVE},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MICROP  ", "2217-15MQ1091501", ""},     SDEV_NOSYNCCACHE},           "MICROP  ", "2217-15MQ1091501", ""},     PQUIRK_NOSYNCCACHE},
         {{T_OPTICAL, T_REMOV,          {{T_OPTICAL, T_REMOV,
          "EPSON   ", "OMD-5010        ", "3.08"}, SDEV_NOLUNS},           "EPSON   ", "OMD-5010        ", "3.08"}, PQUIRK_NOLUNS},
           {{T_DIRECT, T_FIXED,
            "TOSHIBA ","CD-ROM XM-3401TA",  "0283"}, PQUIRK_CDROM|PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
         "TOSHIBA ", "CD-ROM XM-3401TA", "0283"}, SDEV_CDROM|SDEV_NOLUNS},           "TOSHIBA ", "CD-ROM DRIVE:XM",  "1971"}, PQUIRK_CDROM|PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
         "TOSHIBA ", "CD-ROM DRIVE:XM", "1971"}, SDEV_CDROM|SDEV_NOLUNS},           "ADAPTEC ", "AEC-4412BD",       "1.2A"}, PQUIRK_NOMODESENSE},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "ADAPTEC ", "AEC-4412BD",       "1.2A"}, SDEV_NOMODESENSE},           "ADAPTEC ", "ACB-4000",         ""},     PQUIRK_FORCELUNS|PQUIRK_AUTOSAVE|PQUIRK_NOMODESENSE},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "DEC     ", "RZ55     (C) DEC", ""},     SDEV_AUTOSAVE},           "DEC     ", "RZ55     (C) DEC", ""},     PQUIRK_AUTOSAVE},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "EMULEX  ", "MD21/S2     ESDI", "A00"},  SDEV_FORCELUNS|SDEV_AUTOSAVE},           "EMULEX  ", "MD21/S2     ESDI", "A00"},
                                   PQUIRK_FORCELUNS|PQUIRK_AUTOSAVE},
         /* Gives non-media hardware failure in response to start-unit command */          /* Gives non-media hardware failure in response to start-unit command */
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "HITACHI", "DK515C",           "CP16"},  SDEV_NOSTARTUNIT},           "HITACHI", "DK515C",            "CP16"}, PQUIRK_NOSTARTUNIT},
           {{T_DIRECT, T_FIXED,
            "HITACHI", "DK515C",            "CP15"}, PQUIRK_NOSTARTUNIT},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "HITACHI", "DK515C",           "CP15"},  SDEV_NOSTARTUNIT},          /* improperly report DT-only sync mode */
            "HITACHI", "DX32DJ-72ME",       ""},
                                   PQUIRK_CAP_SYNC|PQUIRK_CAP_WIDE16},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "HP      ", "C372",             ""},     SDEV_NOTAG},           "MICROP",  "1548-15MZ1077801",  "HZ2P"}, PQUIRK_NOTAG},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "IBMRAID ", "0662S",            ""},     SDEV_AUTOSAVE},           "HP      ", "C372",             ""},     PQUIRK_NOTAG},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "IBM     ", "0663H",            ""},     SDEV_AUTOSAVE},           "IBMRAID ", "0662S",            ""},     PQUIRK_AUTOSAVE},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "IBM",      "0664",             ""},     SDEV_AUTOSAVE},           "IBM     ", "0663H",            ""},     PQUIRK_AUTOSAVE},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "IBM     ", "H3171-S2",         ""},     SDEV_NOLUNS|SDEV_AUTOSAVE},           "IBM",      "0664",             ""},     PQUIRK_AUTOSAVE},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "IBM     ", "KZ-C",             ""},     SDEV_AUTOSAVE},          /* improperly report DT-only sync mode */
            "IBM     ", "DXHS36D",          ""},
                                   PQUIRK_CAP_SYNC|PQUIRK_CAP_WIDE16},
           {{T_DIRECT, T_FIXED,
            "IBM     ", "H3171-S2",         ""},
                                   PQUIRK_NOLUNS|PQUIRK_AUTOSAVE},
           {{T_DIRECT, T_FIXED,
            "IBM     ", "KZ-C",             ""},     PQUIRK_AUTOSAVE},
         /* Broken IBM disk */          /* Broken IBM disk */
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          ""        , "DFRSS2F",          ""},     SDEV_AUTOSAVE},           ""        , "DFRSS2F",          ""},     PQUIRK_AUTOSAVE},
         {{T_DIRECT, T_REMOV,          {{T_DIRECT, T_REMOV,
          "MPL     ", "MC-DISK-        ", ""},     SDEV_NOLUNS},           "MPL     ", "MC-DISK-        ", ""},     PQUIRK_NOLUNS},
           {{T_DIRECT, T_FIXED,
            "MAXTOR  ", "XT-3280         ", ""},     PQUIRK_NOLUNS},
           {{T_DIRECT, T_FIXED,
            "MAXTOR  ", "XT-4380S        ", ""},     PQUIRK_NOLUNS},
           {{T_DIRECT, T_FIXED,
            "MAXTOR  ", "MXT-1240S       ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MAXTOR  ", "XT-3280         ", ""},     SDEV_NOLUNS},           "MAXTOR  ", "XT-4170S        ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MAXTOR  ", "XT-4380S        ", ""},     SDEV_NOLUNS},           "MAXTOR  ", "XT-8760S",         ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MAXTOR  ", "MXT-1240S       ", ""},     SDEV_NOLUNS},           "MAXTOR  ", "LXT-213S        ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MAXTOR  ", "XT-4170S        ", ""},     SDEV_NOLUNS},           "MAXTOR  ", "LXT-213S SUN0207", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MAXTOR  ", "XT-8760S",         ""},     SDEV_NOLUNS},           "MAXTOR  ", "LXT-200S        ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MAXTOR  ", "LXT-213S        ", ""},     SDEV_NOLUNS},           "MEGADRV ", "EV1000",           ""},     PQUIRK_NOMODESENSE},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MAXTOR  ", "LXT-213S SUN0207", ""},     SDEV_NOLUNS},           "MICROP", "1991-27MZ",          ""},     PQUIRK_NOTAG},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MAXTOR  ", "LXT-200S        ", ""},     SDEV_NOLUNS},           "MST     ", "SnapLink        ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MEGADRV ", "EV1000",           ""},     SDEV_NOMODESENSE},           "NEC     ", "D3847           ", "0307"}, PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "MST     ", "SnapLink        ", ""},     SDEV_NOLUNS},           "QUANTUM ", "ELS85S          ", ""},     PQUIRK_AUTOSAVE},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "NEC     ", "D3847           ", "0307"}, SDEV_NOLUNS},           "QUANTUM ", "LPS525S         ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "QUANTUM ", "ELS85S          ", ""},     SDEV_AUTOSAVE},           "QUANTUM ", "P105S 910-10-94x", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "QUANTUM ", "LPS525S         ", ""},     SDEV_NOLUNS},           "QUANTUM ", "PD1225S         ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "QUANTUM ", "P105S 910-10-94x", ""},     SDEV_NOLUNS},           "QUANTUM ", "PD210S   SUN0207", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "QUANTUM ", "PD1225S         ", ""},     SDEV_NOLUNS},           "RODIME  ", "RO3000S         ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "QUANTUM ", "PD210S   SUN0207", ""},     SDEV_NOLUNS},           "SEAGATE ", "ST125N          ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "RODIME  ", "RO3000S         ", ""},     SDEV_NOLUNS},           "SEAGATE ", "ST157N          ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "SEAGATE ", "ST125N          ", ""},     SDEV_NOLUNS},           "SEAGATE ", "ST296           ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "SEAGATE ", "ST157N          ", ""},     SDEV_NOLUNS},           "SEAGATE ", "ST296N          ", ""},     PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "SEAGATE ", "ST296           ", ""},     SDEV_NOLUNS},           "SEAGATE ", "ST11200N SUN1.05", ""},     PQUIRK_NOTAG},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "SEAGATE ", "ST296N          ", ""},     SDEV_NOLUNS},           "SEAGATE ", "ST15150N        ", ""},     PQUIRK_NOTAG},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "SEAGATE ", "ST19171",          ""},     SDEV_NOMODESENSE},           "SEAGATE ", "ST19171",          ""},     PQUIRK_NOMODESENSE},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "SEAGATE ", "ST34501FC       ", ""},     SDEV_NOMODESENSE},           "SEAGATE ", "ST32430N",         ""},     PQUIRK_CAP_SYNC},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "TOSHIBA ", "MK538FB         ", "6027"}, SDEV_NOLUNS},           "SEAGATE ", "ST34501FC       ", ""},     PQUIRK_NOMODESENSE},
           {{T_DIRECT, T_FIXED,
            "TOSHIBA ", "MK538FB         ", "6027"}, PQUIRK_NOLUNS},
         {{T_DIRECT, T_FIXED,          {{T_DIRECT, T_FIXED,
          "VMware", "Virtual",           "1.0"},           "VMware", "Virtual",           "1.0"},
                                 SDEV_NOSTARTUNIT|ADEV_NODOORLOCK},                                  PQUIRK_NOSTARTUNIT|PQUIRK_NODOORLOCK},
           {{T_DIRECT, T_FIXED,    /* XXX move to umass */
            "Maxtor 4", "D080H4",           "DAH0"}, PQUIRK_NOMODESENSE},
           {{T_DIRECT, T_FIXED,    /* XXX move to umass */
            "Maxtor 4", "D040H2",           "DAH0"}, PQUIRK_NOMODESENSE},
           {{T_DIRECT, T_FIXED,
            "MICROP  ", "1924",          ""},     PQUIRK_CAP_SYNC},
           {{T_DIRECT, T_FIXED,
            "FUJITSU ", "M2266",         ""},     PQUIRK_CAP_SYNC},
   
         {{T_DIRECT, T_REMOV,          {{T_DIRECT, T_REMOV,
          "iomega", "jaz 1GB",            ""},     SDEV_NOMODESENSE},           "iomega", "jaz 1GB",            ""},     PQUIRK_NOMODESENSE},
         {{T_DIRECT, T_REMOV,          {{T_DIRECT, T_REMOV,
          "IOMEGA", "ZIP 100",            ""},     SDEV_NOMODESENSE},           "IOMEGA", "ZIP 100",            ""},     PQUIRK_NOMODESENSE},
         {{T_DIRECT, T_REMOV,          {{T_DIRECT, T_REMOV,
          "IOMEGA", "ZIP 100",            "J.03"}, SDEV_NOMODESENSE|SDEV_NOLUNS},           "IOMEGA", "ZIP 100",            "J.03"},
                                   PQUIRK_NOMODESENSE|PQUIRK_NOLUNS},
         /* Letting the motor run kills floppy drives and disks quite fast. */          /* Letting the motor run kills floppy drives and disks quite fast. */
         {{T_DIRECT, T_REMOV,          {{T_DIRECT, T_REMOV,
          "TEAC", "FC-1",                 ""},     SDEV_NOSTARTUNIT},           "TEAC", "FC-1",                 ""},     PQUIRK_NOSTARTUNIT},
   
         {{T_DIRECT, T_REMOV,  
          "Y-E DATA", "USB-FDU",          "3.04"}, SDEV_NOMODESENSE},  
         {{T_DIRECT, T_REMOV,          {{T_DIRECT, T_REMOV,
          "TEAC", "FD-05PUB",             "1026"}, SDEV_NOMODESENSE},           "INSITE", "I325VM",             ""},
                                   PQUIRK_NOLUNS|PQUIRK_NODOORLOCK},
   
         /* XXX: QIC-36 tape behind Emulex adapter.  Very broken. */          /* XXX: QIC-36 tape behind Emulex adapter.  Very broken. */
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "        ", "                ", "    "}, SDEV_NOLUNS},           "        ", "                ", "    "}, PQUIRK_NOLUNS},
           {{T_SEQUENTIAL, T_REMOV,
            "EMULEX  ", "MT-02 QIC       ", ""},     PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "CALIPER ", "CP150           ", ""},     SDEV_NOLUNS},           "CALIPER ", "CP150           ", ""},     PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "EXABYTE ", "EXB-8200        ", ""},     SDEV_NOLUNS},           "EXABYTE ", "EXB-8200        ", ""},     PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "SONY    ", "GY-10C          ", ""},     SDEV_NOLUNS},           "SONY    ", "GY-10C          ", ""},     PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "SONY    ", "SDT-2000        ", "2.09"}, SDEV_NOLUNS},           "SONY    ", "SDT-2000        ", "2.09"}, PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "SONY    ", "SDT-5000        ", "3."},   SDEV_NOSYNC|SDEV_NOWIDE},           "SONY    ", "SDT-5000        ", "3."},   PQUIRK_NOSYNC|PQUIRK_NOWIDE},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "SONY    ", "SDT-5200        ", "3."},   SDEV_NOLUNS},           "SONY    ", "SDT-5200        ", "3."},   PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "TANDBERG", " TDC 3600       ", ""},     SDEV_NOLUNS},           "TANDBERG", " TDC 3600       ", ""},     PQUIRK_NOLUNS},
         /* Following entry reported as a Tandberg 3600; ref. PR1933 */          /* Following entry reported as a Tandberg 3600; ref. PR1933 */
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "ARCHIVE ", "VIPER 150  21247", ""},     SDEV_NOLUNS},           "ARCHIVE ", "VIPER 150  21247", ""},     PQUIRK_NOLUNS},
         /* Following entry for a Cipher ST150S; ref. PR4171 */          /* Following entry for a Cipher ST150S; ref. PR4171 */
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "ARCHIVE ", "VIPER 1500 21247", "2.2G"}, SDEV_NOLUNS},           "ARCHIVE ", "VIPER 1500 21247", "2.2G"}, PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "ARCHIVE ", "Python 28454-XXX", ""},     SDEV_NOLUNS},           "ARCHIVE ", "Python 28454-XXX", ""},     PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "WANGTEK ", "5099ES SCSI",      ""},     SDEV_NOLUNS},           "WANGTEK ", "5099ES SCSI",      ""},     PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "WANGTEK ", "5150ES SCSI",      ""},     SDEV_NOLUNS},           "WANGTEK ", "5150ES SCSI",      ""},     PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "WANGTEK ", "SCSI-36",          ""},     SDEV_NOLUNS},           "WANGTEK ", "SCSI-36",          ""},     PQUIRK_NOLUNS},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "WangDAT ", "Model 1300      ", "02.4"}, SDEV_NOSYNC|SDEV_NOWIDE},           "WangDAT ", "Model 1300      ", "02.4"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "WangDAT ", "Model 2600      ", "01.7"}, SDEV_NOSYNC|SDEV_NOWIDE},           "WangDAT ", "Model 2600      ", "01.7"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "WangDAT ", "Model 3200      ", "02.2"}, SDEV_NOSYNC|SDEV_NOWIDE},           "WangDAT ", "Model 3200      ", "02.2"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
         {{T_SEQUENTIAL, T_REMOV,          {{T_SEQUENTIAL, T_REMOV,
          "TEAC    ", "MT-2ST/N50      ", ""},     SDEV_NOLUNS},           "TEAC    ", "MT-2ST/N50      ", ""},     PQUIRK_NOLUNS},
   
         {{T_SCANNER, T_FIXED,          {{T_SCANNER, T_FIXED,
          "RICOH   ", "IS60            ", "1R08"}, SDEV_NOLUNS},           "RICOH   ", "IS60            ", "1R08"}, PQUIRK_NOLUNS},
         {{T_SCANNER, T_FIXED,          {{T_SCANNER, T_FIXED,
          "UMAX    ", "Astra 1200S     ", "V2.9"}, SDEV_NOLUNS},           "UMAX    ", "Astra 1200S     ", "V2.9"}, PQUIRK_NOLUNS},
         {{T_SCANNER, T_FIXED,          {{T_SCANNER, T_FIXED,
          "UMAX    ", "Astra 1220S     ", ""}, SDEV_NOLUNS},           "UMAX    ", "Astra 1220S     ", ""},     PQUIRK_NOLUNS},
         {{T_SCANNER, T_FIXED,          {{T_SCANNER, T_FIXED,
          "UMAX    ", "UMAX S-6E       ", "V2.0"}, SDEV_NOLUNS},           "UMAX    ", "UMAX S-6E       ", "V2.0"}, PQUIRK_NOLUNS},
         {{T_SCANNER, T_FIXED,          {{T_SCANNER, T_FIXED,
          "UMAX    ", "UMAX S-12       ", "V2.1"}, SDEV_NOLUNS},           "UMAX    ", "UMAX S-12       ", "V2.1"}, PQUIRK_NOLUNS},
         {{T_SCANNER, T_FIXED,          {{T_SCANNER, T_FIXED,
          "ULTIMA  ", "A6000C          ", ""}, SDEV_NOLUNS},           "ULTIMA  ", "A6000C          ", ""},     PQUIRK_NOLUNS},
         {{T_PROCESSOR, T_FIXED,          {{T_PROCESSOR, T_FIXED,
          "SYMBIOS", "", ""},     SDEV_NOLUNS},           "SYMBIOS",  "",                 ""},     PQUIRK_NOLUNS},
         {{T_PROCESSOR, T_FIXED,          {{T_PROCESSOR, T_FIXED,
          "LITRONIC", "PCMCIA          ", ""},     SDEV_NOLUNS},           "LITRONIC", "PCMCIA          ", ""},     PQUIRK_NOLUNS},
         {{T_CHANGER, T_REMOV,          {{T_CHANGER, T_REMOV,
          "SONY    ", "CDL1100         ", ""},     SDEV_NOLUNS},           "SONY    ", "CDL1100         ", ""},     PQUIRK_NOLUNS},
         {{T_ENCLOSURE, T_FIXED,          {{T_ENCLOSURE, T_FIXED,
          "SUN     ", "SENA            ", ""},     SDEV_NOLUNS},           "SUN     ", "SENA            ", ""},     PQUIRK_NOLUNS},
 };  };
   
 /*  /*
Line 688  const struct scsi_quirk_inquiry_pattern 
Line 701  const struct scsi_quirk_inquiry_pattern 
  * entry.   * entry.
  */   */
 int  int
 scsi_probedev(scsi, target, lun)  scsi_probe_device(sc, target, lun)
         struct scsibus_softc *scsi;          struct scsibus_softc *sc;
         int target, lun;          int target, lun;
 {  {
         struct scsipi_link *sc_link;          struct scsipi_channel *chan = sc->sc_channel;
           struct scsipi_periph *periph;
         struct scsipi_inquiry_data inqbuf;          struct scsipi_inquiry_data inqbuf;
         struct scsi_quirk_inquiry_pattern *finger;          struct scsi_quirk_inquiry_pattern *finger;
         int checkdtype, priority, docontinue;          int checkdtype, priority, docontinue, quirks;
         struct scsipibus_attach_args sa;          struct scsipibus_attach_args sa;
         struct cfdata *cf;          struct cfdata *cf;
   
Line 708  scsi_probedev(scsi, target, lun)
Line 722  scsi_probedev(scsi, target, lun)
         docontinue = 0;          docontinue = 0;
   
         /* Skip this slot if it is already attached. */          /* Skip this slot if it is already attached. */
         if (scsi->sc_link[target][lun] != NULL)          if (scsipi_lookup_periph(chan, target, lun) != NULL)
                 return (docontinue);                  return (docontinue);
   
         sc_link = malloc(sizeof(*sc_link), M_DEVBUF, M_NOWAIT);          periph = scsipi_alloc_periph(M_NOWAIT);
         *sc_link = *scsi->adapter_link;          if (periph == NULL) {
         sc_link->active = 0;  #ifdef  DIAGNOSTIC
         sc_link->scsipi_scsi.target = target;                  printf("%s: cannot allocate periph for target %d lun %d\n",
         sc_link->scsipi_scsi.lun = lun;                      sc->sc_dev.dv_xname, target, lun);
         sc_link->device = &probe_switch;  #endif
         TAILQ_INIT(&sc_link->pending_xfers);                  return (ENOMEM);
           }
           periph->periph_channel = chan;
           periph->periph_switch = &scsi_probe_dev;
   
           periph->periph_target = target;
           periph->periph_lun = lun;
           periph->periph_quirks = chan->chan_defquirks;
   
   #ifdef SCSIPI_DEBUG
           if (SCSIPI_DEBUG_TYPE == SCSIPI_BUSTYPE_SCSI &&
               SCSIPI_DEBUG_TARGET == target &&
               SCSIPI_DEBUG_LUN == lun)
                   periph->periph_dbflags |= SCSIPI_DEBUG_FLAGS;
   #endif
   
         /*          /*
          * Ask the device what it is           * Ask the device what it is
          */           */
 #if defined(SCSIDEBUG) && DEBUGTYPE == BUS_SCSI          (void) scsipi_test_unit_ready(periph,
         if (target == DEBUGTARGET && lun == DEBUGLUN)  
                 sc_link->flags |= DEBUGLEVEL;  
 #endif /* SCSIDEBUG */  
   
         (void) scsipi_test_unit_ready(sc_link,  
             XS_CTL_DISCOVERY | XS_CTL_IGNORE_ILLEGAL_REQUEST |              XS_CTL_DISCOVERY | XS_CTL_IGNORE_ILLEGAL_REQUEST |
             XS_CTL_IGNORE_NOT_READY | XS_CTL_IGNORE_MEDIA_CHANGE);              XS_CTL_IGNORE_NOT_READY | XS_CTL_IGNORE_MEDIA_CHANGE);
   
 #ifdef SCSI_2_DEF  #ifdef SCSI_2_DEF
         /* some devices need to be told to go to SCSI2 */          /* some devices need to be told to go to SCSI2 */
         /* However some just explode if you tell them this.. leave it out */          /* However some just explode if you tell them this.. leave it out */
         scsi_change_def(sc_link, XS_CTL_DISCOVERY | XS_CTL_SILENT);          scsi_change_def(periph, XS_CTL_DISCOVERY | XS_CTL_SILENT);
 #endif /* SCSI_2_DEF */  #endif /* SCSI_2_DEF */
   
         /* Now go ask the device all about itself. */          /* Now go ask the device all about itself. */
         bzero(&inqbuf, sizeof(inqbuf));          memset(&inqbuf, 0, sizeof(inqbuf));
         if (scsipi_inquire(sc_link, &inqbuf,          if (scsipi_inquire(periph, &inqbuf,
             XS_CTL_DISCOVERY | XS_CTL_DATA_ONSTACK) != 0)              XS_CTL_DISCOVERY | XS_CTL_DATA_ONSTACK) != 0)
                 goto bad;                  goto bad;
   
         {          {
                 u_int8_t *extension = &inqbuf.flags1;                  u_int8_t *extension = &inqbuf.flags1;
                 int len = inqbuf.additional_length;                  int len = inqbuf.additional_length;
Line 760  scsi_probedev(scsi, target, lun)
Line 782  scsi_probedev(scsi, target, lun)
                         extension[len++] = ' ';                          extension[len++] = ' ';
         }          }
   
         sa.sa_sc_link = sc_link;          periph->periph_type = inqbuf.device & SID_TYPE;
         sa.sa_inqbuf.type = inqbuf.device;          if (inqbuf.dev_qual2 & SID_REMOVABLE)
         sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ?                  periph->periph_flags |= PERIPH_REMOVABLE;
             T_REMOV : T_FIXED;          periph->periph_version = inqbuf.version & SID_ANSII;
         sa.sa_inqbuf.vendor = inqbuf.vendor;  
         sa.sa_inqbuf.product = inqbuf.product;  
         sa.sa_inqbuf.revision = inqbuf.revision;  
         sa.scsipi_info.scsi_version = inqbuf.version;  
         sa.sa_inqptr = &inqbuf;  
   
         finger = (struct scsi_quirk_inquiry_pattern *)scsipi_inqmatch(  
             &sa.sa_inqbuf, (caddr_t)scsi_quirk_patterns,  
             sizeof(scsi_quirk_patterns)/sizeof(scsi_quirk_patterns[0]),  
             sizeof(scsi_quirk_patterns[0]), &priority);  
   
         /*  
          * Based upon the inquiry flags we got back, and if we're  
          * at SCSI-2 or better, set some limiting quirks.  
          */  
         if ((inqbuf.version & SID_ANSII) >= 2) {  
                 if ((inqbuf.flags3 & SID_CmdQue) == 0)  
                         sc_link->quirks |= SDEV_NOTAG;  
                 if ((inqbuf.flags3 & SID_Sync) == 0)  
                         sc_link->quirks |= SDEV_NOSYNC;  
                 if ((inqbuf.flags3 & SID_WBus16) == 0)  
                         sc_link->quirks |= SDEV_NOWIDE;  
         } else {  
                 /*  
                  * Turn off command tagging for SCSI 1 devices.  
                  * If the need arises, we could define a `SDEV_FORCETAG'  
                  * quirk and set it for pre-SCSI2 devices that actually  
                  * do support tagged commands.  
                  */  
                 sc_link->quirks |= SDEV_NOTAG;  
         }  
   
         /*  
          * Now apply any quirks from the table.  
          */  
         if (priority != 0)  
                 sc_link->quirks |= finger->quirks;  
         if ((inqbuf.version & SID_ANSII) == 0 &&  
             (sc_link->quirks & SDEV_FORCELUNS) == 0)  
                 sc_link->quirks |= SDEV_NOLUNS;  
         sc_link->scsipi_scsi.scsi_version = inqbuf.version;  
   
         if (sc_link->quirks & SDEV_CDROM) {  
                 sc_link->quirks ^= SDEV_CDROM;  
                 inqbuf.dev_qual2 |= SID_REMOVABLE;  
                 sa.sa_inqbuf.type = inqbuf.device = ((inqbuf.device & ~SID_REMOVABLE) | T_CDROM);  
                 sa.sa_inqbuf.removable = T_REMOV;  
   
         }  
   
         if ((sc_link->quirks & SDEV_NOLUNS) == 0)  
                 docontinue = 1;  
   
         /*  
          * note what BASIC type of device it is  
          */  
         if ((inqbuf.dev_qual2 & SID_REMOVABLE) != 0)  
                 sc_link->flags |= SDEV_REMOVABLE;  
   
         /*          /*
          * Any device qualifier that has the top bit set (qualifier&4 != 0)           * Any device qualifier that has the top bit set (qualifier&4 != 0)
Line 830  scsi_probedev(scsi, target, lun)
Line 794  scsi_probedev(scsi, target, lun)
          */           */
         checkdtype = 0;          checkdtype = 0;
         switch (inqbuf.device & SID_QUAL) {          switch (inqbuf.device & SID_QUAL) {
         case SID_QUAL_LU_OK:          case SID_QUAL_LU_PRESENT:
         case SID_QUAL_LU_OFFLINE:          case SID_QUAL_LU_NOTPRESENT:
                 checkdtype = 1;                  checkdtype = 1;
                 break;                  break;
   
         case SID_QUAL_RSVD:          case SID_QUAL_reserved:
         case SID_QUAL_BAD_LU:          case SID_QUAL_LU_NOT_SUPP:
                 goto bad;                  goto bad;
   
         default:          default:
Line 844  scsi_probedev(scsi, target, lun)
Line 808  scsi_probedev(scsi, target, lun)
         }          }
   
         /* Let the adapter driver handle the device separatley if it wants. */          /* Let the adapter driver handle the device separatley if it wants. */
         if (sc_link->adapter->scsipi_accesschk != NULL &&          if (chan->chan_adapter->adapt_accesschk != NULL &&
             (*sc_link->adapter->scsipi_accesschk)(sc_link, &sa.sa_inqbuf))              (*chan->chan_adapter->adapt_accesschk)(periph, &sa.sa_inqbuf))
                 goto bad;                  goto bad;
   
         if (checkdtype) {          if (checkdtype) {
                 switch (inqbuf.device & SID_TYPE) {                  switch (periph->periph_type) {
                 case T_DIRECT:                  case T_DIRECT:
                 case T_SEQUENTIAL:                  case T_SEQUENTIAL:
                 case T_PRINTER:                  case T_PRINTER:
Line 872  scsi_probedev(scsi, target, lun)
Line 836  scsi_probedev(scsi, target, lun)
                 case T_NODEVICE:                  case T_NODEVICE:
                         goto bad;                          goto bad;
                 }                  }
                 /*          }
                  * At this point we can also tell the adapter that it  
                  * may negotiate things as appropriate.          sa.sa_periph = periph;
                  */          sa.sa_inqbuf.type = inqbuf.device;
                 if (sc_link->adapter->scsipi_ioctl) {          sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ?
                         struct scbusaccel_args s;              T_REMOV : T_FIXED;
                         s.sa_target = target;          sa.sa_inqbuf.vendor = inqbuf.vendor;
                         s.sa_lun = lun;          sa.sa_inqbuf.product = inqbuf.product;
                         s.sa_flags = 0;          sa.sa_inqbuf.revision = inqbuf.revision;
                         if ((sc_link->quirks & SDEV_NOTAG) == 0)          sa.scsipi_info.scsi_version = inqbuf.version;
                                 s.sa_flags |= SC_ACCEL_TAGS;          sa.sa_inqptr = &inqbuf;
                         if ((sc_link->quirks & SDEV_NOSYNC) == 0)  
                                 s.sa_flags |= SC_ACCEL_SYNC;          finger = (struct scsi_quirk_inquiry_pattern *)scsipi_inqmatch(
                         if ((sc_link->quirks & SDEV_NOWIDE) == 0)              &sa.sa_inqbuf, (caddr_t)scsi_quirk_patterns,
                                 s.sa_flags |= SC_ACCEL_WIDE;              sizeof(scsi_quirk_patterns)/sizeof(scsi_quirk_patterns[0]),
                         (void) (*sc_link->adapter->scsipi_ioctl)              sizeof(scsi_quirk_patterns[0]), &priority);
                             (sc_link, SCBUSACCEL, (caddr_t)&s, FWRITE, curproc);  
           if (finger != NULL)
                   quirks = finger->quirks;
           else
                   quirks = 0;
   
           /*
            * Determine the operating mode capabilities of the device.
            */
           if (periph->periph_version >= 2) {
                   if ((inqbuf.flags3 & SID_CmdQue) != 0 &&
                       (quirks & PQUIRK_NOTAG) == 0)
                           periph->periph_cap |= PERIPH_CAP_TQING;
                   if ((inqbuf.flags3 & SID_Linked) != 0)
                           periph->periph_cap |= PERIPH_CAP_LINKCMDS;
                   if ((inqbuf.flags3 & SID_Sync) != 0 &&
                       (quirks & PQUIRK_NOSYNC) == 0)
                           periph->periph_cap |= PERIPH_CAP_SYNC;
                   if ((inqbuf.flags3 & SID_WBus16) != 0 &&
                       (quirks & PQUIRK_NOWIDE) == 0)
                           periph->periph_cap |= PERIPH_CAP_WIDE16;
                   if ((inqbuf.flags3 & SID_WBus32) != 0 &&
                       (quirks & PQUIRK_NOWIDE) == 0)
                           periph->periph_cap |= PERIPH_CAP_WIDE32;
                   if ((inqbuf.flags3 & SID_SftRe) != 0)
                           periph->periph_cap |= PERIPH_CAP_SFTRESET;
                   if ((inqbuf.flags3 & SID_RelAdr) != 0)
                           periph->periph_cap |= PERIPH_CAP_RELADR;
                   if (periph->periph_version >= 3) { /* SPC-2 */
                           /*
                            * Report ST clocking though CAP_WIDExx/CAP_SYNC.
                            * If the device only supports DT, clear these
                            * flags (DT implies SYNC and WIDE)
                            */
                           switch (inqbuf.flags4 & SID_Clocking) {
                           case SID_CLOCKING_DT_ONLY:
                                   periph->periph_cap &=
                                       ~(PERIPH_CAP_SYNC |
                                         PERIPH_CAP_WIDE16 |
                                         PERIPH_CAP_WIDE32);
                                   /* FALLTHOUGH */
                           case SID_CLOCKING_SD_DT:
                                   periph->periph_cap |= PERIPH_CAP_DT;
                                   break;
                           default: /* ST only or invalid */
                                   /* nothing to do */
                                   break;
                           }
                           if (inqbuf.flags4 & SID_IUS)
                                   periph->periph_cap |= PERIPH_CAP_IUS;
                           if (inqbuf.flags4 & SID_QAS)
                                   periph->periph_cap |= PERIPH_CAP_QAS;
                 }                  }
         }          }
           if (quirks & PQUIRK_CAP_SYNC)
                   periph->periph_cap |= PERIPH_CAP_SYNC;
           if (quirks & PQUIRK_CAP_WIDE16)
                   periph->periph_cap |= PERIPH_CAP_WIDE16;
   
           /*
            * Now apply any quirks from the table.
            */
           periph->periph_quirks |= quirks;
           if (periph->periph_version == 0 &&
               (periph->periph_quirks & PQUIRK_FORCELUNS) == 0)
                   periph->periph_quirks |= PQUIRK_NOLUNS;
   
           if (periph->periph_quirks & PQUIRK_CDROM) {
                   periph->periph_quirks ^= PQUIRK_CDROM;
                   inqbuf.dev_qual2 |= SID_REMOVABLE;
                   sa.sa_inqbuf.type = inqbuf.device =
                       ((inqbuf.device & ~SID_REMOVABLE) | T_CDROM);
                   sa.sa_inqbuf.removable = T_REMOV;
           }
   
           if ((periph->periph_quirks & PQUIRK_NOLUNS) == 0)
                   docontinue = 1;
   
         if ((cf = config_search(scsibussubmatch, (struct device *)scsi,          if ((cf = config_search(scsibussubmatch, &sc->sc_dev, &sa)) != NULL) {
             &sa)) != NULL) {                  scsipi_insert_periph(chan, periph);
                 scsi->sc_link[target][lun] = sc_link;                  /*
                 config_attach((struct device *)scsi, cf, &sa, scsibusprint);                   * XXX Can't assign periph_dev here, because we'll
                    * XXX need it before config_attach() returns.  Must
                    * XXX assign it in periph driver.
                    */
                   (void) config_attach(&sc->sc_dev, cf, &sa, scsibusprint);
         } else {          } else {
                 scsibusprint(&sa, scsi->sc_dev.dv_xname);                  scsibusprint(&sa, sc->sc_dev.dv_xname);
                 printf(" not configured\n");                  printf(" not configured\n");
                 goto bad;                  goto bad;
         }          }
Line 905  scsi_probedev(scsi, target, lun)
Line 947  scsi_probedev(scsi, target, lun)
         return (docontinue);          return (docontinue);
   
 bad:  bad:
         free(sc_link, M_DEVBUF);          free(periph, M_DEVBUF);
         return (docontinue);          return (docontinue);
 }  }
   
Line 927  scsibusopen(dev, flag, fmt, p)
Line 969  scsibusopen(dev, flag, fmt, p)
         if (sc->sc_flags & SCSIBUSF_OPEN)          if (sc->sc_flags & SCSIBUSF_OPEN)
                 return (EBUSY);                  return (EBUSY);
   
         if ((error = scsipi_adapter_addref(sc->adapter_link)) != 0)          if ((error = scsipi_adapter_addref(sc->sc_channel->chan_adapter)) != 0)
                 return (error);                  return (error);
   
         sc->sc_flags |= SCSIBUSF_OPEN;          sc->sc_flags |= SCSIBUSF_OPEN;
Line 943  scsibusclose(dev, flag, fmt, p)
Line 985  scsibusclose(dev, flag, fmt, p)
 {  {
         struct scsibus_softc *sc = scsibus_cd.cd_devs[minor(dev)];          struct scsibus_softc *sc = scsibus_cd.cd_devs[minor(dev)];
   
         scsipi_adapter_delref(sc->adapter_link);          scsipi_adapter_delref(sc->sc_channel->chan_adapter);
   
         sc->sc_flags &= ~SCSIBUSF_OPEN;          sc->sc_flags &= ~SCSIBUSF_OPEN;
   
Line 959  scsibusioctl(dev, cmd, addr, flag, p)
Line 1001  scsibusioctl(dev, cmd, addr, flag, p)
         struct proc *p;          struct proc *p;
 {  {
         struct scsibus_softc *sc = scsibus_cd.cd_devs[minor(dev)];          struct scsibus_softc *sc = scsibus_cd.cd_devs[minor(dev)];
         struct scsipi_link *sc_link = sc->adapter_link;          struct scsipi_channel *chan = sc->sc_channel;
         int error;          int error;
   
         /*          /*
Line 969  scsibusioctl(dev, cmd, addr, flag, p)
Line 1011  scsibusioctl(dev, cmd, addr, flag, p)
          */           */
         switch (cmd) {          switch (cmd) {
         case SCBUSIOSCAN:          case SCBUSIOSCAN:
           case SCBUSIODETACH:
         case SCBUSIORESET:          case SCBUSIORESET:
                 if ((flag & FWRITE) == 0)                  if ((flag & FWRITE) == 0)
                         return (EBADF);                          return (EBADF);
Line 980  scsibusioctl(dev, cmd, addr, flag, p)
Line 1023  scsibusioctl(dev, cmd, addr, flag, p)
                 struct scbusioscan_args *a =                  struct scbusioscan_args *a =
                     (struct scbusioscan_args *)addr;                      (struct scbusioscan_args *)addr;
   
                 /* XXX Change interface to this function. */                  error = scsi_probe_bus(sc, a->sa_target, a->sa_lun);
                 error = scsi_probe_busses(minor(dev), a->sa_target,  
                     a->sa_lun);  
                 break;                  break;
             }              }
   
           case SCBUSIODETACH:
               {
                   struct scbusiodetach_args *a =
                       (struct scbusiodetach_args *)addr;
   
                   error = scsipi_target_detach(chan, a->sa_target, a->sa_lun, 0);
                   break;
               }
   
   
         case SCBUSIORESET:          case SCBUSIORESET:
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
         default:          default:
                 if (sc_link->adapter->scsipi_ioctl == NULL)                  if (chan->chan_adapter->adapt_ioctl == NULL)
                         error = ENOTTY;                          error = ENOTTY;
                 else                  else
                         error = (*sc_link->adapter->scsipi_ioctl)(sc_link,                          error = (*chan->chan_adapter->adapt_ioctl)(chan,
                             cmd, addr, flag, p);                              cmd, addr, flag, p);
                 break;                  break;
         }          }

Legend:
Removed from v.1.156  
changed lines
  Added in v.1.156.2.21

CVSweb <webmaster@jp.NetBSD.org>