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

Annotation of sys/scsi/sd.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: sd.c,v 1.136 2007/06/23 19:19:49 krw Exp $    */
        !             2: /*     $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Charles M. Hannum.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *        This product includes software developed by the NetBSD
        !            22:  *        Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: /*
        !            41:  * Originally written by Julian Elischer (julian@dialix.oz.au)
        !            42:  * for TRW Financial Systems for use under the MACH(2.5) operating system.
        !            43:  *
        !            44:  * TRW Financial Systems, in accordance with their agreement with Carnegie
        !            45:  * Mellon University, makes this software available to CMU to distribute
        !            46:  * or use in any manner that they see fit as long as this message is kept with
        !            47:  * the software. For this reason TFS also grants any other persons or
        !            48:  * organisations permission to use or modify this software.
        !            49:  *
        !            50:  * TFS supplies this software to be publicly redistributed
        !            51:  * on the understanding that TFS is not responsible for the correct
        !            52:  * functioning of this software in any circumstances.
        !            53:  *
        !            54:  * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992
        !            55:  */
        !            56:
        !            57: #include <sys/types.h>
        !            58: #include <sys/param.h>
        !            59: #include <sys/systm.h>
        !            60: #include <sys/timeout.h>
        !            61: #include <sys/file.h>
        !            62: #include <sys/stat.h>
        !            63: #include <sys/ioctl.h>
        !            64: #include <sys/mtio.h>
        !            65: #include <sys/buf.h>
        !            66: #include <sys/uio.h>
        !            67: #include <sys/malloc.h>
        !            68: #include <sys/errno.h>
        !            69: #include <sys/device.h>
        !            70: #include <sys/disklabel.h>
        !            71: #include <sys/disk.h>
        !            72: #include <sys/proc.h>
        !            73: #include <sys/conf.h>
        !            74: #include <sys/scsiio.h>
        !            75:
        !            76: #include <scsi/scsi_all.h>
        !            77: #include <scsi/scsi_disk.h>
        !            78: #include <scsi/scsiconf.h>
        !            79: #include <scsi/sdvar.h>
        !            80:
        !            81: #include <ufs/ffs/fs.h>                        /* for BBSIZE and SBSIZE */
        !            82:
        !            83: #include <sys/vnode.h>
        !            84:
        !            85: int    sdmatch(struct device *, void *, void *);
        !            86: void   sdattach(struct device *, struct device *, void *);
        !            87: int    sdactivate(struct device *, enum devact);
        !            88: int    sddetach(struct device *, int);
        !            89:
        !            90: void   sdminphys(struct buf *);
        !            91: void   sdgetdisklabel(dev_t, struct sd_softc *, struct disklabel *, int);
        !            92: void   sdstart(void *);
        !            93: void   sdrestart(void *);
        !            94: void   sddone(struct scsi_xfer *);
        !            95: void   sd_shutdown(void *);
        !            96: int    sd_reassign_blocks(struct sd_softc *, u_long);
        !            97: int    sd_interpret_sense(struct scsi_xfer *);
        !            98: int    sd_get_parms(struct sd_softc *, struct disk_parms *, int);
        !            99: void   sd_flush(struct sd_softc *, int);
        !           100: void   sd_kill_buffers(struct sd_softc *);
        !           101:
        !           102: void   viscpy(u_char *, u_char *, int);
        !           103:
        !           104: int    sd_ioctl_inquiry(struct sd_softc *, struct dk_inquiry *);
        !           105:
        !           106: struct cfattach sd_ca = {
        !           107:        sizeof(struct sd_softc), sdmatch, sdattach,
        !           108:        sddetach, sdactivate
        !           109: };
        !           110:
        !           111: struct cfdriver sd_cd = {
        !           112:        NULL, "sd", DV_DISK
        !           113: };
        !           114:
        !           115: struct dkdriver sddkdriver = { sdstrategy };
        !           116:
        !           117: struct scsi_device sd_switch = {
        !           118:        sd_interpret_sense,     /* check out error handler first */
        !           119:        sdstart,                /* have a queue, served by this */
        !           120:        NULL,                   /* have no async handler */
        !           121:        sddone,                 /* deal with stats at interrupt time */
        !           122: };
        !           123:
        !           124: const struct scsi_inquiry_pattern sd_patterns[] = {
        !           125:        {T_DIRECT, T_FIXED,
        !           126:         "",         "",                 ""},
        !           127:        {T_DIRECT, T_REMOV,
        !           128:         "",         "",                 ""},
        !           129:        {T_RDIRECT, T_FIXED,
        !           130:         "",         "",                 ""},
        !           131:        {T_RDIRECT, T_REMOV,
        !           132:         "",         "",                 ""},
        !           133:        {T_OPTICAL, T_FIXED,
        !           134:         "",         "",                 ""},
        !           135:        {T_OPTICAL, T_REMOV,
        !           136:         "",         "",                 ""},
        !           137: };
        !           138:
        !           139: #define sdlock(softc)   disk_lock(&(softc)->sc_dk)
        !           140: #define sdunlock(softc) disk_unlock(&(softc)->sc_dk)
        !           141: #define sdlookup(unit) (struct sd_softc *)device_lookup(&sd_cd, (unit))
        !           142:
        !           143: int
        !           144: sdmatch(struct device *parent, void *match, void *aux)
        !           145: {
        !           146:        struct scsi_attach_args *sa = aux;
        !           147:        int priority;
        !           148:
        !           149:        (void)scsi_inqmatch(sa->sa_inqbuf,
        !           150:            sd_patterns, sizeof(sd_patterns)/sizeof(sd_patterns[0]),
        !           151:            sizeof(sd_patterns[0]), &priority);
        !           152:
        !           153:        return (priority);
        !           154: }
        !           155:
        !           156: /*
        !           157:  * The routine called by the low level scsi routine when it discovers
        !           158:  * a device suitable for this driver.
        !           159:  */
        !           160: void
        !           161: sdattach(struct device *parent, struct device *self, void *aux)
        !           162: {
        !           163:        int error, result;
        !           164:        struct sd_softc *sd = (struct sd_softc *)self;
        !           165:        struct disk_parms *dp = &sd->params;
        !           166:        struct scsi_attach_args *sa = aux;
        !           167:        struct scsi_link *sc_link = sa->sa_sc_link;
        !           168:
        !           169:        SC_DEBUG(sc_link, SDEV_DB2, ("sdattach:\n"));
        !           170:
        !           171:        /*
        !           172:         * Store information needed to contact our base driver
        !           173:         */
        !           174:        sd->sc_link = sc_link;
        !           175:        sc_link->device = &sd_switch;
        !           176:        sc_link->device_softc = sd;
        !           177:
        !           178:        /*
        !           179:         * Initialize and attach the disk structure.
        !           180:         */
        !           181:        sd->sc_dk.dk_driver = &sddkdriver;
        !           182:        sd->sc_dk.dk_name = sd->sc_dev.dv_xname;
        !           183:        disk_attach(&sd->sc_dk);
        !           184:
        !           185:        if ((sc_link->flags & SDEV_ATAPI) && (sc_link->flags & SDEV_REMOVABLE))
        !           186:                sc_link->quirks |= SDEV_NOSYNCCACHE;
        !           187:
        !           188:        if (!(sc_link->inqdata.flags & SID_RelAdr))
        !           189:                sc_link->quirks |= SDEV_ONLYBIG;
        !           190:
        !           191:        /*
        !           192:         * Note if this device is ancient.  This is used in sdminphys().
        !           193:         */
        !           194:        if (!(sc_link->flags & SDEV_ATAPI) &&
        !           195:            SCSISPC(sa->sa_inqbuf->version) == 0)
        !           196:                sd->flags |= SDF_ANCIENT;
        !           197:
        !           198:        /*
        !           199:         * Use the subdriver to request information regarding
        !           200:         * the drive. We cannot use interrupts yet, so the
        !           201:         * request must specify this.
        !           202:         */
        !           203:        printf("\n");
        !           204:
        !           205:        timeout_set(&sd->sc_timeout, sdrestart, sd);
        !           206:
        !           207:        /* Spin up non-UMASS devices ready or not. */
        !           208:        if ((sd->sc_link->flags & SDEV_UMASS) == 0)
        !           209:                scsi_start(sc_link, SSS_START, scsi_autoconf | SCSI_SILENT |
        !           210:                    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE);
        !           211:
        !           212:        /* Check that it is still responding and ok. */
        !           213:        error = scsi_test_unit_ready(sd->sc_link, TEST_READY_RETRIES,
        !           214:            scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST |
        !           215:            SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT);
        !           216:
        !           217:        if (error)
        !           218:                result = SDGP_RESULT_OFFLINE;
        !           219:        else
        !           220:                result = sd_get_parms(sd, &sd->params,
        !           221:                    scsi_autoconf | SCSI_SILENT | SCSI_IGNORE_MEDIA_CHANGE);
        !           222:
        !           223:        printf("%s: ", sd->sc_dev.dv_xname);
        !           224:        switch (result) {
        !           225:        case SDGP_RESULT_OK:
        !           226:                printf("%lldMB, %lu cyl, %lu head, %lu sec, %lu bytes/sec, %lld sec total",
        !           227:                    dp->disksize / (1048576 / dp->blksize), dp->cyls,
        !           228:                    dp->heads, dp->sectors, dp->blksize, dp->disksize);
        !           229:                break;
        !           230:
        !           231:        case SDGP_RESULT_OFFLINE:
        !           232:                printf("drive offline");
        !           233:                break;
        !           234:
        !           235: #ifdef DIAGNOSTIC
        !           236:        default:
        !           237:                panic("sdattach: unknown result (%#x) from get_parms", result);
        !           238:                break;
        !           239: #endif
        !           240:        }
        !           241:        printf("\n");
        !           242:
        !           243:        /*
        !           244:         * Establish a shutdown hook so that we can ensure that
        !           245:         * our data has actually made it onto the platter at
        !           246:         * shutdown time.  Note that this relies on the fact
        !           247:         * that the shutdown hook code puts us at the head of
        !           248:         * the list (thus guaranteeing that our hook runs before
        !           249:         * our ancestors').
        !           250:         */
        !           251:        if ((sd->sc_sdhook =
        !           252:            shutdownhook_establish(sd_shutdown, sd)) == NULL)
        !           253:                printf("%s: WARNING: unable to establish shutdown hook\n",
        !           254:                    sd->sc_dev.dv_xname);
        !           255: }
        !           256:
        !           257: int
        !           258: sdactivate(struct device *self, enum devact act)
        !           259: {
        !           260:        int rv = 0;
        !           261:
        !           262:        switch (act) {
        !           263:        case DVACT_ACTIVATE:
        !           264:                break;
        !           265:
        !           266:        case DVACT_DEACTIVATE:
        !           267:                /*
        !           268:                 * Nothing to do; we key off the device's DVF_ACTIVATE.
        !           269:                 */
        !           270:                break;
        !           271:        }
        !           272:
        !           273:        return (rv);
        !           274: }
        !           275:
        !           276:
        !           277: int
        !           278: sddetach(struct device *self, int flags)
        !           279: {
        !           280:        struct sd_softc *sd = (struct sd_softc *)self;
        !           281:        int bmaj, cmaj, mn;
        !           282:
        !           283:        sd_kill_buffers(sd);
        !           284:
        !           285:        /* Locate the lowest minor number to be detached. */
        !           286:        mn = DISKMINOR(self->dv_unit, 0);
        !           287:
        !           288:        for (bmaj = 0; bmaj < nblkdev; bmaj++)
        !           289:                if (bdevsw[bmaj].d_open == sdopen)
        !           290:                        vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK);
        !           291:        for (cmaj = 0; cmaj < nchrdev; cmaj++)
        !           292:                if (cdevsw[cmaj].d_open == sdopen)
        !           293:                        vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR);
        !           294:
        !           295:        /* Get rid of the shutdown hook. */
        !           296:        if (sd->sc_sdhook != NULL)
        !           297:                shutdownhook_disestablish(sd->sc_sdhook);
        !           298:
        !           299:        /* Detach disk. */
        !           300:        disk_detach(&sd->sc_dk);
        !           301:
        !           302:        return (0);
        !           303: }
        !           304:
        !           305: /*
        !           306:  * Open the device. Make sure the partition info is as up-to-date as can be.
        !           307:  */
        !           308: int
        !           309: sdopen(dev_t dev, int flag, int fmt, struct proc *p)
        !           310: {
        !           311:        struct scsi_link *sc_link;
        !           312:        struct sd_softc *sd;
        !           313:        int error = 0, part, rawopen, unit;
        !           314:
        !           315:        unit = DISKUNIT(dev);
        !           316:        part = DISKPART(dev);
        !           317:
        !           318:        rawopen = (part == RAW_PART) && (fmt == S_IFCHR);
        !           319:
        !           320:        sd = sdlookup(unit);
        !           321:        if (sd == NULL)
        !           322:                return (ENXIO);
        !           323:
        !           324:        sc_link = sd->sc_link;
        !           325:        SC_DEBUG(sc_link, SDEV_DB1,
        !           326:            ("sdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
        !           327:            sd_cd.cd_ndevs, part));
        !           328:
        !           329:        if ((error = sdlock(sd)) != 0) {
        !           330:                device_unref(&sd->sc_dev);
        !           331:                return (error);
        !           332:        }
        !           333:
        !           334:        if (sd->sc_dk.dk_openmask != 0) {
        !           335:                /*
        !           336:                 * If any partition is open, but the disk has been invalidated,
        !           337:                 * disallow further opens of non-raw partition.
        !           338:                 */
        !           339:                if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
        !           340:                        if (rawopen)
        !           341:                                goto out;
        !           342:                        error = EIO;
        !           343:                        goto bad;
        !           344:                }
        !           345:        } else {
        !           346:                /* Spin up non-UMASS devices ready or not. */
        !           347:                if ((sd->sc_link->flags & SDEV_UMASS) == 0)
        !           348:                        scsi_start(sc_link, SSS_START, (rawopen ? SCSI_SILENT :
        !           349:                            0) | SCSI_IGNORE_ILLEGAL_REQUEST |
        !           350:                            SCSI_IGNORE_MEDIA_CHANGE);
        !           351:
        !           352:                /* Use sd_interpret_sense() for sense errors.
        !           353:                 *
        !           354:                 * But only after spinning the disk up! Just in case a broken
        !           355:                 * device returns "Initialization command required." and causes
        !           356:                 * a loop of scsi_start() calls.
        !           357:                 */
        !           358:                sc_link->flags |= SDEV_OPEN;
        !           359:
        !           360:                /* Check that it is still responding and ok. */
        !           361:                error = scsi_test_unit_ready(sc_link,
        !           362:                    TEST_READY_RETRIES, (rawopen ? SCSI_SILENT : 0) |
        !           363:                    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE);
        !           364:
        !           365:                if (error) {
        !           366:                        if (rawopen) {
        !           367:                                error = 0;
        !           368:                                goto out;
        !           369:                        } else
        !           370:                                goto bad;
        !           371:                }
        !           372:
        !           373:                /*
        !           374:                 * Try to prevent the unloading of a removable device while
        !           375:                 * it's open. But allow the open to proceed if the device can't
        !           376:                 * be locked in.
        !           377:                 */
        !           378:                if ((sc_link->flags & SDEV_REMOVABLE) != 0)
        !           379:                        scsi_prevent(sc_link, PR_PREVENT,
        !           380:                            SCSI_IGNORE_ILLEGAL_REQUEST |
        !           381:                            SCSI_IGNORE_MEDIA_CHANGE);
        !           382:
        !           383:                /* Load the physical device parameters. */
        !           384:                sc_link->flags |= SDEV_MEDIA_LOADED;
        !           385:                if (sd_get_parms(sd, &sd->params, (rawopen ? SCSI_SILENT : 0))
        !           386:                    == SDGP_RESULT_OFFLINE) {
        !           387:                        sc_link->flags &= ~SDEV_MEDIA_LOADED;
        !           388:                        error = ENXIO;
        !           389:                        goto bad;
        !           390:                }
        !           391:                SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded\n"));
        !           392:
        !           393:                /* Load the partition info if not already loaded. */
        !           394:                sdgetdisklabel(dev, sd, sd->sc_dk.dk_label, 0);
        !           395:                SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel loaded\n"));
        !           396:        }
        !           397:
        !           398:        /* Check that the partition exists. */
        !           399:        if (part != RAW_PART &&
        !           400:            (part >= sd->sc_dk.dk_label->d_npartitions ||
        !           401:            sd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
        !           402:                error = ENXIO;
        !           403:                goto bad;
        !           404:        }
        !           405:
        !           406: out:   /* Insure only one open at a time. */
        !           407:        switch (fmt) {
        !           408:        case S_IFCHR:
        !           409:                sd->sc_dk.dk_copenmask |= (1 << part);
        !           410:                break;
        !           411:        case S_IFBLK:
        !           412:                sd->sc_dk.dk_bopenmask |= (1 << part);
        !           413:                break;
        !           414:        }
        !           415:        sd->sc_dk.dk_openmask = sd->sc_dk.dk_copenmask | sd->sc_dk.dk_bopenmask;
        !           416:        SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
        !           417:
        !           418:        /* It's OK to fall through because dk_openmask is now non-zero. */
        !           419: bad:
        !           420:        if (sd->sc_dk.dk_openmask == 0) {
        !           421:                if ((sd->sc_link->flags & SDEV_REMOVABLE) != 0)
        !           422:                        scsi_prevent(sc_link, PR_ALLOW,
        !           423:                            SCSI_IGNORE_ILLEGAL_REQUEST |
        !           424:                            SCSI_IGNORE_MEDIA_CHANGE);
        !           425:                sc_link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED);
        !           426:        }
        !           427:
        !           428:        sdunlock(sd);
        !           429:        device_unref(&sd->sc_dev);
        !           430:        return (error);
        !           431: }
        !           432:
        !           433: /*
        !           434:  * Close the device. Only called if we are the last occurrence of an open
        !           435:  * device.  Convenient now but usually a pain.
        !           436:  */
        !           437: int
        !           438: sdclose(dev_t dev, int flag, int fmt, struct proc *p)
        !           439: {
        !           440:        struct sd_softc *sd;
        !           441:        int part = DISKPART(dev);
        !           442:        int error;
        !           443:
        !           444:        sd = sdlookup(DISKUNIT(dev));
        !           445:        if (sd == NULL)
        !           446:                return ENXIO;
        !           447:
        !           448:        if ((error = sdlock(sd)) != 0) {
        !           449:                device_unref(&sd->sc_dev);
        !           450:                return (error);
        !           451:        }
        !           452:
        !           453:        switch (fmt) {
        !           454:        case S_IFCHR:
        !           455:                sd->sc_dk.dk_copenmask &= ~(1 << part);
        !           456:                break;
        !           457:        case S_IFBLK:
        !           458:                sd->sc_dk.dk_bopenmask &= ~(1 << part);
        !           459:                break;
        !           460:        }
        !           461:        sd->sc_dk.dk_openmask = sd->sc_dk.dk_copenmask | sd->sc_dk.dk_bopenmask;
        !           462:
        !           463:        if (sd->sc_dk.dk_openmask == 0) {
        !           464:                if ((sd->flags & SDF_DIRTY) != 0)
        !           465:                        sd_flush(sd, 0);
        !           466:
        !           467:                if ((sd->sc_link->flags & SDEV_REMOVABLE) != 0)
        !           468:                        scsi_prevent(sd->sc_link, PR_ALLOW,
        !           469:                            SCSI_IGNORE_ILLEGAL_REQUEST |
        !           470:                            SCSI_IGNORE_NOT_READY);
        !           471:                sd->sc_link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED);
        !           472:
        !           473:                if (sd->sc_link->flags & SDEV_EJECTING) {
        !           474:                        scsi_start(sd->sc_link, SSS_STOP|SSS_LOEJ, 0);
        !           475:                        sd->sc_link->flags &= ~SDEV_EJECTING;
        !           476:                }
        !           477:
        !           478:                timeout_del(&sd->sc_timeout);
        !           479:        }
        !           480:
        !           481:        sdunlock(sd);
        !           482:        device_unref(&sd->sc_dev);
        !           483:        return 0;
        !           484: }
        !           485:
        !           486: /*
        !           487:  * Actually translate the requested transfer into one the physical driver
        !           488:  * can understand.  The transfer is described by a buf and will include
        !           489:  * only one physical transfer.
        !           490:  */
        !           491: void
        !           492: sdstrategy(struct buf *bp)
        !           493: {
        !           494:        struct sd_softc *sd;
        !           495:        int s;
        !           496:
        !           497:        sd = sdlookup(DISKUNIT(bp->b_dev));
        !           498:        if (sd == NULL) {
        !           499:                bp->b_error = ENXIO;
        !           500:                goto bad;
        !           501:        }
        !           502:
        !           503:        SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdstrategy: %ld bytes @ blk %d\n",
        !           504:            bp->b_bcount, bp->b_blkno));
        !           505:        /*
        !           506:         * If the device has been made invalid, error out
        !           507:         */
        !           508:        if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
        !           509:                if (sd->sc_link->flags & SDEV_OPEN)
        !           510:                        bp->b_error = EIO;
        !           511:                else
        !           512:                        bp->b_error = ENODEV;
        !           513:                goto bad;
        !           514:        }
        !           515:        /*
        !           516:         * If it's a null transfer, return immediately
        !           517:         */
        !           518:        if (bp->b_bcount == 0)
        !           519:                goto done;
        !           520:
        !           521:        /*
        !           522:         * The transfer must be a whole number of sectors.
        !           523:         */
        !           524:        if ((bp->b_bcount % sd->sc_dk.dk_label->d_secsize) != 0) {
        !           525:                bp->b_error = EINVAL;
        !           526:                goto bad;
        !           527:        }
        !           528:        /*
        !           529:         * Do bounds checking, adjust transfer. if error, process.
        !           530:         * If end of partition, just return.
        !           531:         */
        !           532:        if (DISKPART(bp->b_dev) != RAW_PART &&
        !           533:            bounds_check_with_label(bp, sd->sc_dk.dk_label,
        !           534:            (sd->flags & (SDF_WLABEL|SDF_LABELLING)) != 0) <= 0)
        !           535:                goto done;
        !           536:
        !           537:        s = splbio();
        !           538:
        !           539:        /*
        !           540:         * Place it in the queue of disk activities for this disk
        !           541:         */
        !           542:        disksort(&sd->buf_queue, bp);
        !           543:
        !           544:        /*
        !           545:         * Tell the device to get going on the transfer if it's
        !           546:         * not doing anything, otherwise just wait for completion
        !           547:         */
        !           548:        sdstart(sd);
        !           549:
        !           550:        splx(s);
        !           551:
        !           552:        device_unref(&sd->sc_dev);
        !           553:        return;
        !           554:
        !           555: bad:
        !           556:        bp->b_flags |= B_ERROR;
        !           557: done:
        !           558:        /*
        !           559:         * Correctly set the buf to indicate a completed xfer
        !           560:         */
        !           561:        bp->b_resid = bp->b_bcount;
        !           562:        s = splbio();
        !           563:        biodone(bp);
        !           564:        splx(s);
        !           565:        if (sd != NULL)
        !           566:                device_unref(&sd->sc_dev);
        !           567: }
        !           568:
        !           569: /*
        !           570:  * sdstart looks to see if there is a buf waiting for the device
        !           571:  * and that the device is not already busy. If both are true,
        !           572:  * It dequeues the buf and creates a scsi command to perform the
        !           573:  * transfer in the buf. The transfer request will call scsi_done
        !           574:  * on completion, which will in turn call this routine again
        !           575:  * so that the next queued transfer is performed.
        !           576:  * The bufs are queued by the strategy routine (sdstrategy)
        !           577:  *
        !           578:  * This routine is also called after other non-queued requests
        !           579:  * have been made of the scsi driver, to ensure that the queue
        !           580:  * continues to be drained.
        !           581:  *
        !           582:  * must be called at the correct (highish) spl level
        !           583:  * sdstart() is called at splbio from sdstrategy, sdrestart and scsi_done
        !           584:  */
        !           585: void
        !           586: sdstart(void *v)
        !           587: {
        !           588:        struct sd_softc *sd = (struct sd_softc *)v;
        !           589:        struct scsi_link *sc_link = sd->sc_link;
        !           590:        struct buf *bp = 0;
        !           591:        struct buf *dp;
        !           592:        struct scsi_rw_big cmd_big;
        !           593:        struct scsi_rw_12 cmd_12;
        !           594:        struct scsi_rw_16 cmd_16;
        !           595:        struct scsi_rw cmd_small;
        !           596:        struct scsi_generic *cmdp;
        !           597:        daddr64_t blkno;
        !           598:        int nblks, cmdlen, error;
        !           599:        struct partition *p;
        !           600:
        !           601:        SC_DEBUG(sc_link, SDEV_DB2, ("sdstart\n"));
        !           602:
        !           603:        splassert(IPL_BIO);
        !           604:
        !           605:        /*
        !           606:         * Check if the device has room for another command
        !           607:         */
        !           608:        while (sc_link->openings > 0) {
        !           609:                /*
        !           610:                 * there is excess capacity, but a special waits
        !           611:                 * It'll need the adapter as soon as we clear out of the
        !           612:                 * way and let it run (user level wait).
        !           613:                 */
        !           614:                if (sc_link->flags & SDEV_WAITING) {
        !           615:                        sc_link->flags &= ~SDEV_WAITING;
        !           616:                        wakeup((caddr_t)sc_link);
        !           617:                        return;
        !           618:                }
        !           619:
        !           620:                /*
        !           621:                 * See if there is a buf with work for us to do..
        !           622:                 */
        !           623:                dp = &sd->buf_queue;
        !           624:                if ((bp = dp->b_actf) == NULL)  /* yes, an assign */
        !           625:                        return;
        !           626:                dp->b_actf = bp->b_actf;
        !           627:
        !           628:                /*
        !           629:                 * If the device has become invalid, abort all the
        !           630:                 * reads and writes until all files have been closed and
        !           631:                 * re-opened
        !           632:                 */
        !           633:                if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
        !           634:                        bp->b_error = EIO;
        !           635:                        bp->b_flags |= B_ERROR;
        !           636:                        bp->b_resid = bp->b_bcount;
        !           637:                        biodone(bp);
        !           638:                        continue;
        !           639:                }
        !           640:
        !           641:                /*
        !           642:                 * We have a buf, now we should make a command
        !           643:                 *
        !           644:                 * First, translate the block to absolute and put it in terms
        !           645:                 * of the logical blocksize of the device.
        !           646:                 */
        !           647:                blkno =
        !           648:                    bp->b_blkno / (sd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
        !           649:                p = &sd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
        !           650:                blkno += DL_GETPOFFSET(p);
        !           651:                nblks = howmany(bp->b_bcount, sd->sc_dk.dk_label->d_secsize);
        !           652:
        !           653:                /*
        !           654:                 *  Fill out the scsi command.  If the transfer will
        !           655:                 *  fit in a "small" cdb, use it.
        !           656:                 */
        !           657:                if (!(sc_link->flags & SDEV_ATAPI) &&
        !           658:                    !(sc_link->quirks & SDEV_ONLYBIG) &&
        !           659:                    ((blkno & 0x1fffff) == blkno) &&
        !           660:                    ((nblks & 0xff) == nblks)) {
        !           661:                        /*
        !           662:                         * We can fit in a 6 byte cdb.
        !           663:                         */
        !           664:                        bzero(&cmd_small, sizeof(cmd_small));
        !           665:                        cmd_small.opcode = (bp->b_flags & B_READ) ?
        !           666:                            READ_COMMAND : WRITE_COMMAND;
        !           667:                        _lto3b(blkno, cmd_small.addr);
        !           668:                        cmd_small.length = nblks;
        !           669:                        cmdlen = sizeof(cmd_small);
        !           670:                        cmdp = (struct scsi_generic *)&cmd_small;
        !           671:                } else if (((blkno & 0xffffffff) == blkno) &&
        !           672:                    ((nblks & 0xffff) == nblks)) {
        !           673:                        /*
        !           674:                         * We can fit in a 10 byte cdb.
        !           675:                         */
        !           676:                        bzero(&cmd_big, sizeof(cmd_big));
        !           677:                        cmd_big.opcode = (bp->b_flags & B_READ) ?
        !           678:                            READ_BIG : WRITE_BIG;
        !           679:                        _lto4b(blkno, cmd_big.addr);
        !           680:                        _lto2b(nblks, cmd_big.length);
        !           681:                        cmdlen = sizeof(cmd_big);
        !           682:                        cmdp = (struct scsi_generic *)&cmd_big;
        !           683:                } else if (((blkno & 0xffffffff) == blkno) &&
        !           684:                    ((nblks & 0xffffffff) == nblks)) {
        !           685:                        /*
        !           686:                         * We can fit in a 12 byte cdb.
        !           687:                         */
        !           688:                        bzero(&cmd_12, sizeof(cmd_12));
        !           689:                        cmd_12.opcode = (bp->b_flags & B_READ) ?
        !           690:                            READ_12 : WRITE_12;
        !           691:                        _lto4b(blkno, cmd_12.addr);
        !           692:                        _lto4b(nblks, cmd_12.length);
        !           693:                        cmdlen = sizeof(cmd_12);
        !           694:                        cmdp = (struct scsi_generic *)&cmd_12;
        !           695:                } else {
        !           696:                        /*
        !           697:                         * Need a 16 byte cdb. There's nothing bigger.
        !           698:                         */
        !           699:                        bzero(&cmd_16, sizeof(cmd_16));
        !           700:                        cmd_16.opcode = (bp->b_flags & B_READ) ?
        !           701:                            READ_16 : WRITE_16;
        !           702:                        _lto8b(blkno, cmd_16.addr);
        !           703:                        _lto4b(nblks, cmd_16.length);
        !           704:                        cmdlen = sizeof(cmd_16);
        !           705:                        cmdp = (struct scsi_generic *)&cmd_16;
        !           706:                }
        !           707:
        !           708:                /* Instrumentation. */
        !           709:                disk_busy(&sd->sc_dk);
        !           710:
        !           711:                /*
        !           712:                 * Call the routine that chats with the adapter.
        !           713:                 * Note: we cannot sleep as we may be an interrupt
        !           714:                 */
        !           715:                error = scsi_scsi_cmd(sc_link, cmdp, cmdlen,
        !           716:                    (u_char *)bp->b_data, bp->b_bcount,
        !           717:                    SDRETRIES, 60000, bp, SCSI_NOSLEEP |
        !           718:                    ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT));
        !           719:                switch (error) {
        !           720:                case 0:
        !           721:                        /*
        !           722:                         * Mark the disk dirty so that the cache will be
        !           723:                         * flushed on close.
        !           724:                         */
        !           725:                        if ((bp->b_flags & B_READ) == 0)
        !           726:                                sd->flags |= SDF_DIRTY;
        !           727:                        timeout_del(&sd->sc_timeout);
        !           728:                        break;
        !           729:                case EAGAIN:
        !           730:                        /*
        !           731:                         * The device can't start another i/o. Try again later.
        !           732:                         */
        !           733:                        dp->b_actf = bp;
        !           734:                        disk_unbusy(&sd->sc_dk, 0, 0);
        !           735:                        timeout_add(&sd->sc_timeout, 1);
        !           736:                        return;
        !           737:                default:
        !           738:                        disk_unbusy(&sd->sc_dk, 0, 0);
        !           739:                        printf("%s: not queued, error %d\n",
        !           740:                            sd->sc_dev.dv_xname, error);
        !           741:                        break;
        !           742:                }
        !           743:        }
        !           744: }
        !           745:
        !           746: void
        !           747: sdrestart(void *v)
        !           748: {
        !           749:        int s;
        !           750:
        !           751:        s = splbio();
        !           752:        sdstart(v);
        !           753:        splx(s);
        !           754: }
        !           755:
        !           756: void
        !           757: sddone(struct scsi_xfer *xs)
        !           758: {
        !           759:        struct sd_softc *sd = xs->sc_link->device_softc;
        !           760:
        !           761:        if (sd->flags & SDF_FLUSHING) {
        !           762:                /* Flush completed, no longer dirty. */
        !           763:                sd->flags &= ~(SDF_FLUSHING|SDF_DIRTY);
        !           764:        }
        !           765:
        !           766:        if (xs->bp != NULL)
        !           767:                disk_unbusy(&sd->sc_dk, (xs->bp->b_bcount - xs->bp->b_resid),
        !           768:                    (xs->bp->b_flags & B_READ));
        !           769: }
        !           770:
        !           771: void
        !           772: sdminphys(struct buf *bp)
        !           773: {
        !           774:        struct sd_softc *sd;
        !           775:        long max;
        !           776:
        !           777:        sd = sdlookup(DISKUNIT(bp->b_dev));
        !           778:        if (sd == NULL)
        !           779:                return;  /* XXX - right way to fail this? */
        !           780:
        !           781:        /*
        !           782:         * If the device is ancient, we want to make sure that
        !           783:         * the transfer fits into a 6-byte cdb.
        !           784:         *
        !           785:         * XXX Note that the SCSI-I spec says that 256-block transfers
        !           786:         * are allowed in a 6-byte read/write, and are specified
        !           787:         * by setting the "length" to 0.  However, we're conservative
        !           788:         * here, allowing only 255-block transfers in case an
        !           789:         * ancient device gets confused by length == 0.  A length of 0
        !           790:         * in a 10-byte read/write actually means 0 blocks.
        !           791:         */
        !           792:        if (sd->flags & SDF_ANCIENT) {
        !           793:                max = sd->sc_dk.dk_label->d_secsize * 0xff;
        !           794:
        !           795:                if (bp->b_bcount > max)
        !           796:                        bp->b_bcount = max;
        !           797:        }
        !           798:
        !           799:        (*sd->sc_link->adapter->scsi_minphys)(bp);
        !           800:
        !           801:        device_unref(&sd->sc_dev);
        !           802: }
        !           803:
        !           804: int
        !           805: sdread(dev_t dev, struct uio *uio, int ioflag)
        !           806: {
        !           807:        return (physio(sdstrategy, NULL, dev, B_READ, sdminphys, uio));
        !           808: }
        !           809:
        !           810: int
        !           811: sdwrite(dev_t dev, struct uio *uio, int ioflag)
        !           812: {
        !           813:        return (physio(sdstrategy, NULL, dev, B_WRITE, sdminphys, uio));
        !           814: }
        !           815:
        !           816: /*
        !           817:  * Perform special action on behalf of the user
        !           818:  * Knows about the internals of this device
        !           819:  */
        !           820: int
        !           821: sdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
        !           822: {
        !           823:        struct sd_softc *sd;
        !           824:        struct disklabel *lp;
        !           825:        int error = 0;
        !           826:        int part = DISKPART(dev);
        !           827:
        !           828:        sd = sdlookup(DISKUNIT(dev));
        !           829:        if (sd == NULL)
        !           830:                return ENXIO;
        !           831:
        !           832:        SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdioctl 0x%lx\n", cmd));
        !           833:
        !           834:        /*
        !           835:         * If the device is not valid.. abandon ship
        !           836:         */
        !           837:        if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
        !           838:                switch (cmd) {
        !           839:                case DIOCWLABEL:
        !           840:                case DIOCLOCK:
        !           841:                case DIOCEJECT:
        !           842:                case SCIOCIDENTIFY:
        !           843:                case SCIOCCOMMAND:
        !           844:                case SCIOCDEBUG:
        !           845:                        if (part == RAW_PART)
        !           846:                                break;
        !           847:                /* FALLTHROUGH */
        !           848:                default:
        !           849:                        if ((sd->sc_link->flags & SDEV_OPEN) == 0) {
        !           850:                                error = ENODEV;
        !           851:                                goto exit;
        !           852:                        } else {
        !           853:                                error = EIO;
        !           854:                                goto exit;
        !           855:                        }
        !           856:                }
        !           857:        }
        !           858:
        !           859:        switch (cmd) {
        !           860:        case DIOCRLDINFO:
        !           861:                lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
        !           862:                sdgetdisklabel(dev, sd, lp, 0);
        !           863:                bcopy(lp, sd->sc_dk.dk_label, sizeof(*lp));
        !           864:                free(lp, M_TEMP);
        !           865:                goto exit;
        !           866:        case DIOCGPDINFO:
        !           867:                sdgetdisklabel(dev, sd, (struct disklabel *)addr, 1);
        !           868:                goto exit;
        !           869:
        !           870:        case DIOCGDINFO:
        !           871:                *(struct disklabel *)addr = *(sd->sc_dk.dk_label);
        !           872:                goto exit;
        !           873:
        !           874:        case DIOCGPART:
        !           875:                ((struct partinfo *)addr)->disklab = sd->sc_dk.dk_label;
        !           876:                ((struct partinfo *)addr)->part =
        !           877:                    &sd->sc_dk.dk_label->d_partitions[DISKPART(dev)];
        !           878:                goto exit;
        !           879:
        !           880:        case DIOCWDINFO:
        !           881:        case DIOCSDINFO:
        !           882:                if ((flag & FWRITE) == 0) {
        !           883:                        error = EBADF;
        !           884:                        goto exit;
        !           885:                }
        !           886:
        !           887:                if ((error = sdlock(sd)) != 0)
        !           888:                        goto exit;
        !           889:                sd->flags |= SDF_LABELLING;
        !           890:
        !           891:                error = setdisklabel(sd->sc_dk.dk_label,
        !           892:                    (struct disklabel *)addr, /*sd->sc_dk.dk_openmask : */0);
        !           893:                if (error == 0) {
        !           894:                        if (cmd == DIOCWDINFO)
        !           895:                                error = writedisklabel(DISKLABELDEV(dev),
        !           896:                                    sdstrategy, sd->sc_dk.dk_label);
        !           897:                }
        !           898:
        !           899:                sd->flags &= ~SDF_LABELLING;
        !           900:                sdunlock(sd);
        !           901:                goto exit;
        !           902:
        !           903:        case DIOCWLABEL:
        !           904:                if ((flag & FWRITE) == 0) {
        !           905:                        error = EBADF;
        !           906:                        goto exit;
        !           907:                }
        !           908:                if (*(int *)addr)
        !           909:                        sd->flags |= SDF_WLABEL;
        !           910:                else
        !           911:                        sd->flags &= ~SDF_WLABEL;
        !           912:                goto exit;
        !           913:
        !           914:        case DIOCLOCK:
        !           915:                error = scsi_prevent(sd->sc_link,
        !           916:                    (*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0);
        !           917:                goto exit;
        !           918:
        !           919:        case MTIOCTOP:
        !           920:                if (((struct mtop *)addr)->mt_op != MTOFFL) {
        !           921:                        error = EIO;
        !           922:                        goto exit;
        !           923:                }
        !           924:                /* FALLTHROUGH */
        !           925:        case DIOCEJECT:
        !           926:                if ((sd->sc_link->flags & SDEV_REMOVABLE) == 0) {
        !           927:                        error = ENOTTY;
        !           928:                        goto exit;
        !           929:                }
        !           930:                sd->sc_link->flags |= SDEV_EJECTING;
        !           931:                goto exit;
        !           932:
        !           933:        case DIOCINQ:
        !           934:                error = scsi_do_ioctl(sd->sc_link, dev, cmd, addr, flag, p);
        !           935:                if (error == ENOTTY)
        !           936:                        error = sd_ioctl_inquiry(sd,
        !           937:                            (struct dk_inquiry *)addr);
        !           938:                goto exit;
        !           939:
        !           940:        default:
        !           941:                if (part != RAW_PART) {
        !           942:                        error = ENOTTY;
        !           943:                        goto exit;
        !           944:                }
        !           945:                error = scsi_do_ioctl(sd->sc_link, dev, cmd, addr, flag, p);
        !           946:        }
        !           947:
        !           948:  exit:
        !           949:        device_unref(&sd->sc_dev);
        !           950:        return (error);
        !           951: }
        !           952:
        !           953: int
        !           954: sd_ioctl_inquiry(struct sd_softc *sd, struct dk_inquiry *di)
        !           955: {
        !           956:        struct scsi_inquiry_vpd vpd;
        !           957:
        !           958:        bzero(di, sizeof(struct dk_inquiry));
        !           959:        scsi_strvis(di->vendor, sd->sc_link->inqdata.vendor,
        !           960:            sizeof(sd->sc_link->inqdata.vendor));
        !           961:        scsi_strvis(di->product, sd->sc_link->inqdata.product,
        !           962:            sizeof(sd->sc_link->inqdata.product));
        !           963:        scsi_strvis(di->revision, sd->sc_link->inqdata.revision,
        !           964:            sizeof(sd->sc_link->inqdata.revision));
        !           965:
        !           966:        /* the serial vpd page is optional */
        !           967:        if (scsi_inquire_vpd(sd->sc_link, &vpd, sizeof(vpd),
        !           968:            SI_PG_SERIAL, 0) == 0)
        !           969:                scsi_strvis(di->serial, vpd.serial, sizeof(vpd.serial));
        !           970:
        !           971:        return (0);
        !           972: }
        !           973:
        !           974: /*
        !           975:  * Load the label information on the named device
        !           976:  */
        !           977: void
        !           978: sdgetdisklabel(dev_t dev, struct sd_softc *sd, struct disklabel *lp,
        !           979:     int spoofonly)
        !           980: {
        !           981:        size_t len;
        !           982:        char *errstring, packname[sizeof(lp->d_packname) + 1];
        !           983:        char product[17], vendor[9];
        !           984:
        !           985:        bzero(lp, sizeof(struct disklabel));
        !           986:
        !           987:        lp->d_secsize = sd->params.blksize;
        !           988:        lp->d_ntracks = sd->params.heads;
        !           989:        lp->d_nsectors = sd->params.sectors;
        !           990:        lp->d_ncylinders = sd->params.cyls;
        !           991:        lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
        !           992:        if (lp->d_secpercyl == 0) {
        !           993:                lp->d_secpercyl = 100;
        !           994:                /* as long as it's not 0 - readdisklabel divides by it */
        !           995:        }
        !           996:
        !           997:        lp->d_type = DTYPE_SCSI;
        !           998:        if ((sd->sc_link->inqdata.device & SID_TYPE) == T_OPTICAL)
        !           999:                strncpy(lp->d_typename, "SCSI optical",
        !          1000:                    sizeof(lp->d_typename));
        !          1001:        else
        !          1002:                strncpy(lp->d_typename, "SCSI disk",
        !          1003:                    sizeof(lp->d_typename));
        !          1004:
        !          1005:        /*
        !          1006:         * Try to fit '<vendor> <product>' into d_packname. If that doesn't fit
        !          1007:         * then leave out '<vendor> ' and use only as much of '<product>' as
        !          1008:         * does fit.
        !          1009:         */
        !          1010:        viscpy(vendor, sd->sc_link->inqdata.vendor, 8);
        !          1011:        viscpy(product, sd->sc_link->inqdata.product, 16);
        !          1012:        len = snprintf(packname, sizeof(packname), "%s %s", vendor, product);
        !          1013:        if (len > sizeof(lp->d_packname)) {
        !          1014:                strlcpy(packname, product, sizeof(packname));
        !          1015:                len = strlen(packname);
        !          1016:        }
        !          1017:        /*
        !          1018:         * It is safe to use len as the count of characters to copy because
        !          1019:         * packname is sizeof(lp->d_packname)+1, the string in packname is
        !          1020:         * always null terminated and len does not count the terminating null.
        !          1021:         * d_packname is not a null terminated string.
        !          1022:         */
        !          1023:        bcopy(packname, lp->d_packname, len);
        !          1024:
        !          1025:        DL_SETDSIZE(lp, sd->params.disksize);
        !          1026:        lp->d_rpm = sd->params.rot_rate;
        !          1027:        lp->d_interleave = 1;
        !          1028:        lp->d_version = 1;
        !          1029:        lp->d_flags = 0;
        !          1030:
        !          1031:        /* XXX - these values for BBSIZE and SBSIZE assume ffs */
        !          1032:        lp->d_bbsize = BBSIZE;
        !          1033:        lp->d_sbsize = SBSIZE;
        !          1034:
        !          1035:        lp->d_magic = DISKMAGIC;
        !          1036:        lp->d_magic2 = DISKMAGIC;
        !          1037:        lp->d_checksum = dkcksum(lp);
        !          1038:
        !          1039:        /*
        !          1040:         * Call the generic disklabel extraction routine
        !          1041:         */
        !          1042:        errstring = readdisklabel(DISKLABELDEV(dev), sdstrategy, lp, spoofonly);
        !          1043:        if (errstring) {
        !          1044:                /*printf("%s: %s\n", sd->sc_dev.dv_xname, errstring);*/
        !          1045:        }
        !          1046: }
        !          1047:
        !          1048:
        !          1049: void
        !          1050: sd_shutdown(void *arg)
        !          1051: {
        !          1052:        struct sd_softc *sd = (struct sd_softc *)arg;
        !          1053:
        !          1054:        /*
        !          1055:         * If the disk cache needs to be flushed, and the disk supports
        !          1056:         * it, flush it.  We're cold at this point, so we poll for
        !          1057:         * completion.
        !          1058:         */
        !          1059:        if ((sd->flags & SDF_DIRTY) != 0)
        !          1060:                sd_flush(sd, SCSI_AUTOCONF);
        !          1061:
        !          1062:        timeout_del(&sd->sc_timeout);
        !          1063: }
        !          1064:
        !          1065: /*
        !          1066:  * Tell the device to map out a defective block
        !          1067:  */
        !          1068: int
        !          1069: sd_reassign_blocks(struct sd_softc *sd, u_long blkno)
        !          1070: {
        !          1071:        struct scsi_reassign_blocks scsi_cmd;
        !          1072:        struct scsi_reassign_blocks_data rbdata;
        !          1073:
        !          1074:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1075:        bzero(&rbdata, sizeof(rbdata));
        !          1076:        scsi_cmd.opcode = REASSIGN_BLOCKS;
        !          1077:
        !          1078:        _lto2b(sizeof(rbdata.defect_descriptor[0]), rbdata.length);
        !          1079:        _lto4b(blkno, rbdata.defect_descriptor[0].dlbaddr);
        !          1080:
        !          1081:        return scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd,
        !          1082:            sizeof(scsi_cmd), (u_char *)&rbdata, sizeof(rbdata), SDRETRIES,
        !          1083:            5000, NULL, SCSI_DATA_OUT);
        !          1084: }
        !          1085:
        !          1086: /*
        !          1087:  * Check Errors
        !          1088:  */
        !          1089: int
        !          1090: sd_interpret_sense(struct scsi_xfer *xs)
        !          1091: {
        !          1092:        struct scsi_sense_data *sense = &xs->sense;
        !          1093:        struct scsi_link *sc_link = xs->sc_link;
        !          1094:        struct sd_softc *sd = sc_link->device_softc;
        !          1095:        u_int8_t serr = sense->error_code & SSD_ERRCODE;
        !          1096:        int retval;
        !          1097:
        !          1098:        /*
        !          1099:         * Let the generic code handle everything except a few categories of
        !          1100:         * LUN not ready errors on open devices.
        !          1101:         */
        !          1102:        if (((sc_link->flags & SDEV_OPEN) == 0) ||
        !          1103:            (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED) ||
        !          1104:            ((sense->flags & SSD_KEY) != SKEY_NOT_READY) ||
        !          1105:            (sense->extra_len < 6))
        !          1106:                return (EJUSTRETURN);
        !          1107:
        !          1108:        switch (ASC_ASCQ(sense)) {
        !          1109:        case SENSE_NOT_READY_BECOMING_READY:
        !          1110:                SC_DEBUG(sc_link, SDEV_DB1, ("becoming ready.\n"));
        !          1111:                retval = scsi_delay(xs, 5);
        !          1112:                break;
        !          1113:
        !          1114:        case SENSE_NOT_READY_INIT_REQUIRED:
        !          1115:                SC_DEBUG(sc_link, SDEV_DB1, ("spinning up\n"));
        !          1116:                retval = scsi_start(sd->sc_link, SSS_START,
        !          1117:                    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_URGENT | SCSI_NOSLEEP);
        !          1118:                if (retval == 0)
        !          1119:                        retval = ERESTART;
        !          1120:                else
        !          1121:                        SC_DEBUG(sc_link, SDEV_DB1, ("spin up failed (%#x)\n",
        !          1122:                            retval));
        !          1123:                break;
        !          1124:
        !          1125:        default:
        !          1126:                retval = EJUSTRETURN;
        !          1127:                break;
        !          1128:        }
        !          1129:
        !          1130:        return (retval);
        !          1131: }
        !          1132:
        !          1133: daddr64_t
        !          1134: sdsize(dev_t dev)
        !          1135: {
        !          1136:        struct sd_softc *sd;
        !          1137:        int part, omask;
        !          1138:        int64_t size;
        !          1139:
        !          1140:        sd = sdlookup(DISKUNIT(dev));
        !          1141:        if (sd == NULL)
        !          1142:                return -1;
        !          1143:
        !          1144:        part = DISKPART(dev);
        !          1145:        omask = sd->sc_dk.dk_openmask & (1 << part);
        !          1146:
        !          1147:        if (omask == 0 && sdopen(dev, 0, S_IFBLK, NULL) != 0) {
        !          1148:                size = -1;
        !          1149:                goto exit;
        !          1150:        }
        !          1151:        if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) == 0)
        !          1152:                size = -1;
        !          1153:        else if (sd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
        !          1154:                size = -1;
        !          1155:        else
        !          1156:                size = DL_GETPSIZE(&sd->sc_dk.dk_label->d_partitions[part]) *
        !          1157:                        (sd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
        !          1158:        if (omask == 0 && sdclose(dev, 0, S_IFBLK, NULL) != 0)
        !          1159:                size = -1;
        !          1160:
        !          1161:  exit:
        !          1162:        device_unref(&sd->sc_dev);
        !          1163:        return size;
        !          1164: }
        !          1165:
        !          1166: /* #define SD_DUMP_NOT_TRUSTED if you just want to watch */
        !          1167: static struct scsi_xfer sx;
        !          1168: static int sddoingadump;
        !          1169:
        !          1170: /*
        !          1171:  * dump all of physical memory into the partition specified, starting
        !          1172:  * at offset 'dumplo' into the partition.
        !          1173:  */
        !          1174: int
        !          1175: sddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size)
        !          1176: {
        !          1177:        struct sd_softc *sd;    /* disk unit to do the I/O */
        !          1178:        struct disklabel *lp;   /* disk's disklabel */
        !          1179:        int     unit, part;
        !          1180:        int     sectorsize;     /* size of a disk sector */
        !          1181:        daddr64_t       nsects;         /* number of sectors in partition */
        !          1182:        daddr64_t       sectoff;        /* sector offset of partition */
        !          1183:        int     totwrt;         /* total number of sectors left to write */
        !          1184:        int     nwrt;           /* current number of sectors to write */
        !          1185:        struct scsi_rw_big cmd; /* write command */
        !          1186:        struct scsi_xfer *xs;   /* ... convenience */
        !          1187:        int     retval;
        !          1188:
        !          1189:        /* Check if recursive dump; if so, punt. */
        !          1190:        if (sddoingadump)
        !          1191:                return EFAULT;
        !          1192:
        !          1193:        /* Mark as active early. */
        !          1194:        sddoingadump = 1;
        !          1195:
        !          1196:        unit = DISKUNIT(dev);   /* Decompose unit & partition. */
        !          1197:        part = DISKPART(dev);
        !          1198:
        !          1199:        /* Check for acceptable drive number. */
        !          1200:        if (unit >= sd_cd.cd_ndevs || (sd = sd_cd.cd_devs[unit]) == NULL)
        !          1201:                return ENXIO;
        !          1202:
        !          1203:        /*
        !          1204:         * XXX Can't do this check, since the media might have been
        !          1205:         * XXX marked `invalid' by successful unmounting of all
        !          1206:         * XXX filesystems.
        !          1207:         */
        !          1208: #if 0
        !          1209:        /* Make sure it was initialized. */
        !          1210:        if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) != SDEV_MEDIA_LOADED)
        !          1211:                return ENXIO;
        !          1212: #endif
        !          1213:
        !          1214:        /* Convert to disk sectors.  Request must be a multiple of size. */
        !          1215:        lp = sd->sc_dk.dk_label;
        !          1216:        sectorsize = lp->d_secsize;
        !          1217:        if ((size % sectorsize) != 0)
        !          1218:                return EFAULT;
        !          1219:        totwrt = size / sectorsize;
        !          1220:        blkno = dbtob(blkno) / sectorsize;      /* blkno in DEV_BSIZE units */
        !          1221:
        !          1222:        nsects = DL_GETPSIZE(&lp->d_partitions[part]);
        !          1223:        sectoff = DL_GETPOFFSET(&lp->d_partitions[part]);
        !          1224:
        !          1225:        /* Check transfer bounds against partition size. */
        !          1226:        if ((blkno < 0) || ((blkno + totwrt) > nsects))
        !          1227:                return EINVAL;
        !          1228:
        !          1229:        /* Offset block number to start of partition. */
        !          1230:        blkno += sectoff;
        !          1231:
        !          1232:        xs = &sx;
        !          1233:
        !          1234:        while (totwrt > 0) {
        !          1235:                nwrt = totwrt;          /* XXX */
        !          1236: #ifndef        SD_DUMP_NOT_TRUSTED
        !          1237:                /*
        !          1238:                 *  Fill out the scsi command
        !          1239:                 */
        !          1240:                bzero(&cmd, sizeof(cmd));
        !          1241:                cmd.opcode = WRITE_BIG;
        !          1242:                _lto4b(blkno, cmd.addr);
        !          1243:                _lto2b(nwrt, cmd.length);
        !          1244:                /*
        !          1245:                 * Fill out the scsi_xfer structure
        !          1246:                 *    Note: we cannot sleep as we may be an interrupt
        !          1247:                 * don't use scsi_scsi_cmd() as it may want
        !          1248:                 * to wait for an xs.
        !          1249:                 */
        !          1250:                bzero(xs, sizeof(sx));
        !          1251:                xs->flags |= SCSI_AUTOCONF | SCSI_DATA_OUT;
        !          1252:                xs->sc_link = sd->sc_link;
        !          1253:                xs->retries = SDRETRIES;
        !          1254:                xs->timeout = 10000;    /* 10000 millisecs for a disk ! */
        !          1255:                xs->cmd = (struct scsi_generic *)&cmd;
        !          1256:                xs->cmdlen = sizeof(cmd);
        !          1257:                xs->resid = nwrt * sectorsize;
        !          1258:                xs->error = XS_NOERROR;
        !          1259:                xs->bp = NULL;
        !          1260:                xs->data = va;
        !          1261:                xs->datalen = nwrt * sectorsize;
        !          1262:
        !          1263:                /*
        !          1264:                 * Pass all this info to the scsi driver.
        !          1265:                 */
        !          1266:                retval = (*(sd->sc_link->adapter->scsi_cmd)) (xs);
        !          1267:                if (retval != COMPLETE)
        !          1268:                        return ENXIO;
        !          1269: #else  /* SD_DUMP_NOT_TRUSTED */
        !          1270:                /* Let's just talk about this first... */
        !          1271:                printf("sd%d: dump addr 0x%x, blk %d\n", unit, va, blkno);
        !          1272:                delay(500 * 1000);      /* half a second */
        !          1273: #endif /* SD_DUMP_NOT_TRUSTED */
        !          1274:
        !          1275:                /* update block count */
        !          1276:                totwrt -= nwrt;
        !          1277:                blkno += nwrt;
        !          1278:                va += sectorsize * nwrt;
        !          1279:        }
        !          1280:        sddoingadump = 0;
        !          1281:        return 0;
        !          1282: }
        !          1283:
        !          1284: /*
        !          1285:  * Copy up to len chars from src to dst, ignoring non-printables.
        !          1286:  * Must be room for len+1 chars in dst so we can write the NUL.
        !          1287:  * Does not assume src is NUL-terminated.
        !          1288:  */
        !          1289: void
        !          1290: viscpy(u_char *dst, u_char *src, int len)
        !          1291: {
        !          1292:        while (len > 0 && *src != '\0') {
        !          1293:                if (*src < 0x20 || *src >= 0x80) {
        !          1294:                        src++;
        !          1295:                        continue;
        !          1296:                }
        !          1297:                *dst++ = *src++;
        !          1298:                len--;
        !          1299:        }
        !          1300:        *dst = '\0';
        !          1301: }
        !          1302:
        !          1303: /*
        !          1304:  * Fill out the disk parameter structure. Return SDGP_RESULT_OK if the
        !          1305:  * structure is correctly filled in, SDGP_RESULT_OFFLINE otherwise. The caller
        !          1306:  * is responsible for clearing the SDEV_MEDIA_LOADED flag if the structure
        !          1307:  * cannot be completed.
        !          1308:  */
        !          1309: int
        !          1310: sd_get_parms(struct sd_softc *sd, struct disk_parms *dp, int flags)
        !          1311: {
        !          1312:        union scsi_mode_sense_buf *buf = NULL;
        !          1313:        struct page_rigid_geometry *rigid;
        !          1314:        struct page_flex_geometry *flex;
        !          1315:        struct page_reduced_geometry *reduced;
        !          1316:        u_int32_t heads = 0, sectors = 0, cyls = 0, blksize, ssblksize;
        !          1317:        u_int16_t rpm = 0;
        !          1318:
        !          1319:        dp->disksize = scsi_size(sd->sc_link, flags, &ssblksize);
        !          1320:
        !          1321:        /*
        !          1322:         * Many UMASS devices choke when asked about their geometry. Most
        !          1323:         * don't have a meaningful geometry anyway, so just fake it if
        !          1324:         * scsi_size() worked.
        !          1325:         */
        !          1326:        if ((sd->sc_link->flags & SDEV_UMASS) && (dp->disksize > 0))
        !          1327:                goto validate;   /* N.B. buf will be NULL at validate. */
        !          1328:
        !          1329:        buf = malloc(sizeof(*buf), M_TEMP, M_NOWAIT);
        !          1330:        if (buf == NULL)
        !          1331:                goto validate;
        !          1332:
        !          1333:        switch (sd->sc_link->inqdata.device & SID_TYPE) {
        !          1334:        case T_OPTICAL:
        !          1335:                /* No more information needed or available. */
        !          1336:                break;
        !          1337:
        !          1338:        case T_RDIRECT:
        !          1339:                /* T_RDIRECT supports only PAGE_REDUCED_GEOMETRY (6). */
        !          1340:                scsi_do_mode_sense(sd->sc_link, PAGE_REDUCED_GEOMETRY, buf,
        !          1341:                    (void **)&reduced, NULL, NULL, &blksize, sizeof(*reduced),
        !          1342:                    flags | SCSI_SILENT, NULL);
        !          1343:                if (DISK_PGCODE(reduced, PAGE_REDUCED_GEOMETRY)) {
        !          1344:                        if (dp->disksize == 0)
        !          1345:                                dp->disksize = _5btol(reduced->sectors);
        !          1346:                        if (blksize == 0)
        !          1347:                                blksize = _2btol(reduced->bytes_s);
        !          1348:                }
        !          1349:                break;
        !          1350:
        !          1351:        default:
        !          1352:                /*
        !          1353:                 * NOTE: Some devices leave off the last four bytes of
        !          1354:                 * PAGE_RIGID_GEOMETRY and PAGE_FLEX_GEOMETRY mode sense pages.
        !          1355:                 * The only information in those four bytes is RPM information
        !          1356:                 * so accept the page. The extra bytes will be zero and RPM will
        !          1357:                 * end up with the default value of 3600.
        !          1358:                 */
        !          1359:                rigid = NULL;
        !          1360:                if (((sd->sc_link->flags & SDEV_ATAPI) == 0) ||
        !          1361:                    ((sd->sc_link->flags & SDEV_REMOVABLE) == 0))
        !          1362:                        scsi_do_mode_sense(sd->sc_link, PAGE_RIGID_GEOMETRY,
        !          1363:                            buf, (void **)&rigid, NULL, NULL, &blksize,
        !          1364:                            sizeof(*rigid) - 4, flags | SCSI_SILENT, NULL);
        !          1365:                if (DISK_PGCODE(rigid, PAGE_RIGID_GEOMETRY)) {
        !          1366:                        heads = rigid->nheads;
        !          1367:                        cyls = _3btol(rigid->ncyl);
        !          1368:                        rpm = _2btol(rigid->rpm);
        !          1369:                        if (heads * cyls > 0)
        !          1370:                                sectors = dp->disksize / (heads * cyls);
        !          1371:                } else {
        !          1372:                        scsi_do_mode_sense(sd->sc_link, PAGE_FLEX_GEOMETRY,
        !          1373:                            buf, (void **)&flex, NULL, NULL, &blksize,
        !          1374:                            sizeof(*flex) - 4, flags | SCSI_SILENT, NULL);
        !          1375:                        if (DISK_PGCODE(flex, PAGE_FLEX_GEOMETRY)) {
        !          1376:                                sectors = flex->ph_sec_tr;
        !          1377:                                heads = flex->nheads;
        !          1378:                                cyls = _2btol(flex->ncyl);
        !          1379:                                rpm = _2btol(flex->rpm);
        !          1380:                                if (blksize == 0)
        !          1381:                                        blksize = _2btol(flex->bytes_s);
        !          1382:                                if (dp->disksize == 0)
        !          1383:                                        dp->disksize = heads * cyls * sectors;
        !          1384:                        }
        !          1385:                }
        !          1386:                break;
        !          1387:        }
        !          1388:
        !          1389: validate:
        !          1390:        if (buf)
        !          1391:                free(buf, M_TEMP);
        !          1392:
        !          1393:        if (dp->disksize == 0)
        !          1394:                return (SDGP_RESULT_OFFLINE);
        !          1395:
        !          1396:        if (ssblksize > 0)
        !          1397:                dp->blksize = ssblksize;
        !          1398:        else
        !          1399:                dp->blksize = (blksize == 0) ? 512 : blksize;
        !          1400:
        !          1401:        /*
        !          1402:         * Restrict blksize values to powers of two between 512 and 64k.
        !          1403:         */
        !          1404:        switch (dp->blksize) {
        !          1405:        case 0x200:     /* == 512, == DEV_BSIZE on all architectures. */
        !          1406:        case 0x400:
        !          1407:        case 0x800:
        !          1408:        case 0x1000:
        !          1409:        case 0x2000:
        !          1410:        case 0x4000:
        !          1411:        case 0x8000:
        !          1412:        case 0x10000:
        !          1413:                break;
        !          1414:        default:
        !          1415:                SC_DEBUG(sd->sc_link, SDEV_DB1,
        !          1416:                    ("sd_get_parms: bad blksize: %#x\n", dp->blksize));
        !          1417:                return (SDGP_RESULT_OFFLINE);
        !          1418:        }
        !          1419:
        !          1420:        /*
        !          1421:         * XXX THINK ABOUT THIS!!  Using values such that sectors * heads *
        !          1422:         * cyls is <= disk_size can lead to wasted space. We need a more
        !          1423:         * careful calculation/validation to make everything work out
        !          1424:         * optimally.
        !          1425:         */
        !          1426:        if (dp->disksize > 0xffffffff && (dp->heads * dp->sectors) < 0xffff) {
        !          1427:                dp->heads = 511;
        !          1428:                dp->sectors = 255;
        !          1429:                cyls = 0;
        !          1430:        } else {
        !          1431:                /*
        !          1432:                 * Use standard geometry values for anything we still don't
        !          1433:                 * know.
        !          1434:                 */
        !          1435:                dp->heads = (heads == 0) ? 255 : heads;
        !          1436:                dp->sectors = (sectors == 0) ? 63 : sectors;
        !          1437:                dp->rot_rate = (rpm == 0) ? 3600 : rpm;
        !          1438:        }
        !          1439:
        !          1440:        dp->cyls = (cyls == 0) ? dp->disksize / (dp->heads * dp->sectors) :
        !          1441:            cyls;
        !          1442:
        !          1443:        return (SDGP_RESULT_OK);
        !          1444: }
        !          1445:
        !          1446: void
        !          1447: sd_flush(struct sd_softc *sd, int flags)
        !          1448: {
        !          1449:        struct scsi_link *sc_link = sd->sc_link;
        !          1450:        struct scsi_synchronize_cache sync_cmd;
        !          1451:
        !          1452:        /*
        !          1453:         * If the device is SCSI-2, issue a SYNCHRONIZE CACHE.
        !          1454:         * We issue with address 0 length 0, which should be
        !          1455:         * interpreted by the device as "all remaining blocks
        !          1456:         * starting at address 0".  We ignore ILLEGAL REQUEST
        !          1457:         * in the event that the command is not supported by
        !          1458:         * the device, and poll for completion so that we know
        !          1459:         * that the cache has actually been flushed.
        !          1460:         *
        !          1461:         * Unless, that is, the device can't handle the SYNCHRONIZE CACHE
        !          1462:         * command, as indicated by our quirks flags.
        !          1463:         *
        !          1464:         * XXX What about older devices?
        !          1465:         */
        !          1466:        if (SCSISPC(sc_link->inqdata.version) >= 2 &&
        !          1467:            (sc_link->quirks & SDEV_NOSYNCCACHE) == 0) {
        !          1468:                bzero(&sync_cmd, sizeof(sync_cmd));
        !          1469:                sync_cmd.opcode = SYNCHRONIZE_CACHE;
        !          1470:
        !          1471:                if (scsi_scsi_cmd(sc_link,
        !          1472:                    (struct scsi_generic *)&sync_cmd, sizeof(sync_cmd),
        !          1473:                    NULL, 0, SDRETRIES, 100000, NULL,
        !          1474:                    flags|SCSI_IGNORE_ILLEGAL_REQUEST))
        !          1475:                        printf("%s: WARNING: cache synchronization failed\n",
        !          1476:                            sd->sc_dev.dv_xname);
        !          1477:                else
        !          1478:                        sd->flags |= SDF_FLUSHING;
        !          1479:        }
        !          1480: }
        !          1481:
        !          1482: /*
        !          1483:  * Remove unprocessed buffers from queue.
        !          1484:  */
        !          1485: void
        !          1486: sd_kill_buffers(struct sd_softc *sd)
        !          1487: {
        !          1488:        struct buf *dp, *bp;
        !          1489:        int s;
        !          1490:
        !          1491:        s = splbio();
        !          1492:        for (dp = &sd->buf_queue; (bp = dp->b_actf) != NULL; ) {
        !          1493:                dp->b_actf = bp->b_actf;
        !          1494:
        !          1495:                bp->b_error = ENXIO;
        !          1496:                bp->b_flags |= B_ERROR;
        !          1497:                biodone(bp);
        !          1498:        }
        !          1499:        splx(s);
        !          1500: }

CVSweb