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

Cache object: bcd1d8474a87253ffb571113cb710614


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