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

Cache object: c2926a791ee7ede764af1e04c8234d81


[ 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.