LCOV - code coverage report
Current view: top level - scsi - scsiconf.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 542 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 35 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: scsiconf.c,v 1.196 2017/09/08 05:36:53 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             : #include "mpath.h"
      52             : 
      53             : #include <sys/param.h>
      54             : #include <sys/systm.h>
      55             : #include <sys/malloc.h>
      56             : #include <sys/pool.h>
      57             : #include <sys/device.h>
      58             : #include <sys/buf.h>
      59             : #include <sys/atomic.h>
      60             : 
      61             : #include <scsi/scsi_all.h>
      62             : #include <scsi/scsiconf.h>
      63             : 
      64             : #if NBIO > 0
      65             : #include <sys/ioctl.h>
      66             : #include <sys/scsiio.h>
      67             : #include <dev/biovar.h>
      68             : #endif
      69             : 
      70             : /*
      71             :  * Declarations
      72             :  */
      73             : int     scsi_probedev(struct scsibus_softc *, int, int);
      74             : 
      75             : void    scsi_devid(struct scsi_link *);
      76             : int     scsi_devid_pg80(struct scsi_link *);
      77             : int     scsi_devid_pg83(struct scsi_link *);
      78             : int     scsi_devid_wwn(struct scsi_link *);
      79             : 
      80             : int     scsibusmatch(struct device *, void *, void *);
      81             : void    scsibusattach(struct device *, struct device *, void *);
      82             : int     scsibusactivate(struct device *, int);
      83             : int     scsibusdetach(struct device *, int);
      84             : 
      85             : int     scsibussubmatch(struct device *, void *, void *);
      86             : 
      87             : #if NBIO > 0
      88             : int     scsibus_bioctl(struct device *, u_long, caddr_t);
      89             : #endif
      90             : 
      91             : struct cfattach scsibus_ca = {
      92             :         sizeof(struct scsibus_softc), scsibusmatch, scsibusattach,
      93             :         scsibusdetach, scsibusactivate
      94             : };
      95             : 
      96             : struct cfdriver scsibus_cd = {
      97             :         NULL, "scsibus", DV_DULL
      98             : };
      99             : 
     100             : #ifdef SCSIDEBUG
     101             : u_int32_t scsidebug_buses = SCSIDEBUG_BUSES;
     102             : u_int32_t scsidebug_targets = SCSIDEBUG_TARGETS;
     103             : u_int32_t scsidebug_luns = SCSIDEBUG_LUNS;
     104             : int scsidebug_level = SCSIDEBUG_LEVEL;
     105             : #endif
     106             : 
     107             : int scsi_autoconf = SCSI_AUTOCONF;
     108             : 
     109             : int scsibusprint(void *, const char *);
     110             : void scsibus_printlink(struct scsi_link *);
     111             : 
     112             : int scsi_activate_bus(struct scsibus_softc *, int);
     113             : int scsi_activate_target(struct scsibus_softc *, int, int);
     114             : int scsi_activate_lun(struct scsibus_softc *, int, int, int);
     115             : 
     116             : const u_int8_t version_to_spc [] = {
     117             :         0, /* 0x00: The device does not claim conformance to any standard. */
     118             :         1, /* 0x01: (Obsolete) SCSI-1 in olden times. */
     119             :         2, /* 0x02: (Obsolete) SCSI-2 in olden times. */
     120             :         3, /* 0x03: The device complies to ANSI INCITS 301-1997 (SPC-3). */
     121             :         2, /* 0x04: The device complies to ANSI INCITS 351-2001 (SPC-2). */
     122             :         3, /* 0x05: The device complies to ANSI INCITS 408-2005 (SPC-3). */
     123             :         4, /* 0x06: The device complies to SPC-4. */
     124             :         0, /* 0x07: RESERVED. */
     125             : };
     126             : 
     127             : int
     128           0 : scsiprint(void *aux, const char *pnp)
     129             : {
     130             :         /* only "scsibus"es can attach to "scsi"s; easy. */
     131           0 :         if (pnp)
     132           0 :                 printf("scsibus at %s", pnp);
     133             : 
     134           0 :         return (UNCONF);
     135             : }
     136             : 
     137             : int
     138           0 : scsibusmatch(struct device *parent, void *match, void *aux)
     139             : {
     140           0 :         return (1);
     141             : }
     142             : 
     143             : /*
     144             :  * The routine called by the adapter boards to get all their
     145             :  * devices configured in.
     146             :  */
     147             : void
     148           0 : scsibusattach(struct device *parent, struct device *self, void *aux)
     149             : {
     150           0 :         struct scsibus_softc            *sb = (struct scsibus_softc *)self;
     151           0 :         struct scsibus_attach_args      *saa = aux;
     152           0 :         struct scsi_link                *sc_link_proto = saa->saa_sc_link;
     153             : 
     154           0 :         if (!cold)
     155           0 :                 scsi_autoconf = 0;
     156             : 
     157           0 :         sc_link_proto->bus = sb;
     158           0 :         sc_link_proto->scsibus = sb->sc_dev.dv_unit;
     159           0 :         sb->adapter_link = sc_link_proto;
     160           0 :         if (sb->adapter_link->adapter_buswidth == 0)
     161           0 :                 sb->adapter_link->adapter_buswidth = 8;
     162           0 :         sb->sc_buswidth = sb->adapter_link->adapter_buswidth;
     163           0 :         if (sb->adapter_link->luns == 0)
     164           0 :                 sb->adapter_link->luns = 8;
     165             : 
     166           0 :         printf(": %d targets", sb->sc_buswidth);
     167           0 :         if (sb->adapter_link->adapter_target < sb->sc_buswidth)
     168           0 :                 printf(", initiator %d", sb->adapter_link->adapter_target);
     169           0 :         if (sb->adapter_link->port_wwn != 0x0 &&
     170           0 :             sb->adapter_link->node_wwn != 0x0) {
     171           0 :                 printf(", WWPN %016llx, WWNN %016llx",
     172             :                     sb->adapter_link->port_wwn, sb->adapter_link->node_wwn);
     173           0 :         }
     174           0 :         printf("\n");
     175             : 
     176             :         /* Initialize shared data. */
     177           0 :         scsi_init();
     178             : 
     179           0 :         SLIST_INIT(&sb->sc_link_list);
     180             : 
     181             : #if NBIO > 0
     182           0 :         if (bio_register(&sb->sc_dev, scsibus_bioctl) != 0)
     183           0 :                 printf("%s: unable to register bio\n", sb->sc_dev.dv_xname);
     184             : #endif
     185             : 
     186           0 :         scsi_probe_bus(sb);
     187           0 : }
     188             : 
     189             : int
     190           0 : scsibusactivate(struct device *dev, int act)
     191             : {
     192           0 :         struct scsibus_softc *sb = (struct scsibus_softc *)dev;
     193             : 
     194           0 :         return scsi_activate(sb, -1, -1, act);
     195             : }
     196             : 
     197             : int
     198           0 : scsi_activate(struct scsibus_softc *sb, int target, int lun, int act)
     199             : {
     200           0 :         if (target == -1 && lun == -1)
     201           0 :                 return scsi_activate_bus(sb, act);
     202             : 
     203           0 :         if (target == -1)
     204           0 :                 return 0;
     205             : 
     206           0 :         if (lun == -1)
     207           0 :                 return scsi_activate_target(sb, target, act);
     208             : 
     209           0 :         return scsi_activate_lun(sb, target, lun, act);
     210           0 : }
     211             : 
     212             : int
     213           0 : scsi_activate_bus(struct scsibus_softc *sb, int act)
     214             : {
     215             :         int target, rv = 0, r;
     216             : 
     217           0 :         for (target = 0; target < sb->sc_buswidth; target++) {
     218           0 :                 r = scsi_activate_target(sb, target, act);
     219           0 :                 if (r)
     220           0 :                         rv = r;
     221             :         }
     222           0 :         return (rv);
     223             : }
     224             : 
     225             : int
     226           0 : scsi_activate_target(struct scsibus_softc *sb, int target, int act)
     227             : {
     228             :         int lun, rv = 0, r;
     229             : 
     230           0 :         for (lun = 0; lun < sb->adapter_link->luns; lun++) {
     231           0 :                 r = scsi_activate_lun(sb, target, lun, act);
     232           0 :                 if (r)
     233           0 :                         rv = r;
     234             :         }
     235           0 :         return (rv);
     236             : }
     237             : 
     238             : int
     239           0 : scsi_activate_lun(struct scsibus_softc *sb, int target, int lun, int act)
     240             : {
     241             :         struct scsi_link *link;
     242             :         struct device *dev;
     243             :         int rv = 0;
     244             : 
     245           0 :         link = scsi_get_link(sb, target, lun);
     246           0 :         if (link == NULL)
     247           0 :                 return (0);
     248             : 
     249           0 :         dev = link->device_softc;
     250           0 :         switch (act) {
     251             :         case DVACT_DEACTIVATE:
     252           0 :                 atomic_setbits_int(&link->state, SDEV_S_DYING);
     253           0 :                 config_deactivate(dev);
     254           0 :                 break;
     255             :         default:
     256           0 :                 rv = config_suspend(dev, act);
     257           0 :                 break;
     258             :         }
     259           0 :         return (rv);
     260           0 : }
     261             : 
     262             : int
     263           0 : scsibusdetach(struct device *dev, int type)
     264             : {
     265           0 :         struct scsibus_softc            *sb = (struct scsibus_softc *)dev;
     266             :         int                             error;
     267             : 
     268             : #if NBIO > 0
     269           0 :         bio_unregister(&sb->sc_dev);
     270             : #endif
     271             : 
     272           0 :         error = scsi_detach_bus(sb, type);
     273           0 :         if (error != 0)
     274           0 :                 return (error);
     275             : 
     276           0 :         KASSERT(SLIST_EMPTY(&sb->sc_link_list));
     277             : 
     278           0 :         return (0);
     279           0 : }
     280             : 
     281             : int
     282           0 : scsibussubmatch(struct device *parent, void *match, void *aux)
     283             : {
     284           0 :         struct cfdata                   *cf = match;
     285           0 :         struct scsi_attach_args         *sa = aux;
     286           0 :         struct scsi_link                *link = sa->sa_sc_link;
     287             : 
     288           0 :         if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != link->target)
     289           0 :                 return (0);
     290           0 :         if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != link->lun)
     291           0 :                 return (0);
     292             : 
     293           0 :         return ((*cf->cf_attach->ca_match)(parent, match, aux));
     294           0 : }
     295             : 
     296             : #if NBIO > 0
     297             : int
     298           0 : scsibus_bioctl(struct device *dev, u_long cmd, caddr_t addr)
     299             : {
     300           0 :         struct scsibus_softc            *sb = (struct scsibus_softc *)dev;
     301             :         struct sbioc_device             *sdev;
     302             : 
     303           0 :         switch (cmd) {
     304             :         case SBIOCPROBE:
     305           0 :                 sdev = (struct sbioc_device *)addr;
     306           0 :                 return (scsi_probe(sb, sdev->sd_target, sdev->sd_lun));
     307             : 
     308             :         case SBIOCDETACH:
     309           0 :                 sdev = (struct sbioc_device *)addr;
     310           0 :                 return (scsi_detach(sb, sdev->sd_target, sdev->sd_lun, 0));
     311             : 
     312             :         default:
     313           0 :                 return (ENOTTY);
     314             :         }
     315           0 : }
     316             : #endif
     317             : 
     318             : int
     319           0 : scsi_probe_bus(struct scsibus_softc *sb)
     320             : {
     321           0 :         struct scsi_link *alink = sb->adapter_link;
     322             :         int i;
     323             : 
     324           0 :         for (i = 0; i < alink->adapter_buswidth; i++)
     325           0 :                 scsi_probe_target(sb, i);
     326             : 
     327           0 :         return (0);
     328             : }
     329             : 
     330             : int
     331           0 : scsi_probe_target(struct scsibus_softc *sb, int target)
     332             : {
     333           0 :         struct scsi_link *alink = sb->adapter_link;
     334             :         struct scsi_link *link;
     335             :         struct scsi_report_luns_data *report;
     336             :         int i, nluns, lun;
     337             : 
     338           0 :         if (scsi_probe_lun(sb, target, 0) == EINVAL)
     339           0 :                 return (EINVAL);
     340             : 
     341           0 :         link = scsi_get_link(sb, target, 0);
     342           0 :         if (link == NULL)
     343           0 :                 return (ENXIO);
     344             : 
     345           0 :         if ((link->flags & (SDEV_UMASS | SDEV_ATAPI)) == 0 &&
     346           0 :             SCSISPC(link->inqdata.version) > 2) {
     347           0 :                 report = dma_alloc(sizeof(*report), PR_WAITOK);
     348           0 :                 if (report == NULL)
     349             :                         goto dumbscan;
     350             : 
     351           0 :                 if (scsi_report_luns(link, REPORT_NORMAL, report,
     352           0 :                     sizeof(*report), scsi_autoconf | SCSI_SILENT |
     353           0 :                     SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY |
     354           0 :                     SCSI_IGNORE_MEDIA_CHANGE, 10000) != 0) {
     355           0 :                         dma_free(report, sizeof(*report));
     356           0 :                         goto dumbscan;
     357             :                 }
     358             : 
     359             :                 /*
     360             :                  * XXX In theory we should check if data is full, which
     361             :                  * would indicate it needs to be enlarged and REPORT
     362             :                  * LUNS tried again. Solaris tries up to 3 times with
     363             :                  * larger sizes for data.
     364             :                  */
     365           0 :                 nluns = _4btol(report->length) / RPL_LUNDATA_SIZE;
     366           0 :                 for (i = 0; i < nluns; i++) {
     367           0 :                         if (report->luns[i].lundata[0] != 0)
     368             :                                 continue;
     369           0 :                         lun = report->luns[i].lundata[RPL_LUNDATA_T0LUN];
     370           0 :                         if (lun == 0)
     371             :                                 continue;
     372             : 
     373             :                         /* Probe the provided LUN. Don't check LUN 0. */
     374           0 :                         scsi_remove_link(sb, link);
     375           0 :                         scsi_probe_lun(sb, target, lun);
     376           0 :                         scsi_add_link(sb, link);
     377           0 :                 }
     378             : 
     379           0 :                 dma_free(report, sizeof(*report));
     380           0 :                 return (0);
     381             :         }
     382             : 
     383             : dumbscan:
     384           0 :         for (i = 1; i < alink->luns; i++) {
     385           0 :                 if (scsi_probe_lun(sb, target, i) == EINVAL)
     386             :                         break;
     387             :         }
     388             : 
     389           0 :         return (0);
     390           0 : }
     391             : 
     392             : int
     393           0 : scsi_probe(struct scsibus_softc *sb, int target, int lun)
     394             : {
     395           0 :         if (target == -1 && lun == -1)
     396           0 :                 return (scsi_probe_bus(sb));
     397             : 
     398             :         /* specific lun and wildcard target is bad */
     399           0 :         if (target == -1)
     400           0 :                 return (EINVAL);
     401             : 
     402           0 :         if (lun == -1)
     403           0 :                 return (scsi_probe_target(sb, target));
     404             : 
     405           0 :         return (scsi_probe_lun(sb, target, lun));
     406           0 : }
     407             : 
     408             : int
     409           0 : scsi_probe_lun(struct scsibus_softc *sb, int target, int lun)
     410             : {
     411           0 :         struct scsi_link *alink = sb->adapter_link;
     412             : 
     413           0 :         if (target < 0 || target >= alink->adapter_buswidth ||
     414           0 :             target == alink->adapter_target ||
     415           0 :             lun < 0 || lun >= alink->luns)
     416           0 :                 return (ENXIO);
     417             : 
     418           0 :         return (scsi_probedev(sb, target, lun));
     419           0 : }
     420             : 
     421             : int
     422           0 : scsi_detach_bus(struct scsibus_softc *sb, int flags)
     423             : {
     424           0 :         struct scsi_link *alink = sb->adapter_link;
     425             :         int i, err, rv = 0;
     426             : 
     427           0 :         for (i = 0; i < alink->adapter_buswidth; i++) {
     428           0 :                 err = scsi_detach_target(sb, i, flags);
     429           0 :                 if (err != 0 && err != ENXIO)
     430           0 :                         rv = err;
     431             :         }
     432             : 
     433           0 :         return (rv);
     434             : }
     435             : 
     436             : int
     437           0 : scsi_detach(struct scsibus_softc *sb, int target, int lun, int flags)
     438             : {
     439           0 :         if (target == -1 && lun == -1)
     440           0 :                 return (scsi_detach_bus(sb, flags));
     441             : 
     442             :         /* specific lun and wildcard target is bad */
     443           0 :         if (target == -1)
     444           0 :                 return (EINVAL);
     445             : 
     446           0 :         if (lun == -1)
     447           0 :                 return (scsi_detach_target(sb, target, flags));
     448             : 
     449           0 :         return (scsi_detach_lun(sb, target, lun, flags));
     450           0 : }
     451             : 
     452             : int
     453           0 : scsi_detach_target(struct scsibus_softc *sb, int target, int flags)
     454             : {
     455           0 :         struct scsi_link *alink = sb->adapter_link;
     456             :         int i, err, rv = 0;
     457             : 
     458           0 :         if (target < 0 || target >= alink->adapter_buswidth ||
     459           0 :             target == alink->adapter_target)
     460           0 :                 return (ENXIO);
     461             : 
     462           0 :         for (i = 0; i < alink->luns; i++) { /* nicer backwards? */
     463           0 :                 if (scsi_get_link(sb, target, i) == NULL)
     464             :                         continue;
     465             : 
     466           0 :                 err = scsi_detach_lun(sb, target, i, flags);
     467           0 :                 if (err != 0 && err != ENXIO)
     468           0 :                         rv = err;
     469             :         }
     470             : 
     471           0 :         return (rv);
     472           0 : }
     473             : 
     474             : int
     475           0 : scsi_detach_lun(struct scsibus_softc *sb, int target, int lun, int flags)
     476             : {
     477           0 :         struct scsi_link *alink = sb->adapter_link;
     478             :         struct scsi_link *link;
     479             :         int rv;
     480             : 
     481           0 :         if (target < 0 || target >= alink->adapter_buswidth ||
     482           0 :             target == alink->adapter_target ||
     483           0 :             lun < 0 || lun >= alink->luns)
     484           0 :                 return (ENXIO);
     485             : 
     486           0 :         link = scsi_get_link(sb, target, lun);
     487           0 :         if (link == NULL)
     488           0 :                 return (ENXIO);
     489             : 
     490           0 :         if (((flags & DETACH_FORCE) == 0) && (link->flags & SDEV_OPEN))
     491           0 :                 return (EBUSY);
     492             : 
     493             :         /* detaching a device from scsibus is a five step process... */
     494             : 
     495             :         /* 1. wake up processes sleeping for an xs */
     496           0 :         scsi_link_shutdown(link);
     497             : 
     498             :         /* 2. detach the device */
     499           0 :         rv = config_detach(link->device_softc, flags);
     500             : 
     501           0 :         if (rv != 0)
     502           0 :                 return (rv);
     503             : 
     504             :         /* 3. if its using the openings io allocator, clean it up */
     505           0 :         if (ISSET(link->flags, SDEV_OWN_IOPL)) {
     506           0 :                 scsi_iopool_destroy(link->pool);
     507           0 :                 free(link->pool, M_DEVBUF, sizeof(*link->pool));
     508           0 :         }
     509             : 
     510             :         /* 4. free up its state in the adapter */
     511           0 :         if (alink->adapter->dev_free != NULL)
     512           0 :                 alink->adapter->dev_free(link);
     513             : 
     514             :         /* 5. free up its state in the midlayer */
     515           0 :         if (link->id != NULL)
     516           0 :                 devid_free(link->id);
     517           0 :         scsi_remove_link(sb, link);
     518           0 :         free(link, M_DEVBUF, sizeof(*link));
     519             : 
     520           0 :         return (0);
     521           0 : }
     522             : 
     523             : struct scsi_link *
     524           0 : scsi_get_link(struct scsibus_softc *sb, int target, int lun)
     525             : {
     526             :         struct scsi_link *link;
     527             : 
     528           0 :         SLIST_FOREACH(link, &sb->sc_link_list, bus_list)
     529           0 :                 if (link->target == target && link->lun == lun)
     530           0 :                         return (link);
     531             : 
     532           0 :         return (NULL);
     533           0 : }
     534             : 
     535             : void
     536           0 : scsi_add_link(struct scsibus_softc *sb, struct scsi_link *link)
     537             : {
     538           0 :         SLIST_INSERT_HEAD(&sb->sc_link_list, link, bus_list);
     539           0 : }
     540             : 
     541             : void
     542           0 : scsi_remove_link(struct scsibus_softc *sb, struct scsi_link *link)
     543             : {
     544           0 :         SLIST_REMOVE(&sb->sc_link_list, link, scsi_link, bus_list);
     545           0 : }
     546             : 
     547             : void
     548           0 : scsi_strvis(u_char *dst, u_char *src, int len)
     549             : {
     550             :         u_char                          last;
     551             : 
     552             :         /* Trim leading and trailing whitespace and NULs. */
     553           0 :         while (len > 0 && (src[0] == ' ' || src[0] == '\t' || src[0] == '\n' ||
     554           0 :             src[0] == '\0' || src[0] == 0xff))
     555           0 :                 ++src, --len;
     556           0 :         while (len > 0 && (src[len-1] == ' ' || src[len-1] == '\t' ||
     557           0 :             src[len-1] == '\n' || src[len-1] == '\0' || src[len-1] == 0xff))
     558           0 :                 --len;
     559             : 
     560             :         last = 0xff;
     561           0 :         while (len > 0) {
     562           0 :                 switch (*src) {
     563             :                 case ' ':
     564             :                 case '\t':
     565             :                 case '\n':
     566             :                 case '\0':
     567             :                 case 0xff:
     568             :                         /* collapse whitespace and NULs to a single space */
     569           0 :                         if (last != ' ')
     570           0 :                                 *dst++ = ' ';
     571             :                         last = ' ';
     572           0 :                         break;
     573             :                 case '\\':
     574             :                         /* quote characters */
     575           0 :                         *dst++ = '\\';
     576           0 :                         *dst++ = '\\';
     577             :                         last = '\\';
     578           0 :                         break;
     579             :                 default:
     580           0 :                         if (*src < 0x20 || *src >= 0x80) {
     581             :                                 /* non-printable characters */
     582           0 :                                 *dst++ = '\\';
     583           0 :                                 *dst++ = ((*src & 0300) >> 6) + '0';
     584           0 :                                 *dst++ = ((*src & 0070) >> 3) + '0';
     585           0 :                                 *dst++ = ((*src & 0007) >> 0) + '0';
     586           0 :                         } else {
     587             :                                 /* normal characters */
     588           0 :                                 *dst++ = *src;
     589             :                         }
     590           0 :                         last = *src;
     591           0 :                         break;
     592             :                 }
     593           0 :                 ++src, --len;
     594             :         }
     595             : 
     596           0 :         *dst++ = 0;
     597           0 : }
     598             : 
     599             : struct scsi_quirk_inquiry_pattern {
     600             :         struct scsi_inquiry_pattern     pattern;
     601             :         u_int16_t                       quirks;
     602             : };
     603             : 
     604             : const struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = {
     605             :         {{T_CDROM, T_REMOV,
     606             :          "PLEXTOR", "CD-ROM PX-40TS", "1.01"},    SDEV_NOSYNC},
     607             : 
     608             :         {{T_DIRECT, T_FIXED,
     609             :          "MICROP  ", "1588-15MBSUN0669", ""},     SDEV_AUTOSAVE},
     610             :         {{T_DIRECT, T_FIXED,
     611             :          "DEC     ", "RZ55     (C) DEC", ""},     SDEV_AUTOSAVE},
     612             :         {{T_DIRECT, T_FIXED,
     613             :          "EMULEX  ", "MD21/S2     ESDI", "A00"},  SDEV_AUTOSAVE},
     614             :         {{T_DIRECT, T_FIXED,
     615             :          "IBMRAID ", "0662S",            ""},     SDEV_AUTOSAVE},
     616             :         {{T_DIRECT, T_FIXED,
     617             :          "IBM     ", "0663H",            ""},     SDEV_AUTOSAVE},
     618             :         {{T_DIRECT, T_FIXED,
     619             :          "IBM",         "0664",              ""},   SDEV_AUTOSAVE},
     620             :         {{T_DIRECT, T_FIXED,
     621             :          "IBM     ", "H3171-S2",         ""},       SDEV_AUTOSAVE},
     622             :         {{T_DIRECT, T_FIXED,
     623             :          "IBM     ", "KZ-C",                 ""},   SDEV_AUTOSAVE},
     624             :         /* Broken IBM disk */
     625             :         {{T_DIRECT, T_FIXED,
     626             :          ""      , "DFRSS2F",                ""},   SDEV_AUTOSAVE},
     627             :         {{T_DIRECT, T_FIXED,
     628             :          "QUANTUM ", "ELS85S          ", ""},       SDEV_AUTOSAVE},
     629             :         {{T_DIRECT, T_REMOV,
     630             :          "iomega", "jaz 1GB",                ""},   SDEV_NOTAGS},
     631             :         {{T_DIRECT, T_FIXED,
     632             :          "MICROP", "4421-07",                ""},     SDEV_NOTAGS},
     633             :         {{T_DIRECT, T_FIXED,
     634             :          "SEAGATE", "ST150176LW",        "0002"}, SDEV_NOTAGS},
     635             :         {{T_DIRECT, T_FIXED,
     636             :          "HP", "C3725S",             ""},     SDEV_NOTAGS},
     637             :         {{T_DIRECT, T_FIXED,
     638             :          "IBM", "DCAS",                      ""},     SDEV_NOTAGS},
     639             : 
     640             :         {{T_SEQUENTIAL, T_REMOV,
     641             :          "SONY    ", "SDT-5000        ", "3."},   SDEV_NOSYNC|SDEV_NOWIDE},
     642             :         {{T_SEQUENTIAL, T_REMOV,
     643             :          "WangDAT ", "Model 1300      ", "02.4"}, SDEV_NOSYNC|SDEV_NOWIDE},
     644             :         {{T_SEQUENTIAL, T_REMOV,
     645             :          "WangDAT ", "Model 2600      ", "01.7"}, SDEV_NOSYNC|SDEV_NOWIDE},
     646             :         {{T_SEQUENTIAL, T_REMOV,
     647             :          "WangDAT ", "Model 3200      ", "02.2"}, SDEV_NOSYNC|SDEV_NOWIDE},
     648             : 
     649             :         /* ATAPI device quirks */
     650             :         {{T_CDROM, T_REMOV,
     651             :          "CR-2801TE", "", "1.07"},              ADEV_NOSENSE},
     652             :         {{T_CDROM, T_REMOV,
     653             :          "CREATIVECD3630E", "", "AC101"},       ADEV_NOSENSE},
     654             :         {{T_CDROM, T_REMOV,
     655             :          "FX320S", "", "q01"},                  ADEV_NOSENSE},
     656             :         {{T_CDROM, T_REMOV,
     657             :          "GCD-R580B", "", "1.00"},              ADEV_LITTLETOC},
     658             :         {{T_CDROM, T_REMOV,
     659             :          "MATSHITA CR-574", "", "1.02"},        ADEV_NOCAPACITY},
     660             :         {{T_CDROM, T_REMOV,
     661             :          "MATSHITA CR-574", "", "1.06"},        ADEV_NOCAPACITY},
     662             :         {{T_CDROM, T_REMOV,
     663             :          "Memorex CRW-2642", "", "1.0g"},       ADEV_NOSENSE},
     664             :         {{T_CDROM, T_REMOV,
     665             :          "SANYO CRD-256P", "", "1.02"},         ADEV_NOCAPACITY},
     666             :         {{T_CDROM, T_REMOV,
     667             :          "SANYO CRD-254P", "", "1.02"},         ADEV_NOCAPACITY},
     668             :         {{T_CDROM, T_REMOV,
     669             :          "SANYO CRD-S54P", "", "1.08"},         ADEV_NOCAPACITY},
     670             :         {{T_CDROM, T_REMOV,
     671             :          "CD-ROM  CDR-S1", "", "1.70"},         ADEV_NOCAPACITY}, /* Sanyo */
     672             :         {{T_CDROM, T_REMOV,
     673             :          "CD-ROM  CDR-N16", "", "1.25"},        ADEV_NOCAPACITY}, /* Sanyo */
     674             :         {{T_CDROM, T_REMOV,
     675             :          "UJDCD8730", "", "1.14"},              ADEV_NODOORLOCK}, /* Acer */
     676             : };
     677             : 
     678             : 
     679             : void
     680           0 : scsibus_printlink(struct scsi_link *link)
     681             : {
     682           0 :         char                            vendor[33], product[65], revision[17];
     683             :         struct scsi_inquiry_data        *inqbuf;
     684             :         u_int8_t                        type;
     685             :         int                             removable;
     686             :         char                            *dtype = NULL, *qtype = NULL;
     687             : 
     688           0 :         inqbuf = &link->inqdata;
     689             : 
     690           0 :         type = inqbuf->device & SID_TYPE;
     691           0 :         removable = inqbuf->dev_qual2 & SID_REMOVABLE ? 1 : 0;
     692             : 
     693             :         /*
     694             :          * Figure out basic device type and qualifier.
     695             :          */
     696           0 :         switch (inqbuf->device & SID_QUAL) {
     697             :         case SID_QUAL_LU_OK:
     698             :                 qtype = "";
     699           0 :                 break;
     700             : 
     701             :         case SID_QUAL_LU_OFFLINE:
     702             :                 qtype = " offline";
     703           0 :                 break;
     704             : 
     705             :         case SID_QUAL_RSVD:
     706           0 :                 panic("scsibusprint: qualifier == SID_QUAL_RSVD");
     707             :         case SID_QUAL_BAD_LU:
     708           0 :                 panic("scsibusprint: qualifier == SID_QUAL_BAD_LU");
     709             : 
     710             :         default:
     711             :                 qtype = "";
     712             :                 dtype = "vendor-unique";
     713           0 :                 break;
     714             :         }
     715           0 :         if (dtype == NULL) {
     716           0 :                 switch (type) {
     717             :                 case T_DIRECT:
     718             :                         dtype = "direct";
     719           0 :                         break;
     720             :                 case T_SEQUENTIAL:
     721             :                         dtype = "sequential";
     722           0 :                         break;
     723             :                 case T_PRINTER:
     724             :                         dtype = "printer";
     725           0 :                         break;
     726             :                 case T_PROCESSOR:
     727             :                         dtype = "processor";
     728           0 :                         break;
     729             :                 case T_CDROM:
     730             :                         dtype = "cdrom";
     731           0 :                         break;
     732             :                 case T_WORM:
     733             :                         dtype = "worm";
     734           0 :                         break;
     735             :                 case T_SCANNER:
     736             :                         dtype = "scanner";
     737           0 :                         break;
     738             :                 case T_OPTICAL:
     739             :                         dtype = "optical";
     740           0 :                         break;
     741             :                 case T_CHANGER:
     742             :                         dtype = "changer";
     743           0 :                         break;
     744             :                 case T_COMM:
     745             :                         dtype = "communication";
     746           0 :                         break;
     747             :                 case T_ENCLOSURE:
     748             :                         dtype = "enclosure services";
     749           0 :                         break;
     750             :                 case T_RDIRECT:
     751             :                         dtype = "simplified direct";
     752           0 :                         break;
     753             :                 case T_NODEVICE:
     754           0 :                         panic("scsibusprint: device type T_NODEVICE");
     755             :                 default:
     756             :                         dtype = "unknown";
     757           0 :                         break;
     758             :                 }
     759             :         }
     760             : 
     761           0 :         scsi_strvis(vendor, inqbuf->vendor, 8);
     762           0 :         scsi_strvis(product, inqbuf->product, 16);
     763           0 :         scsi_strvis(revision, inqbuf->revision, 4);
     764             : 
     765           0 :         printf(" targ %d lun %d: <%s, %s, %s> ", link->target, link->lun,
     766             :             vendor, product, revision);
     767           0 :         if (link->flags & SDEV_ATAPI)
     768           0 :                 printf("ATAPI");
     769             :         else
     770           0 :                 printf("SCSI%d", SCSISPC(inqbuf->version));
     771           0 :         printf(" %d/%s %s%s", type, dtype, removable ? "removable" : "fixed",
     772             :             qtype);
     773             : 
     774           0 :         if (link->id != NULL && link->id->d_type != DEVID_NONE) {
     775           0 :                 u_int8_t *id = (u_int8_t *)(link->id + 1);
     776             :                 int i;
     777             : 
     778           0 :                 switch (link->id->d_type) {
     779             :                 case DEVID_NAA:
     780           0 :                         printf(" naa.");
     781           0 :                         break;
     782             :                 case DEVID_EUI:
     783           0 :                         printf(" eui.");
     784           0 :                         break;
     785             :                 case DEVID_T10:
     786           0 :                         printf(" t10.");
     787           0 :                         break;
     788             :                 case DEVID_SERIAL:
     789           0 :                         printf(" serial.");
     790           0 :                         break;
     791             :                 case DEVID_WWN:
     792           0 :                         printf(" wwn.");
     793           0 :                         break;
     794             :                 }
     795             : 
     796           0 :                 if (ISSET(link->id->d_flags, DEVID_F_PRINT)) {
     797           0 :                         for (i = 0; i < link->id->d_len; i++) {
     798           0 :                                 if (id[i] == '\0' || id[i] == ' ') {
     799             :                                         /* skip leading blanks */
     800             :                                         /* collapse multiple blanks into one */
     801           0 :                                         if (i > 0 && id[i-1] != id[i])
     802           0 :                                                 printf("_");
     803           0 :                                 } else if (id[i] < 0x20 || id[i] >= 0x80) {
     804             :                                         /* non-printable characters */
     805           0 :                                         printf("~");
     806           0 :                                 } else {
     807             :                                         /* normal characters */
     808           0 :                                         printf("%c", id[i]);
     809             :                                 }
     810             :                         }
     811             :                 } else {
     812           0 :                         for (i = 0; i < link->id->d_len; i++)
     813           0 :                                 printf("%02x", id[i]);
     814             :                 }
     815           0 :         }
     816           0 : }
     817             : 
     818             : /*
     819             :  * Print out autoconfiguration information for a subdevice.
     820             :  *
     821             :  * This is a slight abuse of 'standard' autoconfiguration semantics,
     822             :  * because 'print' functions don't normally print the colon and
     823             :  * device information.  However, in this case that's better than
     824             :  * either printing redundant information before the attach message,
     825             :  * or having the device driver call a special function to print out
     826             :  * the standard device information.
     827             :  */
     828             : int
     829           0 : scsibusprint(void *aux, const char *pnp)
     830             : {
     831           0 :         struct scsi_attach_args         *sa = aux;
     832             : 
     833           0 :         if (pnp != NULL)
     834           0 :                 printf("%s", pnp);
     835             : 
     836           0 :         scsibus_printlink(sa->sa_sc_link);
     837             : 
     838           0 :         return (UNCONF);
     839             : }
     840             : 
     841             : /*
     842             :  * Given a target and lun, ask the device what it is, and find the correct
     843             :  * driver table entry.
     844             :  *
     845             :  * Return 0 if further LUNs are possible, EINVAL if not.
     846             :  */
     847             : int
     848           0 : scsi_probedev(struct scsibus_softc *sb, int target, int lun)
     849             : {
     850             :         const struct scsi_quirk_inquiry_pattern *finger;
     851             :         struct scsi_inquiry_data *inqbuf, *usbinqbuf;
     852           0 :         struct scsi_attach_args sa;
     853             :         struct scsi_link *link, *link0;
     854             :         struct cfdata *cf;
     855           0 :         int priority, rslt = 0;
     856             : 
     857             :         /* Skip this slot if it is already attached and try the next LUN. */
     858           0 :         if (scsi_get_link(sb, target, lun) != NULL)
     859           0 :                 return (0);
     860             : 
     861           0 :         link = malloc(sizeof(*link), M_DEVBUF, M_NOWAIT);
     862           0 :         if (link == NULL)
     863           0 :                 return (EINVAL);
     864             : 
     865           0 :         *link = *sb->adapter_link;
     866           0 :         link->target = target;
     867           0 :         link->lun = lun;
     868           0 :         link->interpret_sense = scsi_interpret_sense;
     869           0 :         link->node_wwn = link->port_wwn = 0;
     870           0 :         TAILQ_INIT(&link->queue);
     871             : 
     872             :         SC_DEBUG(link, SDEV_DB2, ("scsi_link created.\n"));
     873             : 
     874             :         /* ask the adapter if this will be a valid device */
     875           0 :         if (sb->adapter_link->adapter->dev_probe != NULL &&
     876           0 :             sb->adapter_link->adapter->dev_probe(link) != 0) {
     877           0 :                 if (lun == 0)
     878           0 :                         rslt = EINVAL;
     879             :                 goto free;
     880             :         }
     881             : 
     882             :         /*
     883             :          * If we havent been given an io pool by now then fall back to
     884             :          * using link->openings.
     885             :          */
     886           0 :         if (link->pool == NULL) {
     887           0 :                 link->pool = malloc(sizeof(*link->pool),
     888             :                     M_DEVBUF, M_NOWAIT);
     889           0 :                 if (link->pool == NULL) {
     890             :                         rslt = ENOMEM;
     891           0 :                         goto bad;
     892             :                 }
     893           0 :                 scsi_iopool_init(link->pool, link,
     894             :                     scsi_default_get, scsi_default_put);
     895             : 
     896           0 :                 SET(link->flags, SDEV_OWN_IOPL);
     897           0 :         }
     898             : 
     899             :         /*
     900             :          * Tell drivers that are paying attention to avoid sync/wide/tags until
     901             :          * INQUIRY data has been processed and the quirks information is
     902             :          * complete. Some drivers set bits in quirks before we get here, so
     903             :          * just add NOTAGS, NOWIDE and NOSYNC.
     904             :          */
     905           0 :         link->quirks |= SDEV_NOSYNC | SDEV_NOWIDE | SDEV_NOTAGS;
     906             : 
     907             :         /*
     908             :          * Ask the device what it is
     909             :          */
     910             : #ifdef SCSIDEBUG
     911             :         if (((sb->sc_dev.dv_unit < 32) &&
     912             :              ((1U << sb->sc_dev.dv_unit) & scsidebug_buses)) &&
     913             :             ((target < 32) && ((1U << target) & scsidebug_targets)) &&
     914             :             ((lun < 32) && ((1U << lun) & scsidebug_luns)))
     915             :                 link->flags |= scsidebug_level;
     916             : #endif /* SCSIDEBUG */
     917             : 
     918           0 :         if (lun == 0) {
     919             :                 /* Clear any outstanding errors. */
     920           0 :                 scsi_test_unit_ready(link, TEST_READY_RETRIES,
     921           0 :                     scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST |
     922           0 :                     SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE);
     923           0 :         }
     924             : 
     925             :         /* Now go ask the device all about itself. */
     926           0 :         inqbuf = dma_alloc(sizeof(*inqbuf), PR_NOWAIT | PR_ZERO);
     927           0 :         if (inqbuf == NULL) {
     928             :                 rslt = ENOMEM;
     929           0 :                 goto bad;
     930             :         }
     931             : 
     932           0 :         rslt = scsi_inquire(link, inqbuf, scsi_autoconf | SCSI_SILENT);
     933           0 :         memcpy(&link->inqdata, inqbuf, sizeof(link->inqdata));
     934           0 :         dma_free(inqbuf, sizeof(*inqbuf));
     935             : 
     936           0 :         if (rslt != 0) {
     937             :                 SC_DEBUG(link, SDEV_DB2, ("Bad LUN. rslt = %i\n", rslt));
     938           0 :                 if (lun == 0)
     939           0 :                         rslt = EINVAL;
     940             :                 goto bad;
     941             :         }
     942             :         inqbuf = &link->inqdata;
     943             : 
     944           0 :         switch (inqbuf->device & SID_QUAL) {
     945             :         case SID_QUAL_RSVD:
     946             :         case SID_QUAL_BAD_LU:
     947             :         case SID_QUAL_LU_OFFLINE:
     948             :                 SC_DEBUG(link, SDEV_DB1, ("Bad LUN. SID_QUAL = 0x%02x\n",
     949             :                     inqbuf->device & SID_QUAL));
     950             :                 goto bad;
     951             : 
     952             :         case SID_QUAL_LU_OK:
     953           0 :                 if ((inqbuf->device & SID_TYPE) == T_NODEVICE) {
     954             :                         SC_DEBUG(link, SDEV_DB1,
     955             :                             ("Bad LUN. SID_TYPE = T_NODEVICE\n"));
     956             :                         goto bad;
     957             :                 }
     958             :                 break;
     959             : 
     960             :         default:
     961             :                 break;
     962             :         }
     963             : 
     964           0 :         scsi_devid(link);
     965             : 
     966           0 :         link0 = scsi_get_link(sb, target, 0);
     967           0 :         if (lun == 0 || link0 == NULL)
     968             :                 ;
     969           0 :         else if (link->flags & SDEV_UMASS)
     970             :                 ;
     971           0 :         else if (link->id != NULL && !DEVID_CMP(link0->id, link->id))
     972             :                 ;
     973           0 :         else if (memcmp(inqbuf, &link0->inqdata, sizeof(*inqbuf)) == 0) {
     974             :                 /* The device doesn't distinguish between LUNs. */
     975             :                 SC_DEBUG(link, SDEV_DB1, ("IDENTIFY not supported.\n"));
     976             :                 rslt = EINVAL;
     977           0 :                 goto free_devid;
     978             :         }
     979             : 
     980           0 :         finger = (const struct scsi_quirk_inquiry_pattern *)scsi_inqmatch(
     981             :             inqbuf, scsi_quirk_patterns,
     982             :             nitems(scsi_quirk_patterns),
     983             :             sizeof(scsi_quirk_patterns[0]), &priority);
     984             : 
     985             :         /*
     986             :          * Based upon the inquiry flags we got back, and if we're
     987             :          * at SCSI-2 or better, remove some limiting quirks.
     988             :          */
     989           0 :         if (SCSISPC(inqbuf->version) >= 2) {
     990           0 :                 if ((inqbuf->flags & SID_CmdQue) != 0)
     991           0 :                         link->quirks &= ~SDEV_NOTAGS;
     992           0 :                 if ((inqbuf->flags & SID_Sync) != 0)
     993           0 :                         link->quirks &= ~SDEV_NOSYNC;
     994           0 :                 if ((inqbuf->flags & SID_WBus16) != 0)
     995           0 :                         link->quirks &= ~SDEV_NOWIDE;
     996             :         } else
     997             :                 /* Older devices do not have SYNCHRONIZE CACHE capability. */
     998           0 :                 link->quirks |= SDEV_NOSYNCCACHE;
     999             : 
    1000             :         /*
    1001             :          * Now apply any quirks from the table.
    1002             :          */
    1003           0 :         if (priority != 0)
    1004           0 :                 link->quirks |= finger->quirks;
    1005             : 
    1006             :         /*
    1007             :          * If the device can't use tags, >1 opening may confuse it.
    1008             :          */
    1009           0 :         if (ISSET(link->quirks, SDEV_NOTAGS))
    1010           0 :                 link->openings = 1;
    1011             : 
    1012             :         /*
    1013             :          * note what BASIC type of device it is
    1014             :          */
    1015           0 :         if ((inqbuf->dev_qual2 & SID_REMOVABLE) != 0)
    1016           0 :                 link->flags |= SDEV_REMOVABLE;
    1017             : 
    1018           0 :         sa.sa_sc_link = link;
    1019           0 :         sa.sa_inqbuf = &link->inqdata;
    1020             : 
    1021           0 :         if ((cf = config_search(scsibussubmatch, (struct device *)sb,
    1022           0 :             &sa)) == 0) {
    1023           0 :                 scsibusprint(&sa, sb->sc_dev.dv_xname);
    1024           0 :                 printf(" not configured\n");
    1025           0 :                 goto free_devid;
    1026             :         }
    1027             : 
    1028             :         /*
    1029             :          * Braindead USB devices, especially some x-in-1 media readers, try to
    1030             :          * 'help' by pretending any LUN is actually LUN 0 until they see a
    1031             :          * different LUN used in a command. So do an INQUIRY on LUN 1 at this
    1032             :          * point to prevent such helpfulness before it causes confusion.
    1033             :          */
    1034           0 :         if (lun == 0 && (link->flags & SDEV_UMASS) &&
    1035           0 :             scsi_get_link(sb, target, 1) == NULL && link->luns > 1 &&
    1036           0 :             (usbinqbuf = dma_alloc(sizeof(*usbinqbuf), M_NOWAIT)) != NULL) {
    1037             : 
    1038           0 :                 link->lun = 1;
    1039           0 :                 scsi_inquire(link, usbinqbuf, scsi_autoconf | SCSI_SILENT);
    1040           0 :                 link->lun = 0;
    1041             : 
    1042           0 :                 dma_free(usbinqbuf, sizeof(*usbinqbuf));
    1043           0 :         }
    1044             : 
    1045           0 :         scsi_add_link(sb, link);
    1046             : 
    1047             :         /*
    1048             :          * Generate a TEST_UNIT_READY command. This gives drivers waiting for
    1049             :          * valid quirks data a chance to set wide/sync/tag options
    1050             :          * appropriately. It also clears any outstanding ACA conditions that
    1051             :          * INQUIRY may leave behind.
    1052             :          *
    1053             :          * Do this now so that any messages generated by config_attach() do not
    1054             :          * have negotiation messages inserted into their midst.
    1055             :          */
    1056           0 :         scsi_test_unit_ready(link, TEST_READY_RETRIES,
    1057           0 :             scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST |
    1058           0 :             SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE);
    1059             : 
    1060           0 :         config_attach((struct device *)sb, cf, &sa, scsibusprint);
    1061             : 
    1062           0 :         return (0);
    1063             : 
    1064             : free_devid:
    1065           0 :         if (link->id)
    1066           0 :                 devid_free(link->id);
    1067             : bad:
    1068           0 :         if (ISSET(link->flags, SDEV_OWN_IOPL))
    1069           0 :                 free(link->pool, M_DEVBUF, sizeof(*link->pool));
    1070             : 
    1071           0 :         if (sb->adapter_link->adapter->dev_free != NULL)
    1072           0 :                 sb->adapter_link->adapter->dev_free(link);
    1073             : free:
    1074           0 :         free(link, M_DEVBUF, sizeof(*link));
    1075           0 :         return (rslt);
    1076           0 : }
    1077             : 
    1078             : /*
    1079             :  * Return a priority based on how much of the inquiry data matches
    1080             :  * the patterns for the particular driver.
    1081             :  */
    1082             : const void *
    1083           0 : scsi_inqmatch(struct scsi_inquiry_data *inqbuf, const void *_base,
    1084             :     int nmatches, int matchsize, int *bestpriority)
    1085             : {
    1086             :         u_int8_t                        type;
    1087             :         int                             removable;
    1088             :         const void                      *bestmatch;
    1089             :         const unsigned char             *base = (const unsigned char *)_base;
    1090             : 
    1091             :         /* Include the qualifier to catch vendor-unique types. */
    1092           0 :         type = inqbuf->device;
    1093           0 :         removable = inqbuf->dev_qual2 & SID_REMOVABLE ? T_REMOV : T_FIXED;
    1094             : 
    1095           0 :         for (*bestpriority = 0, bestmatch = 0; nmatches--; base += matchsize) {
    1096           0 :                 struct scsi_inquiry_pattern *match = (void *)base;
    1097             :                 int priority, len;
    1098             : 
    1099           0 :                 if (type != match->type)
    1100           0 :                         continue;
    1101           0 :                 if (removable != match->removable)
    1102           0 :                         continue;
    1103             :                 priority = 2;
    1104           0 :                 len = strlen(match->vendor);
    1105           0 :                 if (bcmp(inqbuf->vendor, match->vendor, len))
    1106           0 :                         continue;
    1107           0 :                 priority += len;
    1108           0 :                 len = strlen(match->product);
    1109           0 :                 if (bcmp(inqbuf->product, match->product, len))
    1110           0 :                         continue;
    1111           0 :                 priority += len;
    1112           0 :                 len = strlen(match->revision);
    1113           0 :                 if (bcmp(inqbuf->revision, match->revision, len))
    1114           0 :                         continue;
    1115           0 :                 priority += len;
    1116             : 
    1117             : #ifdef SCSIDEBUG
    1118             :                 printf("scsi_inqmatch: %d/%d/%d <%s, %s, %s>\n",
    1119             :                     priority, match->type, match->removable,
    1120             :                     match->vendor, match->product, match->revision);
    1121             : #endif
    1122           0 :                 if (priority > *bestpriority) {
    1123           0 :                         *bestpriority = priority;
    1124             :                         bestmatch = base;
    1125           0 :                 }
    1126           0 :         }
    1127             : 
    1128           0 :         return (bestmatch);
    1129             : }
    1130             : 
    1131             : void
    1132           0 : scsi_devid(struct scsi_link *link)
    1133             : {
    1134             :         struct {
    1135             :                 struct scsi_vpd_hdr hdr;
    1136             :                 u_int8_t list[32];
    1137             :         } __packed *pg;
    1138             :         int pg80 = 0, pg83 = 0, i;
    1139             :         size_t len;
    1140             : 
    1141           0 :         if (link->id != NULL)
    1142           0 :                 return;
    1143             : 
    1144           0 :         pg = dma_alloc(sizeof(*pg), PR_WAITOK | PR_ZERO);
    1145             : 
    1146           0 :         if (SCSISPC(link->inqdata.version) >= 2) {
    1147           0 :                 if (scsi_inquire_vpd(link, pg, sizeof(*pg), SI_PG_SUPPORTED,
    1148           0 :                     scsi_autoconf) != 0)
    1149             :                         goto wwn;
    1150             : 
    1151           0 :                 len = MIN(sizeof(pg->list), _2btol(pg->hdr.page_length));
    1152           0 :                 for (i = 0; i < len; i++) {
    1153           0 :                         switch (pg->list[i]) {
    1154             :                         case SI_PG_SERIAL:
    1155             :                                 pg80 = 1;
    1156           0 :                                 break;
    1157             :                         case SI_PG_DEVID:
    1158             :                                 pg83 = 1;
    1159           0 :                                 break;
    1160             :                         }
    1161             :                 }
    1162             : 
    1163           0 :                 if (pg83 && scsi_devid_pg83(link) == 0)
    1164             :                         goto done;
    1165           0 :                 if (pg80 && scsi_devid_pg80(link) == 0)
    1166             :                         goto done;
    1167             :         }
    1168             : 
    1169             : wwn:
    1170           0 :         scsi_devid_wwn(link);
    1171             : done:
    1172           0 :         dma_free(pg, sizeof(*pg));
    1173           0 : }
    1174             : 
    1175             : int
    1176           0 : scsi_devid_pg83(struct scsi_link *link)
    1177             : {
    1178             :         struct scsi_vpd_hdr *hdr = NULL;
    1179             :         struct scsi_vpd_devid_hdr dhdr, chdr;
    1180             :         u_int8_t *pg = NULL, *id;
    1181             :         int type, idtype = 0;
    1182             :         u_char idflags;
    1183             :         int len, pos;
    1184             :         int rv;
    1185             : 
    1186           0 :         hdr = dma_alloc(sizeof(*hdr), PR_WAITOK | PR_ZERO);
    1187             : 
    1188           0 :         rv = scsi_inquire_vpd(link, hdr, sizeof(*hdr), SI_PG_DEVID,
    1189           0 :             scsi_autoconf);
    1190           0 :         if (rv != 0)
    1191             :                 goto done;
    1192             : 
    1193           0 :         len = sizeof(*hdr) + _2btol(hdr->page_length);
    1194           0 :         pg = dma_alloc(len, PR_WAITOK | PR_ZERO);
    1195             : 
    1196           0 :         rv = scsi_inquire_vpd(link, pg, len, SI_PG_DEVID, scsi_autoconf);
    1197           0 :         if (rv != 0)
    1198             :                 goto done;
    1199             : 
    1200             :         pos = sizeof(*hdr);
    1201             : 
    1202           0 :         do {
    1203           0 :                 if (len - pos < sizeof(dhdr)) {
    1204             :                         rv = EIO;
    1205           0 :                         goto done;
    1206             :                 }
    1207           0 :                 memcpy(&dhdr, &pg[pos], sizeof(dhdr));
    1208           0 :                 pos += sizeof(dhdr);
    1209           0 :                 if (len - pos < dhdr.len) {
    1210             :                         rv = EIO;
    1211           0 :                         goto done;
    1212             :                 }
    1213             : 
    1214           0 :                 if (VPD_DEVID_ASSOC(dhdr.flags) == VPD_DEVID_ASSOC_LU) {
    1215           0 :                         type = VPD_DEVID_TYPE(dhdr.flags);
    1216           0 :                         switch (type) {
    1217             :                         case VPD_DEVID_TYPE_NAA:
    1218             :                         case VPD_DEVID_TYPE_EUI64:
    1219             :                         case VPD_DEVID_TYPE_T10:
    1220           0 :                                 if (type >= idtype) {
    1221             :                                         idtype = type;
    1222             : 
    1223             :                                         chdr = dhdr;
    1224           0 :                                         id = &pg[pos];
    1225           0 :                                 }
    1226             :                                 break;
    1227             : 
    1228             :                         default:
    1229             :                                 /* skip */
    1230             :                                 break;
    1231             :                         }
    1232             :                 }
    1233             : 
    1234           0 :                 pos += dhdr.len;
    1235           0 :         } while (idtype != VPD_DEVID_TYPE_NAA && len != pos);
    1236             : 
    1237           0 :         if (idtype > 0) {
    1238           0 :                 switch (VPD_DEVID_TYPE(chdr.flags)) {
    1239             :                 case VPD_DEVID_TYPE_NAA:
    1240             :                         idtype = DEVID_NAA;
    1241           0 :                         break;
    1242             :                 case VPD_DEVID_TYPE_EUI64:
    1243             :                         idtype = DEVID_EUI;
    1244           0 :                         break;
    1245             :                 case VPD_DEVID_TYPE_T10:
    1246             :                         idtype = DEVID_T10;
    1247           0 :                         break;
    1248             :                 }
    1249           0 :                 switch (VPD_DEVID_CODE(chdr.pi_code)) {
    1250             :                 case VPD_DEVID_CODE_ASCII:
    1251             :                 case VPD_DEVID_CODE_UTF8:
    1252             :                         idflags = DEVID_F_PRINT;
    1253           0 :                         break;
    1254             :                 default:
    1255             :                         idflags = 0;
    1256           0 :                         break;
    1257             :                 }
    1258           0 :                 link->id = devid_alloc(idtype, idflags, chdr.len, id);
    1259           0 :         } else
    1260             :                 rv = ENODEV;
    1261             : 
    1262             : done:
    1263           0 :         if (pg)
    1264           0 :                 dma_free(pg, len);
    1265           0 :         if (hdr)
    1266           0 :                 dma_free(hdr, sizeof(*hdr));
    1267           0 :         return (rv);
    1268             : }
    1269             : 
    1270             : int
    1271           0 : scsi_devid_pg80(struct scsi_link *link)
    1272             : {
    1273             :         struct scsi_vpd_hdr *hdr = NULL;
    1274             :         u_int8_t *pg = NULL;
    1275             :         char *id;
    1276             :         size_t idlen;
    1277             :         int pglen, len;
    1278             :         int rv;
    1279             : 
    1280           0 :         hdr = dma_alloc(sizeof(*hdr), PR_WAITOK | PR_ZERO);
    1281             : 
    1282           0 :         rv = scsi_inquire_vpd(link, hdr, sizeof(*hdr), SI_PG_SERIAL,
    1283           0 :             scsi_autoconf);
    1284           0 :         if (rv != 0)
    1285             :                 goto freehdr;
    1286             : 
    1287           0 :         len = _2btol(hdr->page_length);
    1288           0 :         if (len == 0) {
    1289             :                 rv = EINVAL;
    1290           0 :                 goto freehdr;
    1291             :         }
    1292             : 
    1293           0 :         pglen = sizeof(*hdr) + len;
    1294           0 :         pg = dma_alloc(pglen, PR_WAITOK | PR_ZERO);
    1295             : 
    1296           0 :         rv = scsi_inquire_vpd(link, pg, pglen, SI_PG_SERIAL, scsi_autoconf);
    1297           0 :         if (rv != 0)
    1298             :                 goto free;
    1299             : 
    1300             :         idlen = sizeof(link->inqdata.vendor) +
    1301           0 :             sizeof(link->inqdata.product) + len;
    1302           0 :         id = malloc(idlen, M_TEMP, M_WAITOK);
    1303           0 :         memcpy(id, link->inqdata.vendor, sizeof(link->inqdata.vendor));
    1304           0 :         memcpy(id + sizeof(link->inqdata.vendor), link->inqdata.product,
    1305             :             sizeof(link->inqdata.product));
    1306           0 :         memcpy(id + sizeof(link->inqdata.vendor) +
    1307             :             sizeof(link->inqdata.product), pg + sizeof(*hdr), len);
    1308             : 
    1309           0 :         link->id = devid_alloc(DEVID_SERIAL, DEVID_F_PRINT,
    1310           0 :             sizeof(link->inqdata.vendor) + sizeof(link->inqdata.product) + len,
    1311             :             id);
    1312             : 
    1313           0 :         free(id, M_TEMP, idlen);
    1314             : 
    1315             : free:
    1316           0 :         dma_free(pg, pglen);
    1317             : freehdr:
    1318           0 :         dma_free(hdr, sizeof(*hdr));
    1319           0 :         return (rv);
    1320             : }
    1321             : 
    1322             : int
    1323           0 : scsi_devid_wwn(struct scsi_link *link)
    1324             : {
    1325           0 :         u_int64_t wwnn;
    1326             : 
    1327           0 :         if (link->lun != 0 || link->node_wwn == 0)
    1328           0 :                 return (EOPNOTSUPP);
    1329             : 
    1330           0 :         wwnn = htobe64(link->node_wwn);
    1331           0 :         link->id = devid_alloc(DEVID_WWN, 0, sizeof(wwnn), (u_int8_t *)&wwnn);
    1332             : 
    1333           0 :         return (0);
    1334           0 : }
    1335             : 
    1336             : /*
    1337             :  * scsi_minphys member of struct scsi_adapter for drivers which don't
    1338             :  * need any specific routine.
    1339             :  */
    1340             : void
    1341           0 : scsi_minphys(struct buf *bp, struct scsi_link *sl)
    1342             : {
    1343           0 :         minphys(bp);
    1344           0 : }
    1345             : 
    1346             : struct devid *
    1347           0 : devid_alloc(u_int8_t type, u_int8_t flags, u_int8_t len, u_int8_t *id)
    1348             : {
    1349             :         struct devid *d;
    1350             : 
    1351           0 :         d = malloc(sizeof(*d) + len, M_DEVBUF, M_WAITOK|M_CANFAIL);
    1352           0 :         if (d == NULL)
    1353           0 :                 return (NULL);
    1354             : 
    1355           0 :         d->d_type = type;
    1356           0 :         d->d_flags = flags;
    1357           0 :         d->d_len = len;
    1358           0 :         d->d_refcount = 1;
    1359           0 :         memcpy(d + 1, id, len);
    1360             : 
    1361           0 :         return (d);
    1362           0 : }
    1363             : 
    1364             : struct devid *
    1365           0 : devid_copy(struct devid *d)
    1366             : {
    1367           0 :         d->d_refcount++;
    1368           0 :         return (d);
    1369             : }
    1370             : 
    1371             : void
    1372           0 : devid_free(struct devid *d)
    1373             : {
    1374           0 :         if (--d->d_refcount == 0)
    1375           0 :                 free(d, M_DEVBUF, sizeof(*d) + d->d_len);
    1376           0 : }

Generated by: LCOV version 1.13