The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/scsipi/scsiconf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: scsiconf.c,v 1.250 2008/07/16 18:50:58 drochner Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1998, 1999, 2004 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
    9  * Simulation Facility, NASA Ames Research Center.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  * POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Originally written by Julian Elischer (julian@tfs.com)
   35  * for TRW Financial Systems for use under the MACH(2.5) operating system.
   36  *
   37  * TRW Financial Systems, in accordance with their agreement with Carnegie
   38  * Mellon University, makes this software available to CMU to distribute
   39  * or use in any manner that they see fit as long as this message is kept with
   40  * the software. For this reason TFS also grants any other persons or
   41  * organisations permission to use or modify this software.
   42  *
   43  * TFS supplies this software to be publicly redistributed
   44  * on the understanding that TFS is not responsible for the correct
   45  * functioning of this software in any circumstances.
   46  *
   47  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
   48  */
   49 
   50 #include <sys/cdefs.h>
   51 __KERNEL_RCSID(0, "$NetBSD: scsiconf.c,v 1.250 2008/07/16 18:50:58 drochner Exp $");
   52 
   53 #include <sys/param.h>
   54 #include <sys/systm.h>
   55 #include <sys/kernel.h>
   56 #include <sys/proc.h>
   57 #include <sys/kthread.h>
   58 #include <sys/malloc.h>
   59 #include <sys/device.h>
   60 #include <sys/conf.h>
   61 #include <sys/fcntl.h>
   62 #include <sys/scsiio.h>
   63 #include <sys/queue.h>
   64 #include <sys/simplelock.h>
   65 
   66 #include <dev/scsipi/scsi_all.h>
   67 #include <dev/scsipi/scsipi_all.h>
   68 #include <dev/scsipi/scsiconf.h>
   69 
   70 #include "locators.h"
   71 
   72 static const struct scsipi_periphsw scsi_probe_dev = {
   73         NULL,
   74         NULL,
   75         NULL,
   76         NULL,
   77 };
   78 
   79 struct scsi_initq {
   80         struct scsipi_channel *sc_channel;
   81         TAILQ_ENTRY(scsi_initq) scsi_initq;
   82 };
   83 
   84 static TAILQ_HEAD(, scsi_initq) scsi_initq_head =
   85     TAILQ_HEAD_INITIALIZER(scsi_initq_head);
   86 static struct simplelock scsibus_interlock = SIMPLELOCK_INITIALIZER;
   87 
   88 static int      scsi_probe_device(struct scsibus_softc *, int, int);
   89 
   90 static int      scsibusmatch(struct device *, struct cfdata *, void *);
   91 static void     scsibusattach(struct device *, struct device *, void *);
   92 static int      scsibusactivate(struct device *, enum devact);
   93 static int      scsibusdetach(struct device *, int flags);
   94 static int      scsibusrescan(struct device *, const char *, const int *);
   95 static void     scsidevdetached(struct device *, struct device *);
   96 
   97 CFATTACH_DECL2_NEW(scsibus, sizeof(struct scsibus_softc),
   98     scsibusmatch, scsibusattach, scsibusdetach, scsibusactivate,
   99     scsibusrescan, scsidevdetached);
  100 
  101 extern struct cfdriver scsibus_cd;
  102 
  103 static dev_type_open(scsibusopen);
  104 static dev_type_close(scsibusclose);
  105 static dev_type_ioctl(scsibusioctl);
  106 
  107 const struct cdevsw scsibus_cdevsw = {
  108         scsibusopen, scsibusclose, noread, nowrite, scsibusioctl,
  109         nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
  110 };
  111 
  112 static int      scsibusprint(void *, const char *);
  113 static void     scsibus_config(struct scsipi_channel *, void *);
  114 
  115 const struct scsipi_bustype scsi_bustype = {
  116         SCSIPI_BUSTYPE_SCSI,
  117         scsi_scsipi_cmd,
  118         scsipi_interpret_sense,
  119         scsi_print_addr,
  120         scsi_kill_pending,
  121 };
  122 
  123 int
  124 scsiprint(void *aux, const char *pnp)
  125 {
  126         struct scsipi_channel *chan = aux;
  127         struct scsipi_adapter *adapt = chan->chan_adapter;
  128 
  129         /* only "scsibus"es can attach to "scsi"s; easy. */
  130         if (pnp)
  131                 aprint_normal("scsibus at %s", pnp);
  132 
  133         /* don't print channel if the controller says there can be only one. */
  134         if (adapt->adapt_nchannels != 1)
  135                 aprint_normal(" channel %d", chan->chan_channel);
  136 
  137         return (UNCONF);
  138 }
  139 
  140 static int
  141 scsibusmatch(struct device *parent, struct cfdata *cf, void *aux)
  142 {
  143         struct scsipi_channel *chan = aux;
  144 
  145         if (chan->chan_bustype->bustype_type != SCSIPI_BUSTYPE_SCSI)
  146                 return 0;
  147 
  148         if (cf->cf_loc[SCSICF_CHANNEL] != chan->chan_channel &&
  149             cf->cf_loc[SCSICF_CHANNEL] != SCSICF_CHANNEL_DEFAULT)
  150                 return (0);
  151 
  152         return (1);
  153 }
  154 
  155 static void
  156 scsibusattach(struct device *parent, struct device *self, void *aux)
  157 {
  158         struct scsibus_softc *sc = device_private(self);
  159         struct scsipi_channel *chan = aux;
  160         struct scsi_initq *scsi_initq;
  161 
  162         if (!pmf_device_register(self, NULL, NULL))
  163                 aprint_error_dev(self, "couldn't establish power handler\n");
  164 
  165         sc->sc_dev = self;
  166         sc->sc_channel = chan;
  167         chan->chan_name = device_xname(sc->sc_dev);
  168 
  169         aprint_naive(": SCSI bus\n");
  170         aprint_normal(": %d target%s, %d lun%s per target\n",
  171             chan->chan_ntargets,
  172             chan->chan_ntargets == 1 ? "" : "s",
  173             chan->chan_nluns,
  174             chan->chan_nluns == 1 ? "" : "s");
  175 
  176         if (scsipi_adapter_addref(chan->chan_adapter))
  177                 return;
  178 
  179         /* Initialize the channel structure first */
  180         chan->chan_init_cb = scsibus_config;
  181         chan->chan_init_cb_arg = sc;
  182 
  183         scsi_initq = malloc(sizeof(struct scsi_initq), M_DEVBUF, M_WAITOK);
  184         scsi_initq->sc_channel = chan;
  185         TAILQ_INSERT_TAIL(&scsi_initq_head, scsi_initq, scsi_initq);
  186         config_pending_incr();
  187         if (scsipi_channel_init(chan)) {
  188                 aprint_error_dev(sc->sc_dev, "failed to init channel\n");
  189                 return;
  190         }
  191 }
  192 
  193 static void
  194 scsibus_config(struct scsipi_channel *chan, void *arg)
  195 {
  196         struct scsibus_softc *sc = arg;
  197         struct scsi_initq *scsi_initq;
  198 
  199 #ifndef SCSI_DELAY
  200 #define SCSI_DELAY 2
  201 #endif
  202         if ((chan->chan_flags & SCSIPI_CHAN_NOSETTLE) == 0 &&
  203             SCSI_DELAY > 0) {
  204                 aprint_normal_dev(sc->sc_dev,
  205                     "waiting %d seconds for devices to settle...\n",
  206                     SCSI_DELAY);
  207                 /* ...an identifier we know no one will use... */
  208                 (void) tsleep(scsibus_config, PRIBIO,
  209                     "scsidly", SCSI_DELAY * hz);
  210         }
  211 
  212         /* Make sure the devices probe in scsibus order to avoid jitter. */
  213         simple_lock(&scsibus_interlock);
  214         for (;;) {
  215                 scsi_initq = TAILQ_FIRST(&scsi_initq_head);
  216                 if (scsi_initq->sc_channel == chan)
  217                         break;
  218                 ltsleep(&scsi_initq_head, PRIBIO, "scsi_initq", 0,
  219                     &scsibus_interlock);
  220         }
  221 
  222         simple_unlock(&scsibus_interlock);
  223 
  224         scsi_probe_bus(sc, -1, -1);
  225 
  226         simple_lock(&scsibus_interlock);
  227         TAILQ_REMOVE(&scsi_initq_head, scsi_initq, scsi_initq);
  228         simple_unlock(&scsibus_interlock);
  229 
  230         free(scsi_initq, M_DEVBUF);
  231         wakeup(&scsi_initq_head);
  232 
  233         scsipi_adapter_delref(chan->chan_adapter);
  234 
  235         config_pending_decr();
  236 }
  237 
  238 static int
  239 scsibusactivate(struct device *self, enum devact act)
  240 {
  241         struct scsibus_softc *sc = device_private(self);
  242         struct scsipi_channel *chan = sc->sc_channel;
  243         struct scsipi_periph *periph;
  244         int target, lun, error = 0, s;
  245 
  246         s = splbio();
  247         switch (act) {
  248         case DVACT_ACTIVATE:
  249                 error = EOPNOTSUPP;
  250                 break;
  251 
  252         case DVACT_DEACTIVATE:
  253                 for (target = 0; target < chan->chan_ntargets;
  254                      target++) {
  255                         if (target == chan->chan_id)
  256                                 continue;
  257                         for (lun = 0; lun < chan->chan_nluns; lun++) {
  258                                 periph = scsipi_lookup_periph(chan,
  259                                     target, lun);
  260                                 if (periph == NULL)
  261                                         continue;
  262                                 error = config_deactivate(periph->periph_dev);
  263                                 if (error)
  264                                         goto out;
  265                         }
  266                 }
  267                 break;
  268         }
  269  out:
  270         splx(s);
  271         return (error);
  272 }
  273 
  274 static int
  275 scsibusdetach(struct device *self, int flags)
  276 {
  277         struct scsibus_softc *sc = device_private(self);
  278         struct scsipi_channel *chan = sc->sc_channel;
  279         struct scsipi_periph *periph;
  280         int ctarget, clun;
  281         struct scsipi_xfer *xs;
  282         int error;
  283 
  284         pmf_device_deregister(self);
  285 
  286         /*
  287          * Process outstanding commands (which will never complete as the
  288          * controller is gone).
  289          */
  290         for (ctarget = 0; ctarget < chan->chan_ntargets; ctarget++) {
  291                 if (ctarget == chan->chan_id)
  292                         continue;
  293                 for (clun = 0; clun < chan->chan_nluns; clun++) {
  294                         periph = scsipi_lookup_periph(chan, ctarget, clun);
  295                         if (periph == NULL)
  296                                 continue;
  297                         TAILQ_FOREACH(xs, &periph->periph_xferq, device_q) {
  298                                 callout_stop(&xs->xs_callout);
  299                                 xs->error = XS_DRIVER_STUFFUP;
  300                                 scsipi_done(xs);
  301                         }
  302                 }
  303         }
  304 
  305         /*
  306          * Detach all of the periphs.
  307          */
  308         error = scsipi_target_detach(chan, -1, -1, flags);
  309 
  310         /*
  311          * Now shut down the channel.
  312          * XXX only if no errors ?
  313          */
  314         scsipi_channel_shutdown(chan);
  315         return (error);
  316 }
  317 
  318 /*
  319  * Probe the requested scsi bus. It must be already set up.
  320  * target and lun optionally narrow the search if not -1
  321  */
  322 int
  323 scsi_probe_bus(struct scsibus_softc *sc, int target, int lun)
  324 {
  325         struct scsipi_channel *chan = sc->sc_channel;
  326         int maxtarget, mintarget, maxlun, minlun;
  327         int error;
  328 
  329         if (target == -1) {
  330                 maxtarget = chan->chan_ntargets - 1;
  331                 mintarget = 0;
  332         } else {
  333                 if (target < 0 || target >= chan->chan_ntargets)
  334                         return (EINVAL);
  335                 maxtarget = mintarget = target;
  336         }
  337 
  338         if (lun == -1) {
  339                 maxlun = chan->chan_nluns - 1;
  340                 minlun = 0;
  341         } else {
  342                 if (lun < 0 || lun >= chan->chan_nluns)
  343                         return (EINVAL);
  344                 maxlun = minlun = lun;
  345         }
  346 
  347         /*
  348          * Some HBAs provide an abstracted view of the bus; give them an
  349          * oppertunity to re-scan it before we do.
  350          */
  351         if (chan->chan_adapter->adapt_ioctl != NULL)
  352                 (*chan->chan_adapter->adapt_ioctl)(chan, SCBUSIOLLSCAN, NULL,
  353                     0, curproc);
  354 
  355         if ((error = scsipi_adapter_addref(chan->chan_adapter)) != 0)
  356                 return (error);
  357         for (target = mintarget; target <= maxtarget; target++) {
  358                 if (target == chan->chan_id)
  359                         continue;
  360                 for (lun = minlun; lun <= maxlun; lun++) {
  361                         /*
  362                          * See if there's a device present, and configure it.
  363                          */
  364                         if (scsi_probe_device(sc, target, lun) == 0)
  365                                 break;
  366                         /* otherwise something says we should look further */
  367                 }
  368 
  369                 /*
  370                  * Now that we've discovered all of the LUNs on this
  371                  * I_T Nexus, update the xfer mode for all of them
  372                  * that we know about.
  373                  */
  374                 scsipi_set_xfer_mode(chan, target, 1);
  375         }
  376         scsipi_adapter_delref(chan->chan_adapter);
  377         return (0);
  378 }
  379 
  380 static int
  381 scsibusrescan(struct device *sc, const char *ifattr,
  382     const int *locators)
  383 {
  384 
  385         KASSERT(ifattr && !strcmp(ifattr, "scsibus"));
  386         KASSERT(locators);
  387 
  388         return (scsi_probe_bus(device_private(sc),
  389                 locators[SCSIBUSCF_TARGET], locators[SCSIBUSCF_LUN]));
  390 }
  391 
  392 static void
  393 scsidevdetached(struct device *sc, struct device *dev)
  394 {
  395         struct scsibus_softc *ssc = device_private(sc);
  396         struct scsipi_channel *chan = ssc->sc_channel;
  397         struct scsipi_periph *periph;
  398         int target, lun;
  399 
  400         target = device_locator(dev, SCSIBUSCF_TARGET);
  401         lun = device_locator(dev, SCSIBUSCF_LUN);
  402 
  403         periph = scsipi_lookup_periph(chan, target, lun);
  404         KASSERT(periph->periph_dev == dev);
  405 
  406         scsipi_remove_periph(chan, periph);
  407         free(periph, M_DEVBUF);
  408 }
  409 
  410 /*
  411  * Print out autoconfiguration information for a subdevice.
  412  *
  413  * This is a slight abuse of 'standard' autoconfiguration semantics,
  414  * because 'print' functions don't normally print the colon and
  415  * device information.  However, in this case that's better than
  416  * either printing redundant information before the attach message,
  417  * or having the device driver call a special function to print out
  418  * the standard device information.
  419  */
  420 static int
  421 scsibusprint(void *aux, const char *pnp)
  422 {
  423         struct scsipibus_attach_args *sa = aux;
  424         struct scsipi_inquiry_pattern *inqbuf;
  425         u_int8_t type;
  426         const char *dtype;
  427         char vendor[33], product[65], revision[17];
  428         int target, lun;
  429 
  430         if (pnp != NULL)
  431                 aprint_normal("%s", pnp);
  432 
  433         inqbuf = &sa->sa_inqbuf;
  434 
  435         target = sa->sa_periph->periph_target;
  436         lun = sa->sa_periph->periph_lun;
  437         type = inqbuf->type & SID_TYPE;
  438 
  439         dtype = scsipi_dtype(type);
  440 
  441         scsipi_strvis(vendor, 33, inqbuf->vendor, 8);
  442         scsipi_strvis(product, 65, inqbuf->product, 16);
  443         scsipi_strvis(revision, 17, inqbuf->revision, 4);
  444 
  445         aprint_normal(" target %d lun %d: <%s, %s, %s> %s %s",
  446             target, lun, vendor, product, revision, dtype,
  447             inqbuf->removable ? "removable" : "fixed");
  448 
  449         return (UNCONF);
  450 }
  451 
  452 static const struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = {
  453         {{T_CDROM, T_REMOV,
  454          "CHINON  ", "CD-ROM CDS-431  ", ""},     PQUIRK_NOLUNS},
  455         {{T_CDROM, T_REMOV,
  456          "CHINON  ", "CD-ROM CDS-435  ", ""},     PQUIRK_NOLUNS},
  457         {{T_CDROM, T_REMOV,
  458          "Chinon  ", "CD-ROM CDS-525  ", ""},     PQUIRK_NOLUNS},
  459         {{T_CDROM, T_REMOV,
  460          "CHINON  ", "CD-ROM CDS-535  ", ""},     PQUIRK_NOLUNS},
  461         {{T_CDROM, T_REMOV,
  462          "DEC     ", "RRD42   (C) DEC ", ""},     PQUIRK_NOLUNS},
  463         {{T_CDROM, T_REMOV,
  464          "DENON   ", "DRD-25X         ", "V"},    PQUIRK_NOLUNS},
  465         {{T_CDROM, T_REMOV,
  466          "GENERIC ", "CRD-BP2         ", ""},     PQUIRK_NOLUNS},
  467         {{T_CDROM, T_REMOV,
  468          "HP      ", "C4324/C4325     ", ""},     PQUIRK_NOLUNS},
  469         {{T_CDROM, T_REMOV,
  470          "IMS     ", "CDD521/10       ", "2.06"}, PQUIRK_NOLUNS},
  471         {{T_CDROM, T_REMOV,
  472          "MATSHITA", "CD-ROM CR-5XX   ", "1.0b"}, PQUIRK_NOLUNS},
  473         {{T_CDROM, T_REMOV,
  474          "MEDAVIS ", "RENO CD-ROMX2A  ", ""},     PQUIRK_NOLUNS},
  475         {{T_CDROM, T_REMOV,
  476          "MEDIAVIS", "CDR-H93MV       ", "1.3"},  PQUIRK_NOLUNS},
  477         {{T_CDROM, T_REMOV,
  478          "NEC     ", "CD-ROM DRIVE:502", ""},     PQUIRK_NOLUNS},
  479         {{T_CDROM, T_REMOV,
  480          "NEC     ", "CD-ROM DRIVE:55 ", ""},     PQUIRK_NOLUNS},
  481         {{T_CDROM, T_REMOV,
  482          "NEC     ", "CD-ROM DRIVE:83 ", ""},     PQUIRK_NOLUNS},
  483         {{T_CDROM, T_REMOV,
  484          "NEC     ", "CD-ROM DRIVE:84 ", ""},     PQUIRK_NOLUNS},
  485         {{T_CDROM, T_REMOV,
  486          "NEC     ", "CD-ROM DRIVE:841", ""},     PQUIRK_NOLUNS},
  487         {{T_CDROM, T_REMOV,
  488          "OLYMPUS ", "CDS620E         ", "1.1d"},
  489                                PQUIRK_NOLUNS|PQUIRK_NOSYNC|PQUIRK_NOCAPACITY},
  490         {{T_CDROM, T_REMOV,
  491          "PIONEER ", "CD-ROM DR-124X  ", "1.01"}, PQUIRK_NOLUNS},
  492         {{T_CDROM, T_REMOV,
  493          "PLEXTOR ", "CD-ROM PX-4XCS  ", "1.01"},
  494                                PQUIRK_NOLUNS|PQUIRK_NOSYNC},
  495         {{T_CDROM, T_REMOV,
  496          "SONY    ", "CD-ROM CDU-541  ", ""},     PQUIRK_NOLUNS},
  497         {{T_CDROM, T_REMOV,
  498          "SONY    ", "CD-ROM CDU-55S  ", ""},     PQUIRK_NOLUNS},
  499         {{T_CDROM, T_REMOV,
  500          "SONY    ", "CD-ROM CDU-561  ", ""},     PQUIRK_NOLUNS},
  501         {{T_CDROM, T_REMOV,
  502          "SONY    ", "CD-ROM CDU-76S", ""},
  503                                 PQUIRK_NOLUNS|PQUIRK_NOSYNC|PQUIRK_NOWIDE},
  504         {{T_CDROM, T_REMOV,
  505          "SONY    ", "CD-ROM CDU-8003A", ""},     PQUIRK_NOLUNS},
  506         {{T_CDROM, T_REMOV,
  507          "SONY    ", "CD-ROM CDU-8012 ", ""},     PQUIRK_NOLUNS},
  508         {{T_CDROM, T_REMOV,
  509          "TEAC    ", "CD-ROM          ", "1.06"}, PQUIRK_NOLUNS},
  510         {{T_CDROM, T_REMOV,
  511          "TEAC    ", "CD-ROM CD-56S   ", "1.0B"}, PQUIRK_NOLUNS},
  512         {{T_CDROM, T_REMOV,
  513          "TEXEL   ", "CD-ROM          ", "1.06"}, PQUIRK_NOLUNS},
  514         {{T_CDROM, T_REMOV,
  515          "TEXEL   ", "CD-ROM DM-XX24 K", "1.09"}, PQUIRK_NOLUNS},
  516         {{T_CDROM, T_REMOV,
  517          "TEXEL   ", "CD-ROM DM-XX24 K", "1.10"}, PQUIRK_NOLUNS},
  518         {{T_CDROM, T_REMOV,
  519          "TOSHIBA ", "XM-4101TASUNSLCD", ""}, PQUIRK_NOLUNS|PQUIRK_NOSYNC},
  520         /* "IBM CDRM00201     !F" 0724 is an IBM OEM Toshiba XM-4101BME */
  521         {{T_CDROM, T_REMOV,
  522          "IBM     ", "CDRM00201     !F", "0724"}, PQUIRK_NOLUNS|PQUIRK_NOSYNC},
  523         {{T_CDROM, T_REMOV,
  524          "ShinaKen", "CD-ROM DM-3x1S",   "1.04"}, PQUIRK_NOLUNS},
  525         {{T_CDROM, T_REMOV,
  526          "JVC     ", "R2626",            ""},     PQUIRK_NOLUNS},
  527         {{T_CDROM, T_REMOV,
  528          "YAMAHA", "CRW8424S",           ""},     PQUIRK_NOLUNS},
  529         {{T_CDROM, T_REMOV,
  530          "NEC     ", "CD-ROM DRIVE:222", ""},     PQUIRK_NOLUNS|PQUIRK_NOSYNC},
  531 
  532         {{T_DIRECT, T_FIXED,
  533          "MICROP  ", "1588-15MBSUN0669", ""},     PQUIRK_AUTOSAVE},
  534         {{T_DIRECT, T_FIXED,
  535          "MICROP  ", "2217-15MQ1091501", ""},     PQUIRK_NOSYNCCACHE},
  536         {{T_OPTICAL, T_REMOV,
  537          "EPSON   ", "OMD-5010        ", "3.08"}, PQUIRK_NOLUNS},
  538         {{T_DIRECT, T_FIXED,
  539          "ADAPTEC ", "AEC-4412BD",       "1.2A"}, PQUIRK_NOMODESENSE},
  540         {{T_DIRECT, T_FIXED,
  541          "ADAPTEC ", "ACB-4000",         ""},     PQUIRK_FORCELUNS|PQUIRK_AUTOSAVE|PQUIRK_NOMODESENSE},
  542         {{T_DIRECT, T_FIXED,
  543          "DEC     ", "RZ55     (C) DEC", ""},     PQUIRK_AUTOSAVE},
  544         {{T_DIRECT, T_FIXED,
  545          "EMULEX  ", "MD21/S2     ESDI", "A00"},
  546                                 PQUIRK_FORCELUNS|PQUIRK_AUTOSAVE},
  547         {{T_DIRECT, T_FIXED,
  548          "MICROP",  "1548-15MZ1077801",  "HZ2P"}, PQUIRK_NOTAG},
  549         {{T_DIRECT, T_FIXED,
  550          "HP      ", "C372",             ""},     PQUIRK_NOTAG},
  551         {{T_DIRECT, T_FIXED,
  552          "IBMRAID ", "0662S",            ""},     PQUIRK_AUTOSAVE},
  553         {{T_DIRECT, T_FIXED,
  554          "IBM     ", "0663H",            ""},     PQUIRK_AUTOSAVE},
  555         {{T_DIRECT, T_FIXED,
  556          "IBM",      "0664",             ""},     PQUIRK_AUTOSAVE},
  557         {{T_DIRECT, T_FIXED,
  558         /* improperly report DT-only sync mode */
  559          "IBM     ", "DXHS36D",          ""},
  560                                 PQUIRK_CAP_SYNC|PQUIRK_CAP_WIDE16},
  561         {{T_DIRECT, T_FIXED,
  562          "IBM     ", "DXHS18Y",          ""},
  563                                 PQUIRK_CAP_SYNC|PQUIRK_CAP_WIDE16},
  564         {{T_DIRECT, T_FIXED,
  565          "IBM     ", "H3171-S2",         ""},
  566                                 PQUIRK_NOLUNS|PQUIRK_AUTOSAVE},
  567         {{T_DIRECT, T_FIXED,
  568          "IBM     ", "KZ-C",             ""},     PQUIRK_AUTOSAVE},
  569         /* Broken IBM disk */
  570         {{T_DIRECT, T_FIXED,
  571          ""        , "DFRSS2F",          ""},     PQUIRK_AUTOSAVE},
  572         {{T_DIRECT, T_FIXED,
  573          "Initio  ", "",                 ""},     PQUIRK_NOBIGMODESENSE},
  574         {{T_DIRECT, T_REMOV,
  575          "MPL     ", "MC-DISK-        ", ""},     PQUIRK_NOLUNS},
  576         {{T_DIRECT, T_FIXED,
  577          "MAXTOR  ", "XT-3280         ", ""},     PQUIRK_NOLUNS},
  578         {{T_DIRECT, T_FIXED,
  579          "MAXTOR  ", "XT-4380S        ", ""},     PQUIRK_NOLUNS},
  580         {{T_DIRECT, T_FIXED,
  581          "MAXTOR  ", "MXT-1240S       ", ""},     PQUIRK_NOLUNS},
  582         {{T_DIRECT, T_FIXED,
  583          "MAXTOR  ", "XT-4170S        ", ""},     PQUIRK_NOLUNS},
  584         {{T_DIRECT, T_FIXED,
  585          "MAXTOR  ", "XT-8760S",         ""},     PQUIRK_NOLUNS},
  586         {{T_DIRECT, T_FIXED,
  587          "MAXTOR  ", "LXT-213S        ", ""},     PQUIRK_NOLUNS},
  588         {{T_DIRECT, T_FIXED,
  589          "MAXTOR  ", "LXT-213S SUN0207", ""},     PQUIRK_NOLUNS},
  590         {{T_DIRECT, T_FIXED,
  591          "MAXTOR  ", "LXT-200S        ", ""},     PQUIRK_NOLUNS},
  592         {{T_DIRECT, T_FIXED,
  593          "MEGADRV ", "EV1000",           ""},     PQUIRK_NOMODESENSE},
  594         {{T_DIRECT, T_FIXED,
  595          "MICROP", "1991-27MZ",          ""},     PQUIRK_NOTAG},
  596         {{T_DIRECT, T_FIXED,
  597          "MST     ", "SnapLink        ", ""},     PQUIRK_NOLUNS},
  598         {{T_DIRECT, T_FIXED,
  599          "NEC     ", "D3847           ", "0307"}, PQUIRK_NOLUNS},
  600         {{T_DIRECT, T_FIXED,
  601          "QUANTUM ", "ELS85S          ", ""},     PQUIRK_AUTOSAVE},
  602         {{T_DIRECT, T_FIXED,
  603          "QUANTUM ", "LPS525S         ", ""},     PQUIRK_NOLUNS},
  604         {{T_DIRECT, T_FIXED,
  605          "QUANTUM ", "P105S 910-10-94x", ""},     PQUIRK_NOLUNS},
  606         {{T_DIRECT, T_FIXED,
  607          "QUANTUM ", "PD1225S         ", ""},     PQUIRK_NOLUNS},
  608         {{T_DIRECT, T_FIXED,
  609          "QUANTUM ", "PD210S   SUN0207", ""},     PQUIRK_NOLUNS},
  610         {{T_DIRECT, T_FIXED,
  611          "QUANTUM ", "ATLAS IV 9 WLS", "0A0A"},   PQUIRK_CAP_NODT},
  612         {{T_DIRECT, T_FIXED,
  613          "RODIME  ", "RO3000S         ", ""},     PQUIRK_NOLUNS},
  614         {{T_DIRECT, T_FIXED,
  615          "SEAGATE ", "ST125N          ", ""},     PQUIRK_NOLUNS},
  616         {{T_DIRECT, T_FIXED,
  617          "SEAGATE ", "ST157N          ", ""},     PQUIRK_NOLUNS},
  618         {{T_DIRECT, T_FIXED,
  619          "SEAGATE ", "ST296           ", ""},     PQUIRK_NOLUNS},
  620         {{T_DIRECT, T_FIXED,
  621          "SEAGATE ", "ST296N          ", ""},     PQUIRK_NOLUNS},
  622         {{T_DIRECT, T_FIXED,
  623          "SEAGATE ", "ST318404LC      ", ""},     PQUIRK_NOLUNS},
  624         {{T_DIRECT, T_FIXED,
  625          "SEAGATE ", "ST15150N        ", ""},     PQUIRK_NOTAG},
  626         {{T_DIRECT, T_FIXED,
  627          "SEAGATE ", "ST19171",          ""},     PQUIRK_NOMODESENSE},
  628         {{T_DIRECT, T_FIXED,
  629          "SEAGATE ", "ST32430N",         ""},     PQUIRK_CAP_SYNC},
  630         {{T_DIRECT, T_FIXED,
  631          "SEAGATE ", "ST34501FC       ", ""},     PQUIRK_NOMODESENSE},
  632         {{T_DIRECT, T_FIXED,
  633          "SEAGATE ", "SX910800N",        ""},     PQUIRK_NOTAG},
  634         {{T_DIRECT, T_FIXED,
  635          "TOSHIBA ", "MK538FB         ", "6027"}, PQUIRK_NOLUNS},
  636         {{T_DIRECT, T_FIXED,
  637          "MICROP  ", "1924",          ""},     PQUIRK_CAP_SYNC},
  638         {{T_DIRECT, T_FIXED,
  639          "FUJITSU ", "M2266",         ""},     PQUIRK_CAP_SYNC},
  640         {{T_DIRECT, T_FIXED,
  641          "FUJITSU ", "M2624S-512      ", ""},     PQUIRK_CAP_SYNC},
  642         {{T_DIRECT, T_FIXED,
  643          "SEAGATE ", "SX336704LC"   , ""}, PQUIRK_CAP_SYNC | PQUIRK_CAP_WIDE16},
  644 
  645         {{T_DIRECT, T_REMOV,
  646          "IOMEGA", "ZIP 100",            "J.03"}, PQUIRK_NOLUNS},
  647         {{T_DIRECT, T_REMOV,
  648          "INSITE", "I325VM",             ""},     PQUIRK_NOLUNS},
  649 
  650         /* XXX: QIC-36 tape behind Emulex adapter.  Very broken. */
  651         {{T_SEQUENTIAL, T_REMOV,
  652          "        ", "                ", "    "}, PQUIRK_NOLUNS},
  653         {{T_SEQUENTIAL, T_REMOV,
  654          "EMULEX  ", "MT-02 QIC       ", ""},     PQUIRK_NOLUNS},
  655         {{T_SEQUENTIAL, T_REMOV,
  656          "CALIPER ", "CP150           ", ""},     PQUIRK_NOLUNS},
  657         {{T_SEQUENTIAL, T_REMOV,
  658          "EXABYTE ", "EXB-8200        ", ""},     PQUIRK_NOLUNS},
  659         {{T_SEQUENTIAL, T_REMOV,
  660          "SONY    ", "GY-10C          ", ""},     PQUIRK_NOLUNS},
  661         {{T_SEQUENTIAL, T_REMOV,
  662          "SONY    ", "SDT-2000        ", "2.09"}, PQUIRK_NOLUNS},
  663         {{T_SEQUENTIAL, T_REMOV,
  664          "SONY    ", "SDT-5000        ", "3."},   PQUIRK_NOSYNC|PQUIRK_NOWIDE},
  665         {{T_SEQUENTIAL, T_REMOV,
  666          "SONY    ", "SDT-5200        ", "3."},   PQUIRK_NOLUNS},
  667         {{T_SEQUENTIAL, T_REMOV,
  668          "TANDBERG", " TDC 3600       ", ""},     PQUIRK_NOLUNS},
  669         /* Following entry reported as a Tandberg 3600; ref. PR1933 */
  670         {{T_SEQUENTIAL, T_REMOV,
  671          "ARCHIVE ", "VIPER 150  21247", ""},     PQUIRK_NOLUNS},
  672         /* Following entry for a Cipher ST150S; ref. PR4171 */
  673         {{T_SEQUENTIAL, T_REMOV,
  674          "ARCHIVE ", "VIPER 1500 21247", "2.2G"}, PQUIRK_NOLUNS},
  675         {{T_SEQUENTIAL, T_REMOV,
  676          "ARCHIVE ", "Python 28454-XXX", ""},     PQUIRK_NOLUNS},
  677         {{T_SEQUENTIAL, T_REMOV,
  678          "WANGTEK ", "5099ES SCSI",      ""},     PQUIRK_NOLUNS},
  679         {{T_SEQUENTIAL, T_REMOV,
  680          "WANGTEK ", "5150ES SCSI",      ""},     PQUIRK_NOLUNS},
  681         {{T_SEQUENTIAL, T_REMOV,
  682          "WANGTEK ", "SCSI-36",          ""},     PQUIRK_NOLUNS},
  683         {{T_SEQUENTIAL, T_REMOV,
  684          "WangDAT ", "Model 1300      ", "02.4"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
  685         {{T_SEQUENTIAL, T_REMOV,
  686          "WangDAT ", "Model 2600      ", "01.7"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
  687         {{T_SEQUENTIAL, T_REMOV,
  688          "WangDAT ", "Model 3200      ", "02.2"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
  689         {{T_SEQUENTIAL, T_REMOV,
  690          "TEAC    ", "MT-2ST/N50      ", ""},     PQUIRK_NOLUNS},
  691 
  692         {{T_SCANNER, T_FIXED,
  693          "RICOH   ", "IS60            ", "1R08"}, PQUIRK_NOLUNS},
  694         {{T_SCANNER, T_FIXED,
  695          "UMAX    ", "Astra 1200S     ", "V2.9"}, PQUIRK_NOLUNS},
  696         {{T_SCANNER, T_FIXED,
  697          "UMAX    ", "Astra 1220S     ", ""},     PQUIRK_NOLUNS},
  698         {{T_SCANNER, T_FIXED,
  699          "UMAX    ", "UMAX S-6E       ", "V2.0"}, PQUIRK_NOLUNS},
  700         {{T_SCANNER, T_FIXED,
  701          "UMAX    ", "UMAX S-12       ", "V2.1"}, PQUIRK_NOLUNS},
  702         {{T_SCANNER, T_FIXED,
  703          "ULTIMA  ", "A6000C          ", ""},     PQUIRK_NOLUNS},
  704         {{T_PROCESSOR, T_FIXED,
  705          "ESG-SHV",  "SCA HSBP M15",     ""},     PQUIRK_NOLUNS},
  706         {{T_PROCESSOR, T_FIXED,
  707          "SYMBIOS",  "",                 ""},     PQUIRK_NOLUNS},
  708         {{T_PROCESSOR, T_FIXED,
  709          "LITRONIC", "PCMCIA          ", ""},     PQUIRK_NOLUNS},
  710         {{T_CHANGER, T_REMOV,
  711          "SONY    ", "CDL1100         ", ""},     PQUIRK_NOLUNS},
  712         {{T_ENCLOSURE, T_FIXED,
  713          "SUN     ", "SENA            ", ""},     PQUIRK_NOLUNS},
  714 };
  715 
  716 /*
  717  * given a target and lun, ask the device what
  718  * it is, and find the correct driver table
  719  * entry.
  720  */
  721 static int
  722 scsi_probe_device(struct scsibus_softc *sc, int target, int lun)
  723 {
  724         struct scsipi_channel *chan = sc->sc_channel;
  725         struct scsipi_periph *periph;
  726         struct scsipi_inquiry_data inqbuf;
  727         const struct scsi_quirk_inquiry_pattern *finger;
  728         int checkdtype, priority, docontinue, quirks;
  729         struct scsipibus_attach_args sa;
  730         struct cfdata *cf;
  731         int locs[SCSIBUSCF_NLOCS];
  732         struct device *chld;
  733 
  734         /*
  735          * Assume no more luns to search after this one.
  736          * If we successfully get Inquiry data and after
  737          * merging quirks we find we can probe for more
  738          * luns, we will.
  739          */
  740         docontinue = 0;
  741 
  742         /* Skip this slot if it is already attached. */
  743         if (scsipi_lookup_periph(chan, target, lun) != NULL)
  744                 return (docontinue);
  745 
  746         periph = scsipi_alloc_periph(M_NOWAIT);
  747         if (periph == NULL) {
  748 #ifdef  DIAGNOSTIC
  749                 aprint_error_dev(sc->sc_dev,
  750                     "cannot allocate periph for target %d lun %d\n",
  751                     target, lun);
  752 #endif
  753                 return (ENOMEM);
  754         }
  755         periph->periph_channel = chan;
  756         periph->periph_switch = &scsi_probe_dev;
  757 
  758         periph->periph_target = target;
  759         periph->periph_lun = lun;
  760         periph->periph_quirks = chan->chan_defquirks;
  761 
  762 #ifdef SCSIPI_DEBUG
  763         if (SCSIPI_DEBUG_TYPE == SCSIPI_BUSTYPE_SCSI &&
  764             SCSIPI_DEBUG_TARGET == target &&
  765             SCSIPI_DEBUG_LUN == lun)
  766                 periph->periph_dbflags |= SCSIPI_DEBUG_FLAGS;
  767 #endif
  768 
  769         /*
  770          * Ask the device what it is
  771          */
  772 
  773 #ifdef SCSI_2_DEF
  774         /* some devices need to be told to go to SCSI2 */
  775         /* However some just explode if you tell them this.. leave it out */
  776         scsi_change_def(periph, XS_CTL_DISCOVERY | XS_CTL_SILENT);
  777 #endif /* SCSI_2_DEF */
  778 
  779         /* Now go ask the device all about itself. */
  780         memset(&inqbuf, 0, sizeof(inqbuf));
  781         {
  782                 u_int8_t *extension = &inqbuf.flags1;
  783                 int len = 0;
  784                 while (len < 3)
  785                         extension[len++] = '\0';
  786                 while (len < 3 + 28)
  787                         extension[len++] = ' ';
  788                 while (len < 3 + 28 + 20)
  789                         extension[len++] = '\0';
  790                 while (len < 3 + 28 + 20 + 1)
  791                         extension[len++] = '\0';
  792                 while (len < 3 + 28 + 20 + 1 + 1)
  793                         extension[len++] = '\0';
  794                 while (len < 3 + 28 + 20 + 1 + 1 + (8*2))
  795                         extension[len++] = ' ';
  796         }
  797         if (scsipi_inquire(periph, &inqbuf,
  798             XS_CTL_DISCOVERY | XS_CTL_DATA_ONSTACK | XS_CTL_SILENT) != 0)
  799                 goto bad;
  800 
  801         periph->periph_type = inqbuf.device & SID_TYPE;
  802         if (inqbuf.dev_qual2 & SID_REMOVABLE)
  803                 periph->periph_flags |= PERIPH_REMOVABLE;
  804         periph->periph_version = inqbuf.version & SID_ANSII;
  805 
  806         /*
  807          * Any device qualifier that has the top bit set (qualifier&4 != 0)
  808          * is vendor specific and won't match in this switch.
  809          * All we do here is throw out bad/negative responses.
  810          */
  811         checkdtype = 0;
  812         switch (inqbuf.device & SID_QUAL) {
  813         case SID_QUAL_LU_PRESENT:
  814                 checkdtype = 1;
  815                 break;
  816 
  817         case SID_QUAL_LU_NOTPRESENT:
  818         case SID_QUAL_reserved:
  819         case SID_QUAL_LU_NOT_SUPP:
  820                 goto bad;
  821 
  822         default:
  823                 break;
  824         }
  825 
  826         /* Let the adapter driver handle the device separatley if it wants. */
  827         if (chan->chan_adapter->adapt_accesschk != NULL &&
  828             (*chan->chan_adapter->adapt_accesschk)(periph, &sa.sa_inqbuf))
  829                 goto bad;
  830 
  831         if (checkdtype) {
  832                 switch (periph->periph_type) {
  833                 case T_DIRECT:
  834                 case T_SEQUENTIAL:
  835                 case T_PRINTER:
  836                 case T_PROCESSOR:
  837                 case T_WORM:
  838                 case T_CDROM:
  839                 case T_SCANNER:
  840                 case T_OPTICAL:
  841                 case T_CHANGER:
  842                 case T_COMM:
  843                 case T_IT8_1:
  844                 case T_IT8_2:
  845                 case T_STORARRAY:
  846                 case T_ENCLOSURE:
  847                 case T_SIMPLE_DIRECT:
  848                 case T_OPTIC_CARD_RW:
  849                 case T_OBJECT_STORED:
  850                 default:
  851                         break;
  852                 case T_NODEVICE:
  853                         goto bad;
  854                 }
  855         }
  856 
  857         sa.sa_periph = periph;
  858         sa.sa_inqbuf.type = inqbuf.device;
  859         sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ?
  860             T_REMOV : T_FIXED;
  861         sa.sa_inqbuf.vendor = inqbuf.vendor;
  862         sa.sa_inqbuf.product = inqbuf.product;
  863         sa.sa_inqbuf.revision = inqbuf.revision;
  864         sa.scsipi_info.scsi_version = inqbuf.version;
  865         sa.sa_inqptr = &inqbuf;
  866 
  867         finger = scsipi_inqmatch(
  868             &sa.sa_inqbuf, scsi_quirk_patterns,
  869             sizeof(scsi_quirk_patterns)/sizeof(scsi_quirk_patterns[0]),
  870             sizeof(scsi_quirk_patterns[0]), &priority);
  871 
  872         if (finger != NULL)
  873                 quirks = finger->quirks;
  874         else
  875                 quirks = 0;
  876 
  877         /*
  878          * Determine the operating mode capabilities of the device.
  879          */
  880         if (periph->periph_version >= 2) {
  881                 if ((inqbuf.flags3 & SID_CmdQue) != 0 &&
  882                     (quirks & PQUIRK_NOTAG) == 0)
  883                         periph->periph_cap |= PERIPH_CAP_TQING;
  884                 if ((inqbuf.flags3 & SID_Linked) != 0)
  885                         periph->periph_cap |= PERIPH_CAP_LINKCMDS;
  886                 if ((inqbuf.flags3 & SID_Sync) != 0 &&
  887                     (quirks & PQUIRK_NOSYNC) == 0)
  888                         periph->periph_cap |= PERIPH_CAP_SYNC;
  889                 if ((inqbuf.flags3 & SID_WBus16) != 0 &&
  890                     (quirks & PQUIRK_NOWIDE) == 0)
  891                         periph->periph_cap |= PERIPH_CAP_WIDE16;
  892                 if ((inqbuf.flags3 & SID_WBus32) != 0 &&
  893                     (quirks & PQUIRK_NOWIDE) == 0)
  894                         periph->periph_cap |= PERIPH_CAP_WIDE32;
  895                 if ((inqbuf.flags3 & SID_SftRe) != 0)
  896                         periph->periph_cap |= PERIPH_CAP_SFTRESET;
  897                 if ((inqbuf.flags3 & SID_RelAdr) != 0)
  898                         periph->periph_cap |= PERIPH_CAP_RELADR;
  899                 /* SPC-2 */
  900                 if (periph->periph_version >= 3 &&
  901                     !(quirks & PQUIRK_CAP_NODT)){
  902                         /*
  903                          * Report ST clocking though CAP_WIDExx/CAP_SYNC.
  904                          * If the device only supports DT, clear these
  905                          * flags (DT implies SYNC and WIDE)
  906                          */
  907                         switch (inqbuf.flags4 & SID_Clocking) {
  908                         case SID_CLOCKING_DT_ONLY:
  909                                 periph->periph_cap &=
  910                                     ~(PERIPH_CAP_SYNC |
  911                                       PERIPH_CAP_WIDE16 |
  912                                       PERIPH_CAP_WIDE32);
  913                                 /* FALLTHROUGH */
  914                         case SID_CLOCKING_SD_DT:
  915                                 periph->periph_cap |= PERIPH_CAP_DT;
  916                                 break;
  917                         default: /* ST only or invalid */
  918                                 /* nothing to do */
  919                                 break;
  920                         }
  921                 }
  922                 if (periph->periph_version >= 3) {
  923                         if (inqbuf.flags4 & SID_IUS)
  924                                 periph->periph_cap |= PERIPH_CAP_IUS;
  925                         if (inqbuf.flags4 & SID_QAS)
  926                                 periph->periph_cap |= PERIPH_CAP_QAS;
  927                 }
  928         }
  929         if (quirks & PQUIRK_CAP_SYNC)
  930                 periph->periph_cap |= PERIPH_CAP_SYNC;
  931         if (quirks & PQUIRK_CAP_WIDE16)
  932                 periph->periph_cap |= PERIPH_CAP_WIDE16;
  933 
  934         /*
  935          * Now apply any quirks from the table.
  936          */
  937         periph->periph_quirks |= quirks;
  938         if (periph->periph_version == 0 &&
  939             (periph->periph_quirks & PQUIRK_FORCELUNS) == 0)
  940                 periph->periph_quirks |= PQUIRK_NOLUNS;
  941 
  942         if ((periph->periph_quirks & PQUIRK_NOLUNS) == 0)
  943                 docontinue = 1;
  944 
  945         locs[SCSIBUSCF_TARGET] = target;
  946         locs[SCSIBUSCF_LUN] = lun;
  947 
  948         if ((cf = config_search_loc(config_stdsubmatch, sc->sc_dev,
  949              "scsibus", locs, &sa)) != NULL) {
  950                 scsipi_insert_periph(chan, periph);
  951                 /*
  952                  * XXX Can't assign periph_dev here, because we'll
  953                  * XXX need it before config_attach() returns.  Must
  954                  * XXX assign it in periph driver.
  955                  */
  956                 chld = config_attach_loc(sc->sc_dev, cf, locs, &sa,
  957                                          scsibusprint);
  958         } else {
  959                 scsibusprint(&sa, device_xname(sc->sc_dev));
  960                 aprint_normal(" not configured\n");
  961                 goto bad;
  962         }
  963 
  964         return (docontinue);
  965 
  966 bad:
  967         free(periph, M_DEVBUF);
  968         return (docontinue);
  969 }
  970 
  971 /****** Entry points for user control of the SCSI bus. ******/
  972 
  973 static int
  974 scsibusopen(dev_t dev, int flag, int fmt,
  975     struct lwp *l)
  976 {
  977         struct scsibus_softc *sc;
  978         int error, unit = minor(dev);
  979 
  980         sc = device_lookup_private(&scsibus_cd, unit);
  981         if (sc == NULL)
  982                 return (ENXIO);
  983 
  984         if (sc->sc_flags & SCSIBUSF_OPEN)
  985                 return (EBUSY);
  986 
  987         if ((error = scsipi_adapter_addref(sc->sc_channel->chan_adapter)) != 0)
  988                 return (error);
  989 
  990         sc->sc_flags |= SCSIBUSF_OPEN;
  991 
  992         return (0);
  993 }
  994 
  995 static int
  996 scsibusclose(dev_t dev, int flag, int fmt,
  997     struct lwp *l)
  998 {
  999         struct scsibus_softc *sc;
 1000 
 1001         sc = device_lookup_private(&scsibus_cd, minor(dev));
 1002         scsipi_adapter_delref(sc->sc_channel->chan_adapter);
 1003 
 1004         sc->sc_flags &= ~SCSIBUSF_OPEN;
 1005 
 1006         return (0);
 1007 }
 1008 
 1009 static int
 1010 scsibusioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
 1011 {
 1012         struct scsibus_softc *sc;
 1013         struct scsipi_channel *chan;
 1014         int error;
 1015 
 1016         sc = device_lookup_private(&scsibus_cd, minor(dev));
 1017         chan = sc->sc_channel;
 1018 
 1019         /*
 1020          * Enforce write permission for ioctls that change the
 1021          * state of the bus.  Host adapter specific ioctls must
 1022          * be checked by the adapter driver.
 1023          */
 1024         switch (cmd) {
 1025         case SCBUSIOSCAN:
 1026         case SCBUSIODETACH:
 1027         case SCBUSIORESET:
 1028                 if ((flag & FWRITE) == 0)
 1029                         return (EBADF);
 1030         }
 1031 
 1032         switch (cmd) {
 1033         case SCBUSIOSCAN:
 1034             {
 1035                 struct scbusioscan_args *a =
 1036                     (struct scbusioscan_args *)addr;
 1037 
 1038                 error = scsi_probe_bus(sc, a->sa_target, a->sa_lun);
 1039                 break;
 1040             }
 1041 
 1042         case SCBUSIODETACH:
 1043             {
 1044                 struct scbusiodetach_args *a =
 1045                     (struct scbusiodetach_args *)addr;
 1046 
 1047                 error = scsipi_target_detach(chan, a->sa_target, a->sa_lun, 0);
 1048                 break;
 1049             }
 1050 
 1051 
 1052         case SCBUSIORESET:
 1053                 /* FALLTHROUGH */
 1054         default:
 1055                 if (chan->chan_adapter->adapt_ioctl == NULL)
 1056                         error = ENOTTY;
 1057                 else
 1058                         error = (*chan->chan_adapter->adapt_ioctl)(chan,
 1059                             cmd, addr, flag, l->l_proc);
 1060                 break;
 1061         }
 1062 
 1063         return (error);
 1064 }

Cache object: d9c2fabeff23018909b51be400ff2f91


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.