root/scsi/scsiconf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. scsiprint
  2. scsibusmatch
  3. scsibusattach
  4. scsibusactivate
  5. scsibusdetach
  6. scsibussubmatch
  7. scsibus_bioctl
  8. scsi_probe_bus
  9. scsi_probe_target
  10. scsi_probe_lun
  11. scsi_detach_bus
  12. scsi_detach_target
  13. scsi_detach_lun
  14. scsi_strvis
  15. scsibusprint
  16. scsi_probedev
  17. scsi_inqmatch

    1 /*      $OpenBSD: scsiconf.c,v 1.125 2007/05/08 18:50:39 deraadt Exp $  */
    2 /*      $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $       */
    3 
    4 /*
    5  * Copyright (c) 1994 Charles Hannum.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Charles Hannum.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Originally written by Julian Elischer (julian@tfs.com)
   35  * for TRW Financial Systems for use under the MACH(2.5) operating system.
   36  *
   37  * TRW Financial Systems, in accordance with their agreement with Carnegie
   38  * Mellon University, makes this software available to CMU to distribute
   39  * or use in any manner that they see fit as long as this message is kept with
   40  * the software. For this reason TFS also grants any other persons or
   41  * organisations permission to use or modify this software.
   42  *
   43  * TFS supplies this software to be publicly redistributed
   44  * on the understanding that TFS is not responsible for the correct
   45  * functioning of this software in any circumstances.
   46  *
   47  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
   48  */
   49 
   50 #include "bio.h"
   51 
   52 #include <sys/types.h>
   53 #include <sys/param.h>
   54 #include <sys/systm.h>
   55 #include <sys/malloc.h>
   56 #include <sys/device.h>
   57 
   58 #include <scsi/scsi_all.h>
   59 #include <scsi/scsiconf.h>
   60 
   61 #if NBIO > 0
   62 #include <sys/ioctl.h>
   63 #include <sys/scsiio.h>
   64 #include <dev/biovar.h>
   65 #endif
   66 
   67 /*
   68  * Declarations
   69  */
   70 int     scsi_probedev(struct scsibus_softc *, int, int);
   71 
   72 struct scsi_device probe_switch = {
   73         NULL,
   74         NULL,
   75         NULL,
   76         NULL,
   77 };
   78 
   79 int     scsibusmatch(struct device *, void *, void *);
   80 void    scsibusattach(struct device *, struct device *, void *);
   81 int     scsibusactivate(struct device *, enum devact);
   82 int     scsibusdetach(struct device *, int);
   83 
   84 int     scsibussubmatch(struct device *, void *, void *);
   85 
   86 #if NBIO > 0
   87 int     scsibus_bioctl(struct device *, u_long, caddr_t);
   88 #endif
   89 
   90 struct cfattach scsibus_ca = {
   91         sizeof(struct scsibus_softc), scsibusmatch, scsibusattach,
   92         scsibusdetach, scsibusactivate
   93 };
   94 
   95 struct cfdriver scsibus_cd = {
   96         NULL, "scsibus", DV_DULL
   97 };
   98 
   99 #ifdef SCSIDEBUG
  100 int scsidebug_buses = SCSIDEBUG_BUSES;
  101 int scsidebug_targets = SCSIDEBUG_TARGETS;
  102 int scsidebug_luns = SCSIDEBUG_LUNS;
  103 int scsidebug_level = SCSIDEBUG_LEVEL;
  104 #endif
  105 
  106 int scsi_autoconf = SCSI_AUTOCONF;
  107 
  108 int scsibusprint(void *, const char *);
  109 
  110 const u_int8_t version_to_spc [] = {
  111         0, /* 0x00: The device does not claim conformance to any standard. */
  112         1, /* 0x01: (Obsolete) SCSI-1 in olden times. */
  113         2, /* 0x02: (Obsolete) SCSI-2 in olden times. */
  114         3, /* 0x03: The device complies to ANSI INCITS 301-1997 (SPC-3). */
  115         2, /* 0x04: The device complies to ANSI INCITS 351-2001 (SPC-2). */
  116         3, /* 0x05: The device complies to ANSI INCITS 408-2005 (SPC-3). */
  117         4, /* 0x06: The device complies to SPC-4. */
  118         0, /* 0x07: RESERVED. */
  119 };
  120 
  121 int
  122 scsiprint(void *aux, const char *pnp)
  123 {
  124         /* only "scsibus"es can attach to "scsi"s; easy. */
  125         if (pnp)
  126                 printf("scsibus at %s", pnp);
  127 
  128         return (UNCONF);
  129 }
  130 
  131 int
  132 scsibusmatch(struct device *parent, void *match, void *aux)
  133 {
  134         return (1);
  135 }
  136 
  137 /*
  138  * The routine called by the adapter boards to get all their
  139  * devices configured in.
  140  */
  141 void
  142 scsibusattach(struct device *parent, struct device *self, void *aux)
  143 {
  144         struct scsibus_softc            *sb = (struct scsibus_softc *)self;
  145         struct scsibus_attach_args      *saa = aux;
  146         struct scsi_link                *sc_link_proto = saa->saa_sc_link;
  147         int                             nbytes, i;
  148 
  149         if (!cold)
  150                 scsi_autoconf = 0;
  151 
  152         sc_link_proto->scsibus = sb->sc_dev.dv_unit;
  153         sb->adapter_link = sc_link_proto;
  154         if (sb->adapter_link->adapter_buswidth == 0)
  155                 sb->adapter_link->adapter_buswidth = 8;
  156         sb->sc_buswidth = sb->adapter_link->adapter_buswidth;
  157         if (sb->adapter_link->luns == 0)
  158                 sb->adapter_link->luns = 8;
  159 
  160         printf(": %d targets\n", sb->sc_buswidth);
  161 
  162         /* Initialize shared data. */
  163         scsi_init();
  164 
  165         nbytes = sb->sc_buswidth * sizeof(struct scsi_link **);
  166         sb->sc_link = malloc(nbytes, M_DEVBUF, M_NOWAIT);
  167         if (sb->sc_link == NULL)
  168                 panic("scsibusattach: can't allocate target links");
  169         nbytes = sb->adapter_link->luns * sizeof(struct scsi_link *);
  170         for (i = 0; i < sb->sc_buswidth; i++) {
  171                 sb->sc_link[i] = malloc(nbytes, M_DEVBUF, M_NOWAIT);
  172                 if (sb->sc_link[i] == NULL)
  173                         panic("scsibusattach: can't allocate lun links");
  174                 bzero(sb->sc_link[i], nbytes);
  175         }
  176 
  177 #if NBIO > 0
  178         if (bio_register(&sb->sc_dev, scsibus_bioctl) != 0)
  179                 printf("%s: unable to register bio\n", sb->sc_dev.dv_xname);
  180 #endif
  181 
  182         scsi_probe_bus(sb);
  183 }
  184 
  185 int
  186 scsibusactivate(struct device *dev, enum devact act)
  187 {
  188         return (config_activate_children(dev, act));
  189 }
  190 
  191 int
  192 scsibusdetach(struct device *dev, int type)
  193 {
  194         struct scsibus_softc            *sb = (struct scsibus_softc *)dev;
  195         int                             i, j, error;
  196 
  197 #if NBIO > 0
  198         bio_unregister(&sb->sc_dev);
  199 #endif
  200 
  201         if ((error = config_detach_children(dev, type)) != 0)
  202                 return (error);
  203 
  204         for (i = 0; i < sb->sc_buswidth; i++) {
  205                 if (sb->sc_link[i] != NULL) {
  206                         for (j = 0; j < sb->adapter_link->luns; j++) {
  207                                 if (sb->sc_link[i][j] != NULL)
  208                                         free(sb->sc_link[i][j], M_DEVBUF);
  209                         }
  210                         free(sb->sc_link[i], M_DEVBUF);
  211                 }
  212         }
  213 
  214         free(sb->sc_link, M_DEVBUF);
  215 
  216         /* Free shared data. */
  217         scsi_deinit();
  218 
  219         return (0);
  220 }
  221 
  222 int
  223 scsibussubmatch(struct device *parent, void *match, void *aux)
  224 {
  225         struct cfdata                   *cf = match;
  226         struct scsi_attach_args         *sa = aux;
  227         struct scsi_link                *sc_link = sa->sa_sc_link;
  228 
  229         if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != sc_link->target)
  230                 return (0);
  231         if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != sc_link->lun)
  232                 return (0);
  233 
  234         return ((*cf->cf_attach->ca_match)(parent, match, aux));
  235 }
  236 
  237 #if NBIO > 0
  238 int
  239 scsibus_bioctl(struct device *dev, u_long cmd, caddr_t addr)
  240 {
  241         struct scsibus_softc            *sc = (struct scsibus_softc *)dev;
  242         struct sbioc_device             *sdev;
  243 
  244         switch (cmd) {
  245         case SBIOCPROBE:
  246                 sdev = (struct sbioc_device *)addr;
  247 
  248                 if (sdev->sd_target == -1 && sdev->sd_lun == -1)
  249                         return (scsi_probe_bus(sc));
  250 
  251                 /* specific lun and wildcard target is bad */
  252                 if (sdev->sd_target == -1)
  253                         return (EINVAL);
  254 
  255                 if (sdev->sd_lun == -1)
  256                         return (scsi_probe_target(sc, sdev->sd_target));
  257 
  258                 return (scsi_probe_lun(sc, sdev->sd_target, sdev->sd_lun));
  259 
  260         case SBIOCDETACH:
  261                 sdev = (struct sbioc_device *)addr;
  262 
  263                 if (sdev->sd_target == -1)
  264                         return (EINVAL);
  265 
  266                 if (sdev->sd_lun == -1)
  267                         return (scsi_detach_target(sc, sdev->sd_target, 0));
  268 
  269                 return (scsi_detach_lun(sc, sdev->sd_target, sdev->sd_lun, 0));
  270 
  271         default:
  272                 return (ENOTTY);
  273         }
  274 }
  275 #endif
  276 
  277 int
  278 scsi_probe_bus(struct scsibus_softc *sc)
  279 {
  280         struct scsi_link *alink = sc->adapter_link;
  281         int i;
  282 
  283         for (i = 0; i < alink->adapter_buswidth; i++)
  284                 scsi_probe_target(sc, i);
  285 
  286         return (0);
  287 }
  288 
  289 int
  290 scsi_probe_target(struct scsibus_softc *sc, int target)
  291 {
  292         struct scsi_link *alink = sc->adapter_link;
  293         struct scsi_link *link;
  294         struct scsi_report_luns_data *report;
  295         int i, nluns, lun;
  296 
  297         if (scsi_probe_lun(sc, target, 0) == EINVAL)
  298                 return (EINVAL);
  299 
  300         link = sc->sc_link[target][0];
  301         if (link == NULL)
  302                 return (ENXIO);
  303 
  304         if ((link->flags & (SDEV_UMASS | SDEV_ATAPI)) == 0 &&
  305             SCSISPC(link->inqdata.version) > 2) {
  306                 report = malloc(sizeof(*report), M_TEMP, M_WAITOK);
  307                 if (report == NULL)
  308                         goto dumbscan;
  309 
  310                 if (scsi_report_luns(link, REPORT_NORMAL, report,
  311                     sizeof(*report), scsi_autoconf | SCSI_SILENT |
  312                     SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY |
  313                     SCSI_IGNORE_MEDIA_CHANGE, 10000) != 0) {
  314                         free(report, M_TEMP);
  315                         goto dumbscan;
  316                 }
  317 
  318                 /*
  319                  * XXX In theory we should check if data is full, which
  320                  * would indicate it needs to be enlarged and REPORT
  321                  * LUNS tried again. Solaris tries up to 3 times with
  322                  * larger sizes for data.
  323                  */
  324                 nluns = _4btol(report->length) / RPL_LUNDATA_SIZE;
  325                 for (i = 0; i < nluns; i++) {
  326                         if (report->luns[i].lundata[0] != 0)
  327                                 continue;
  328                         lun = report->luns[i].lundata[RPL_LUNDATA_T0LUN];
  329                         if (lun == 0)
  330                                 continue;
  331 
  332                         /* Probe the provided LUN. Don't check LUN 0. */
  333                         sc->sc_link[target][0] = NULL;
  334                         scsi_probe_lun(sc, target, lun);
  335                         sc->sc_link[target][0] = link;
  336                 }
  337 
  338                 free(report, M_TEMP);
  339                 return (0);
  340         }
  341 
  342 dumbscan:
  343         for (i = 1; i < alink->luns; i++) {
  344                 if (scsi_probe_lun(sc, target, i) == EINVAL)
  345                         break;
  346         }
  347 
  348         return (0);
  349 }
  350 
  351 int
  352 scsi_probe_lun(struct scsibus_softc *sc, int target, int lun)
  353 {
  354         struct scsi_link *alink = sc->adapter_link;
  355 
  356         if (target < 0 || target >= alink->adapter_buswidth ||
  357             target == alink->adapter_target ||
  358             lun < 0 || lun >= alink->luns)
  359                 return (ENXIO);
  360 
  361         return (scsi_probedev(sc, target, lun));
  362 }
  363 
  364 int
  365 scsi_detach_bus(struct scsibus_softc *sc, int flags)
  366 {
  367         struct scsi_link *alink = sc->adapter_link;
  368         int i;
  369 
  370         for (i = 0; i < alink->adapter_buswidth; i++)
  371                 scsi_detach_target(sc, i, flags);
  372 
  373         return (0);
  374 }
  375 
  376 int
  377 scsi_detach_target(struct scsibus_softc *sc, int target, int flags)
  378 {
  379         struct scsi_link *alink = sc->adapter_link;
  380         int i, err, rv = 0, detached = 0;
  381 
  382         if (target < 0 || target >= alink->adapter_buswidth ||
  383             target == alink->adapter_target)
  384                 return (ENXIO);
  385 
  386         if (sc->sc_link[target] == NULL)
  387                 return (ENXIO);
  388 
  389         for (i = 0; i < alink->luns; i++) { /* nicer backwards? */
  390                 if (sc->sc_link[target][i] == NULL)
  391                         continue;
  392 
  393                 err = scsi_detach_lun(sc, target, i, flags);
  394                 if (err != 0)
  395                         rv = err;
  396                 detached = 1;
  397         }
  398 
  399         return (detached ? rv : ENXIO);
  400 }
  401 
  402 int
  403 scsi_detach_lun(struct scsibus_softc *sc, int target, int lun, int flags)
  404 {
  405         struct scsi_link *alink = sc->adapter_link;
  406         struct scsi_link *link;
  407         int rv;
  408 
  409         if (target < 0 || target >= alink->adapter_buswidth ||
  410             target == alink->adapter_target ||
  411             lun < 0 || lun >= alink->luns)
  412                 return (ENXIO);
  413 
  414         if (sc->sc_link[target] == NULL)
  415                 return (ENXIO);
  416 
  417         link = sc->sc_link[target][lun];
  418         if (link == NULL)
  419                 return (ENXIO);
  420 
  421         if (((flags & DETACH_FORCE) == 0) && (link->flags & SDEV_OPEN))
  422                 return (EBUSY);
  423 
  424         /* detaching a device from scsibus is a two step process... */
  425 
  426         /* 1. detach the device */
  427         rv = config_detach(link->device_softc, flags);
  428         if (rv != 0)
  429                 return (rv);
  430 
  431         /* 2. free up its state in the midlayer */
  432         free(link, M_DEVBUF);
  433         sc->sc_link[target][lun] = NULL;
  434 
  435         return (0);
  436 }
  437 
  438 void
  439 scsi_strvis(u_char *dst, u_char *src, int len)
  440 {
  441         u_char                          last;
  442 
  443         /* Trim leading and trailing whitespace and NULs. */
  444         while (len > 0 && (src[0] == ' ' || src[0] == '\t' || src[0] == '\n' ||
  445             src[0] == '\0' || src[0] == 0xff))
  446                 ++src, --len;
  447         while (len > 0 && (src[len-1] == ' ' || src[len-1] == '\t' ||
  448             src[len-1] == '\n' || src[len-1] == '\0' || src[len-1] == 0xff))
  449                 --len;
  450 
  451         last = 0xff;
  452         while (len > 0) {
  453                 switch (*src) {
  454                 case ' ':
  455                 case '\t':
  456                 case '\n':
  457                 case '\0':
  458                 case 0xff:
  459                         /* collapse whitespace and NULs to a single space */
  460                         if (last != ' ')
  461                                 *dst++ = ' ';
  462                         last = ' ';
  463                         break;
  464                 case '\\':
  465                         /* quote characters */
  466                         *dst++ = '\\';
  467                         *dst++ = '\\';
  468                         last = '\\';
  469                         break;
  470                 default:
  471                         if (*src < 0x20 || *src >= 0x80) {
  472                                 /* non-printable characters */
  473                                 *dst++ = '\\';
  474                                 *dst++ = ((*src & 0300) >> 6) + '0';
  475                                 *dst++ = ((*src & 0070) >> 3) + '0';
  476                                 *dst++ = ((*src & 0007) >> 0) + '0';
  477                         } else {
  478                                 /* normal characters */
  479                                 *dst++ = *src;
  480                         }
  481                         last = *src;
  482                         break;
  483                 }
  484                 ++src, --len;
  485         }
  486 
  487         *dst++ = 0;
  488 }
  489 
  490 struct scsi_quirk_inquiry_pattern {
  491         struct scsi_inquiry_pattern     pattern;
  492         u_int16_t                       quirks;
  493 };
  494 
  495 const struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = {
  496         {{T_CDROM, T_REMOV,
  497          "PLEXTOR", "CD-ROM PX-40TS", "1.01"},    SDEV_NOSYNC},
  498 
  499         {{T_DIRECT, T_FIXED,
  500          "MICROP  ", "1588-15MBSUN0669", ""},     SDEV_AUTOSAVE},
  501         {{T_DIRECT, T_FIXED,
  502          "DEC     ", "RZ55     (C) DEC", ""},     SDEV_AUTOSAVE},
  503         {{T_DIRECT, T_FIXED,
  504          "EMULEX  ", "MD21/S2     ESDI", "A00"},  SDEV_AUTOSAVE},
  505         {{T_DIRECT, T_FIXED,
  506          "IBMRAID ", "0662S",            ""},     SDEV_AUTOSAVE},
  507         {{T_DIRECT, T_FIXED,
  508          "IBM     ", "0663H",            ""},     SDEV_AUTOSAVE},
  509         {{T_DIRECT, T_FIXED,
  510          "IBM",   "0664",                ""},     SDEV_AUTOSAVE},
  511         {{T_DIRECT, T_FIXED,
  512          "IBM     ", "H3171-S2",         ""},     SDEV_AUTOSAVE},
  513         {{T_DIRECT, T_FIXED,
  514          "IBM     ", "KZ-C",             ""},     SDEV_AUTOSAVE},
  515         /* Broken IBM disk */
  516         {{T_DIRECT, T_FIXED,
  517          ""        , "DFRSS2F",          ""},     SDEV_AUTOSAVE},
  518         {{T_DIRECT, T_FIXED,
  519          "QUANTUM ", "ELS85S          ", ""},     SDEV_AUTOSAVE},
  520         {{T_DIRECT, T_REMOV,
  521          "iomega", "jaz 1GB",            ""},     SDEV_NOTAGS},
  522         {{T_DIRECT, T_FIXED,
  523          "MICROP", "4421-07",            ""},     SDEV_NOTAGS},
  524         {{T_DIRECT, T_FIXED,
  525          "SEAGATE", "ST150176LW",        "0002"}, SDEV_NOTAGS},
  526         {{T_DIRECT, T_FIXED,
  527          "HP", "C3725S",                 ""},     SDEV_NOTAGS},
  528         {{T_DIRECT, T_FIXED,
  529          "IBM", "DCAS",                  ""},     SDEV_NOTAGS},
  530 
  531         {{T_SEQUENTIAL, T_REMOV,
  532          "SONY    ", "SDT-5000        ", "3."},   SDEV_NOSYNC|SDEV_NOWIDE},
  533         {{T_SEQUENTIAL, T_REMOV,
  534          "WangDAT ", "Model 1300      ", "02.4"}, SDEV_NOSYNC|SDEV_NOWIDE},
  535         {{T_SEQUENTIAL, T_REMOV,
  536          "WangDAT ", "Model 2600      ", "01.7"}, SDEV_NOSYNC|SDEV_NOWIDE},
  537         {{T_SEQUENTIAL, T_REMOV,
  538          "WangDAT ", "Model 3200      ", "02.2"}, SDEV_NOSYNC|SDEV_NOWIDE},
  539 
  540         /* ATAPI device quirks */
  541         {{T_CDROM, T_REMOV,
  542          "ALPS ELECTRIC CO.,LTD. DC544C", "", "SW03D"}, ADEV_NOTUR},
  543         {{T_CDROM, T_REMOV,
  544          "CR-2801TE", "", "1.07"},              ADEV_NOSENSE},
  545         {{T_CDROM, T_REMOV,
  546          "CREATIVECD3630E", "", "AC101"},       ADEV_NOSENSE},
  547         {{T_CDROM, T_REMOV,
  548          "FX320S", "", "q01"},                  ADEV_NOSENSE},
  549         {{T_CDROM, T_REMOV,
  550          "GCD-R580B", "", "1.00"},              ADEV_LITTLETOC},
  551         {{T_CDROM, T_REMOV,
  552          "MATSHITA CR-574", "", "1.02"},        ADEV_NOCAPACITY},
  553         {{T_CDROM, T_REMOV,
  554          "MATSHITA CR-574", "", "1.06"},        ADEV_NOCAPACITY},
  555         {{T_CDROM, T_REMOV,
  556          "Memorex CRW-2642", "", "1.0g"},       ADEV_NOSENSE},
  557         {{T_CDROM, T_REMOV,
  558          "NEC                 CD-ROM DRIVE:273", "", "4.21"}, ADEV_NOTUR},
  559         {{T_CDROM, T_REMOV,
  560          "SANYO CRD-256P", "", "1.02"},         ADEV_NOCAPACITY},
  561         {{T_CDROM, T_REMOV,
  562          "SANYO CRD-254P", "", "1.02"},         ADEV_NOCAPACITY},
  563         {{T_CDROM, T_REMOV,
  564          "SANYO CRD-S54P", "", "1.08"},         ADEV_NOCAPACITY},
  565         {{T_CDROM, T_REMOV,
  566          "CD-ROM  CDR-S1", "", "1.70"},         ADEV_NOCAPACITY}, /* Sanyo */
  567         {{T_CDROM, T_REMOV,
  568          "CD-ROM  CDR-N16", "", "1.25"},        ADEV_NOCAPACITY}, /* Sanyo */
  569         {{T_CDROM, T_REMOV,
  570          "UJDCD8730", "", "1.14"},              ADEV_NODOORLOCK}, /* Acer */
  571 };
  572 
  573 
  574 /*
  575  * Print out autoconfiguration information for a subdevice.
  576  *
  577  * This is a slight abuse of 'standard' autoconfiguration semantics,
  578  * because 'print' functions don't normally print the colon and
  579  * device information.  However, in this case that's better than
  580  * either printing redundant information before the attach message,
  581  * or having the device driver call a special function to print out
  582  * the standard device information.
  583  */
  584 int
  585 scsibusprint(void *aux, const char *pnp)
  586 {
  587         struct scsi_attach_args         *sa = aux;
  588         struct scsi_inquiry_data        *inqbuf;
  589         u_int8_t                        type;
  590         int                             removable;
  591         char                            *dtype, *qtype;
  592         char                            vendor[33], product[65], revision[17];
  593         int                             target, lun;
  594 
  595         if (pnp != NULL)
  596                 printf("%s", pnp);
  597 
  598         inqbuf = sa->sa_inqbuf;
  599 
  600         target = sa->sa_sc_link->target;
  601         lun = sa->sa_sc_link->lun;
  602 
  603         type = inqbuf->device & SID_TYPE;
  604         removable = inqbuf->dev_qual2 & SID_REMOVABLE ? 1 : 0;
  605 
  606         /*
  607          * Figure out basic device type and qualifier.
  608          */
  609         dtype = 0;
  610         switch (inqbuf->device & SID_QUAL) {
  611         case SID_QUAL_LU_OK:
  612                 qtype = "";
  613                 break;
  614 
  615         case SID_QUAL_LU_OFFLINE:
  616                 qtype = " offline";
  617                 break;
  618 
  619         case SID_QUAL_RSVD:
  620                 panic("scsibusprint: qualifier == SID_QUAL_RSVD");
  621 
  622         case SID_QUAL_BAD_LU:
  623                 panic("scsibusprint: qualifier == SID_QUAL_BAD_LU");
  624 
  625         default:
  626                 qtype = "";
  627                 dtype = "vendor-unique";
  628                 break;
  629         }
  630         if (dtype == 0) {
  631                 switch (type) {
  632                 case T_DIRECT:
  633                         dtype = "direct";
  634                         break;
  635                 case T_SEQUENTIAL:
  636                         dtype = "sequential";
  637                         break;
  638                 case T_PRINTER:
  639                         dtype = "printer";
  640                         break;
  641                 case T_PROCESSOR:
  642                         dtype = "processor";
  643                         break;
  644                 case T_CDROM:
  645                         dtype = "cdrom";
  646                         break;
  647                 case T_WORM:
  648                         dtype = "worm";
  649                         break;
  650                 case T_SCANNER:
  651                         dtype = "scanner";
  652                         break;
  653                 case T_OPTICAL:
  654                         dtype = "optical";
  655                         break;
  656                 case T_CHANGER:
  657                         dtype = "changer";
  658                         break;
  659                 case T_COMM:
  660                         dtype = "communication";
  661                         break;
  662                 case T_ENCLOSURE:
  663                         dtype = "enclosure services";
  664                         break;
  665                 case T_RDIRECT:
  666                         dtype = "simplified direct";
  667                         break;
  668                 case T_NODEVICE:
  669                         panic("scsibusprint: device type T_NODEVICE");
  670                 default:
  671                         dtype = "unknown";
  672                         break;
  673                 }
  674         }
  675 
  676         scsi_strvis(vendor, inqbuf->vendor, 8);
  677         scsi_strvis(product, inqbuf->product, 16);
  678         scsi_strvis(revision, inqbuf->revision, 4);
  679 
  680         printf(" targ %d lun %d: <%s, %s, %s> SCSI%d %d/%s %s%s",
  681             target, lun, vendor, product, revision,
  682             SCSISPC(inqbuf->version), type, dtype,
  683             removable ? "removable" : "fixed", qtype);
  684 
  685         return (UNCONF);
  686 }
  687 
  688 /*
  689  * Given a target and lun, ask the device what it is, and find the correct
  690  * driver table entry.
  691  *
  692  * Return 0 if further LUNs are possible, EINVAL if not.
  693  */
  694 int
  695 scsi_probedev(struct scsibus_softc *scsi, int target, int lun)
  696 {
  697         const struct scsi_quirk_inquiry_pattern *finger;
  698         static struct scsi_inquiry_data inqbuf;
  699         struct scsi_attach_args sa;
  700         struct scsi_link *sc_link;
  701         struct cfdata *cf;
  702         int priority, rslt = 0;
  703 
  704         /* Skip this slot if it is already attached and try the next LUN. */
  705         if (scsi->sc_link[target][lun] != NULL)
  706                 return (0);
  707 
  708         sc_link = malloc(sizeof(*sc_link), M_DEVBUF, M_NOWAIT);
  709         if (sc_link == NULL)
  710                 return (EINVAL);
  711 
  712         *sc_link = *scsi->adapter_link;
  713         sc_link->target = target;
  714         sc_link->lun = lun;
  715         sc_link->device = &probe_switch;
  716 
  717         SC_DEBUG(sc_link, SDEV_DB2, ("scsi_link created.\n"));
  718 
  719         /*
  720          * Tell drivers that are paying attention to avoid sync/wide/tags until
  721          * INQUIRY data has been processed and the quirks information is
  722          * complete. Some drivers set bits in quirks before we get here, so
  723          * just add NOTAGS, NOWIDE and NOSYNC.
  724          */
  725         sc_link->quirks |= SDEV_NOSYNC | SDEV_NOWIDE | SDEV_NOTAGS;
  726 
  727         /*
  728          * Ask the device what it is
  729          */
  730 #ifdef SCSIDEBUG
  731         if (((1 << sc_link->scsibus) & scsidebug_buses) &&
  732             ((1 << target) & scsidebug_targets) &&
  733             ((1 << lun) & scsidebug_luns))
  734                 sc_link->flags |= scsidebug_level;
  735 #endif /* SCSIDEBUG */
  736 
  737 #if defined(mvme68k)
  738         if (lun == 0) {
  739                 /* XXX some drivers depend on this */
  740                 scsi_test_unit_ready(sc_link, TEST_READY_RETRIES,
  741                     scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST |
  742                     SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE);
  743         }
  744 #endif
  745 
  746         /* Now go ask the device all about itself. */
  747         rslt = scsi_inquire(sc_link, &inqbuf, scsi_autoconf | SCSI_SILENT);
  748         if (rslt != 0) {
  749                 SC_DEBUG(sc_link, SDEV_DB2, ("Bad LUN. rslt = %i\n", rslt));
  750                 if (lun == 0)
  751                         rslt = EINVAL;
  752                 goto bad;
  753         }
  754 
  755         switch (inqbuf.device & SID_QUAL) {
  756         case SID_QUAL_RSVD:
  757         case SID_QUAL_BAD_LU:
  758         case SID_QUAL_LU_OFFLINE:
  759                 SC_DEBUG(sc_link, SDEV_DB1,
  760                     ("Bad LUN. SID_QUAL = 0x%02x\n", inqbuf.device & SID_QUAL));
  761                 goto bad;
  762 
  763         case SID_QUAL_LU_OK:
  764                 if ((inqbuf.device & SID_TYPE) == T_NODEVICE) {
  765                         SC_DEBUG(sc_link, SDEV_DB1,
  766                             ("Bad LUN. SID_TYPE = T_NODEVICE\n"));
  767                         goto bad;
  768                 }
  769                 break;
  770 
  771         default:
  772                 break;
  773         }
  774 
  775         if (lun == 0 || scsi->sc_link[target][0] == NULL)
  776                 ;
  777         else if (sc_link->flags & SDEV_UMASS)
  778                 ;
  779         else if (memcmp(&inqbuf, &scsi->sc_link[target][0]->inqdata,
  780             sizeof inqbuf) == 0) {
  781                 /* The device doesn't distinguish between LUNs. */
  782                 SC_DEBUG(sc_link, SDEV_DB1, ("IDENTIFY not supported.\n"));
  783                 rslt = EINVAL;
  784                 goto bad;
  785         }
  786 
  787         finger = (const struct scsi_quirk_inquiry_pattern *)scsi_inqmatch(
  788             &inqbuf, scsi_quirk_patterns,
  789             sizeof(scsi_quirk_patterns)/sizeof(scsi_quirk_patterns[0]),
  790             sizeof(scsi_quirk_patterns[0]), &priority);
  791 
  792         /*
  793          * Based upon the inquiry flags we got back, and if we're
  794          * at SCSI-2 or better, remove some limiting quirks.
  795          */
  796         if (SCSISPC(inqbuf.version) >= 2) {
  797                 if ((inqbuf.flags & SID_CmdQue) != 0)
  798                         sc_link->quirks &= ~SDEV_NOTAGS;
  799                 if ((inqbuf.flags & SID_Sync) != 0)
  800                         sc_link->quirks &= ~SDEV_NOSYNC;
  801                 if ((inqbuf.flags & SID_WBus16) != 0)
  802                         sc_link->quirks &= ~SDEV_NOWIDE;
  803         }
  804         /*
  805          * Now apply any quirks from the table.
  806          */
  807         if (priority != 0)
  808                 sc_link->quirks |= finger->quirks;
  809 
  810         /*
  811          * Save INQUIRY.
  812          */
  813         memcpy(&sc_link->inqdata, &inqbuf, sizeof(sc_link->inqdata));
  814 
  815         /*
  816          * note what BASIC type of device it is
  817          */
  818         if ((inqbuf.dev_qual2 & SID_REMOVABLE) != 0)
  819                 sc_link->flags |= SDEV_REMOVABLE;
  820 
  821         sa.sa_sc_link = sc_link;
  822         sa.sa_inqbuf = &sc_link->inqdata;
  823 
  824         if ((cf = config_search(scsibussubmatch, (struct device *)scsi,
  825             &sa)) == 0) {
  826                 scsibusprint(&sa, scsi->sc_dev.dv_xname);
  827                 printf(" not configured\n");
  828                 goto bad;
  829         }
  830 
  831         /*
  832          * Braindead USB devices, especially some x-in-1 media readers, try to
  833          * 'help' by pretending any LUN is actually LUN 0 until they see a
  834          * different LUN used in a command. So do an INQUIRY on LUN 1 at this
  835          * point (since we are done with the data in inqbuf) to prevent such
  836          * helpfulness before it causes confusion.
  837          */
  838         if (lun == 0 && (sc_link->flags & SDEV_UMASS) &&
  839             scsi->sc_link[target][1] == NULL && sc_link->luns > 1) {
  840                 sc_link->lun = 1;
  841                 scsi_inquire(sc_link, &inqbuf, scsi_autoconf | SCSI_SILENT);
  842                 sc_link->lun = 0;
  843         }
  844 
  845         scsi->sc_link[target][lun] = sc_link;
  846 
  847         /*
  848          * Generate a TEST_UNIT_READY command. This gives drivers waiting for
  849          * valid quirks data a chance to set wide/sync/tag options
  850          * appropriately. It also clears any outstanding ACA conditions that
  851          * INQUIRY may leave behind.
  852          *
  853          * Do this now so that any messages generated by config_attach() do not
  854          * have negotiation messages inserted into their midst.
  855          */
  856         scsi_test_unit_ready(sc_link, TEST_READY_RETRIES,
  857             scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST |
  858             SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE);
  859 
  860         config_attach((struct device *)scsi, cf, &sa, scsibusprint);
  861 
  862         return (0);
  863 
  864 bad:
  865         free(sc_link, M_DEVBUF);
  866         return (rslt);
  867 }
  868 
  869 /*
  870  * Return a priority based on how much of the inquiry data matches
  871  * the patterns for the particular driver.
  872  */
  873 const void *
  874 scsi_inqmatch(struct scsi_inquiry_data *inqbuf, const void *_base,
  875     int nmatches, int matchsize, int *bestpriority)
  876 {
  877         u_int8_t                        type;
  878         int                             removable;
  879         const void                      *bestmatch;
  880         const unsigned char             *base = (const unsigned char *)_base;
  881 
  882         /* Include the qualifier to catch vendor-unique types. */
  883         type = inqbuf->device;
  884         removable = inqbuf->dev_qual2 & SID_REMOVABLE ? T_REMOV : T_FIXED;
  885 
  886         for (*bestpriority = 0, bestmatch = 0; nmatches--; base += matchsize) {
  887                 struct scsi_inquiry_pattern *match = (void *)base;
  888                 int priority, len;
  889 
  890                 if (type != match->type)
  891                         continue;
  892                 if (removable != match->removable)
  893                         continue;
  894                 priority = 2;
  895                 len = strlen(match->vendor);
  896                 if (bcmp(inqbuf->vendor, match->vendor, len))
  897                         continue;
  898                 priority += len;
  899                 len = strlen(match->product);
  900                 if (bcmp(inqbuf->product, match->product, len))
  901                         continue;
  902                 priority += len;
  903                 len = strlen(match->revision);
  904                 if (bcmp(inqbuf->revision, match->revision, len))
  905                         continue;
  906                 priority += len;
  907 
  908 #if SCSIDEBUG
  909                 printf("scsi_inqmatch: %d/%d/%d <%s, %s, %s>\n",
  910                     priority, match->type, match->removable,
  911                     match->vendor, match->product, match->revision);
  912 #endif
  913                 if (priority > *bestpriority) {
  914                         *bestpriority = priority;
  915                         bestmatch = base;
  916                 }
  917         }
  918 
  919         return (bestmatch);
  920 }

/* [<][>][^][v][top][bottom][index][help] */