[BACK]Return to scsiconf.c CVS log [TXT][DIR] Up to [local] / sys / scsi

Annotation of sys/scsi/scsiconf.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb