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

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

1.1     ! nbrk        1: /*     $OpenBSD: cd.c,v 1.132 2007/06/20 18:15:47 deraadt Exp $        */
        !             2: /*     $NetBSD: cd.c,v 1.100 1997/04/02 02:29:30 mycroft Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1994, 1995, 1997 Charles M. 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 M. 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 <sys/types.h>
        !            51: #include <sys/param.h>
        !            52: #include <sys/systm.h>
        !            53: #include <sys/timeout.h>
        !            54: #include <sys/file.h>
        !            55: #include <sys/stat.h>
        !            56: #include <sys/ioctl.h>
        !            57: #include <sys/mtio.h>
        !            58: #include <sys/buf.h>
        !            59: #include <sys/uio.h>
        !            60: #include <sys/malloc.h>
        !            61: #include <sys/errno.h>
        !            62: #include <sys/device.h>
        !            63: #include <sys/disklabel.h>
        !            64: #include <sys/disk.h>
        !            65: #include <sys/cdio.h>
        !            66: #include <sys/proc.h>
        !            67: #include <sys/conf.h>
        !            68: #include <sys/scsiio.h>
        !            69: #include <sys/vnode.h>
        !            70:
        !            71: #include <scsi/scsi_all.h>
        !            72: #include <scsi/cd.h>
        !            73: #include <scsi/scsi_disk.h>    /* rw_big and start_stop come from there */
        !            74: #include <scsi/scsiconf.h>
        !            75:
        !            76:
        !            77: #include <ufs/ffs/fs.h>                        /* for BBSIZE and SBSIZE */
        !            78:
        !            79: #define        CDOUTSTANDING   4
        !            80:
        !            81: #define MAXTRACK       99
        !            82: #define CD_BLOCK_OFFSET        150
        !            83: #define CD_FRAMES      75
        !            84: #define CD_SECS                60
        !            85:
        !            86: struct cd_toc {
        !            87:        struct ioc_toc_header header;
        !            88:        struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */
        !            89:                                                 /* leadout */
        !            90: };
        !            91:
        !            92: int    cdmatch(struct device *, void *, void *);
        !            93: void   cdattach(struct device *, struct device *, void *);
        !            94: int    cdactivate(struct device *, enum devact);
        !            95: int    cddetach(struct device *, int);
        !            96:
        !            97: void   cdstart(void *);
        !            98: void   cdrestart(void *);
        !            99: void   cdminphys(struct buf *);
        !           100: void   cdgetdisklabel(dev_t, struct cd_softc *, struct disklabel *, int);
        !           101: void   cddone(struct scsi_xfer *);
        !           102: u_long cd_size(struct cd_softc *, int);
        !           103: void   cd_kill_buffers(struct cd_softc *);
        !           104: void   lba2msf(u_long, u_char *, u_char *, u_char *);
        !           105: u_long msf2lba(u_char, u_char, u_char);
        !           106: int    cd_setchan(struct cd_softc *, int, int, int, int, int);
        !           107: int    cd_getvol(struct cd_softc *cd, struct ioc_vol *, int);
        !           108: int    cd_setvol(struct cd_softc *, const struct ioc_vol *, int);
        !           109: int    cd_load_unload(struct cd_softc *, int, int);
        !           110: int    cd_set_pa_immed(struct cd_softc *, int);
        !           111: int    cd_play(struct cd_softc *, int, int);
        !           112: int    cd_play_tracks(struct cd_softc *, int, int, int, int);
        !           113: int    cd_play_msf(struct cd_softc *, int, int, int, int, int, int);
        !           114: int    cd_pause(struct cd_softc *, int);
        !           115: int    cd_reset(struct cd_softc *);
        !           116: int    cd_read_subchannel(struct cd_softc *, int, int, int,
        !           117:            struct cd_sub_channel_info *, int );
        !           118: int    cd_read_toc(struct cd_softc *, int, int, void *, int, int);
        !           119: int    cd_get_parms(struct cd_softc *, int);
        !           120: int    cd_load_toc(struct cd_softc *, struct cd_toc *, int);
        !           121: int    cd_interpret_sense(struct scsi_xfer *);
        !           122:
        !           123: int    dvd_auth(struct cd_softc *, union dvd_authinfo *);
        !           124: int    dvd_read_physical(struct cd_softc *, union dvd_struct *);
        !           125: int    dvd_read_copyright(struct cd_softc *, union dvd_struct *);
        !           126: int    dvd_read_disckey(struct cd_softc *, union dvd_struct *);
        !           127: int    dvd_read_bca(struct cd_softc *, union dvd_struct *);
        !           128: int    dvd_read_manufact(struct cd_softc *, union dvd_struct *);
        !           129: int    dvd_read_struct(struct cd_softc *, union dvd_struct *);
        !           130:
        !           131: void   cd_powerhook(int why, void *arg);
        !           132:
        !           133: struct cfattach cd_ca = {
        !           134:        sizeof(struct cd_softc), cdmatch, cdattach,
        !           135:        cddetach, cdactivate
        !           136: };
        !           137:
        !           138: struct cfdriver cd_cd = {
        !           139:        NULL, "cd", DV_DISK
        !           140: };
        !           141:
        !           142: struct dkdriver cddkdriver = { cdstrategy };
        !           143:
        !           144: struct scsi_device cd_switch = {
        !           145:        cd_interpret_sense,
        !           146:        cdstart,                /* we have a queue, which is started by this */
        !           147:        NULL,                   /* we do not have an async handler */
        !           148:        cddone,                 /* deal with stats at interrupt time */
        !           149: };
        !           150:
        !           151: const struct scsi_inquiry_pattern cd_patterns[] = {
        !           152:        {T_CDROM, T_REMOV,
        !           153:         "",         "",                 ""},
        !           154:        {T_WORM, T_REMOV,
        !           155:         "",         "",                 ""},
        !           156:        {T_DIRECT, T_REMOV,
        !           157:         "NEC                 CD-ROM DRIVE:260", "", ""},
        !           158: #if 0
        !           159:        {T_CDROM, T_REMOV, /* more luns */
        !           160:         "PIONEER ", "CD-ROM DRM-600  ", ""},
        !           161: #endif
        !           162: };
        !           163:
        !           164: #define cdlock(softc)   disk_lock(&(softc)->sc_dk)
        !           165: #define cdunlock(softc) disk_unlock(&(softc)->sc_dk)
        !           166: #define cdlookup(unit) (struct cd_softc *)device_lookup(&cd_cd, (unit))
        !           167:
        !           168: int
        !           169: cdmatch(struct device *parent, void *match, void *aux)
        !           170: {
        !           171:        struct scsi_attach_args *sa = aux;
        !           172:        int priority;
        !           173:
        !           174:        scsi_inqmatch(sa->sa_inqbuf, cd_patterns,
        !           175:            sizeof(cd_patterns)/sizeof(cd_patterns[0]), sizeof(cd_patterns[0]),
        !           176:            &priority);
        !           177:        return (priority);
        !           178: }
        !           179:
        !           180: /*
        !           181:  * The routine called by the low level scsi routine when it discovers
        !           182:  * A device suitable for this driver
        !           183:  */
        !           184: void
        !           185: cdattach(struct device *parent, struct device *self, void *aux)
        !           186: {
        !           187:        struct scsi_attach_args *sa = aux;
        !           188:        struct scsi_link *sc_link = sa->sa_sc_link;
        !           189:        struct cd_softc *cd = (struct cd_softc *)self;
        !           190:
        !           191:        SC_DEBUG(sc_link, SDEV_DB2, ("cdattach:\n"));
        !           192:
        !           193:        /*
        !           194:         * Store information needed to contact our base driver
        !           195:         */
        !           196:        cd->sc_link = sc_link;
        !           197:        sc_link->device = &cd_switch;
        !           198:        sc_link->device_softc = cd;
        !           199:        if (sc_link->openings > CDOUTSTANDING)
        !           200:                sc_link->openings = CDOUTSTANDING;
        !           201:
        !           202:        /*
        !           203:         * Initialize and attach the disk structure.
        !           204:         */
        !           205:        cd->sc_dk.dk_driver = &cddkdriver;
        !           206:        cd->sc_dk.dk_name = cd->sc_dev.dv_xname;
        !           207:        disk_attach(&cd->sc_dk);
        !           208:
        !           209:        /*
        !           210:         * Note if this device is ancient.  This is used in cdminphys().
        !           211:         */
        !           212:        if (!(sc_link->flags & SDEV_ATAPI) &&
        !           213:            SCSISPC(sa->sa_inqbuf->version) == 0)
        !           214:                cd->flags |= CDF_ANCIENT;
        !           215:
        !           216:        printf("\n");
        !           217:
        !           218:        timeout_set(&cd->sc_timeout, cdrestart, cd);
        !           219:
        !           220:        if ((cd->sc_cdpwrhook = powerhook_establish(cd_powerhook, cd)) == NULL)
        !           221:                printf("%s: WARNING: unable to establish power hook\n",
        !           222:                    cd->sc_dev.dv_xname);
        !           223: }
        !           224:
        !           225:
        !           226: int
        !           227: cdactivate(struct device *self, enum devact act)
        !           228: {
        !           229:        int rv = 0;
        !           230:
        !           231:        switch (act) {
        !           232:        case DVACT_ACTIVATE:
        !           233:                break;
        !           234:
        !           235:        case DVACT_DEACTIVATE:
        !           236:                /*
        !           237:                 * Nothing to do; we key off the device's DVF_ACTIVATE.
        !           238:                 */
        !           239:                break;
        !           240:        }
        !           241:        return (rv);
        !           242: }
        !           243:
        !           244:
        !           245: int
        !           246: cddetach(struct device *self, int flags)
        !           247: {
        !           248:        struct cd_softc *cd = (struct cd_softc *)self;
        !           249:        int bmaj, cmaj, mn;
        !           250:
        !           251:        cd_kill_buffers(cd);
        !           252:
        !           253:        /* Locate the lowest minor number to be detached. */
        !           254:        mn = DISKMINOR(self->dv_unit, 0);
        !           255:
        !           256:        for (bmaj = 0; bmaj < nblkdev; bmaj++)
        !           257:                if (bdevsw[bmaj].d_open == cdopen)
        !           258:                        vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK);
        !           259:        for (cmaj = 0; cmaj < nchrdev; cmaj++)
        !           260:                if (cdevsw[cmaj].d_open == cdopen)
        !           261:                        vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR);
        !           262:
        !           263:        /* Get rid of the power hook. */
        !           264:        if (cd->sc_cdpwrhook != NULL)
        !           265:                powerhook_disestablish(cd->sc_cdpwrhook);
        !           266:
        !           267:        /* Detach disk. */
        !           268:        disk_detach(&cd->sc_dk);
        !           269:
        !           270:        return (0);
        !           271: }
        !           272:
        !           273: /*
        !           274:  * Open the device. Make sure the partition info is as up-to-date as can be.
        !           275:  */
        !           276: int
        !           277: cdopen(dev_t dev, int flag, int fmt, struct proc *p)
        !           278: {
        !           279:        struct scsi_link *sc_link;
        !           280:        struct cd_softc *cd;
        !           281:        int error = 0, part, rawopen, unit;
        !           282:
        !           283:        unit = DISKUNIT(dev);
        !           284:        part = DISKPART(dev);
        !           285:
        !           286:        rawopen = (part == RAW_PART) && (fmt == S_IFCHR);
        !           287:
        !           288:        cd = cdlookup(unit);
        !           289:        if (cd == NULL)
        !           290:                return (ENXIO);
        !           291:
        !           292:        sc_link = cd->sc_link;
        !           293:        SC_DEBUG(sc_link, SDEV_DB1,
        !           294:            ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
        !           295:            cd_cd.cd_ndevs, part));
        !           296:
        !           297:        if ((error = cdlock(cd)) != 0) {
        !           298:                device_unref(&cd->sc_dev);
        !           299:                return (error);
        !           300:        }
        !           301:
        !           302:        if (cd->sc_dk.dk_openmask != 0) {
        !           303:                /*
        !           304:                 * If any partition is open, but the disk has been invalidated,
        !           305:                 * disallow further opens.
        !           306:                 */
        !           307:                if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
        !           308:                        if (rawopen)
        !           309:                                goto out;
        !           310:                        error = EIO;
        !           311:                        goto bad;
        !           312:                }
        !           313:        } else {
        !           314:                /*
        !           315:                 * Check that it is still responding and ok.  Drive can be in
        !           316:                 * progress of loading media so use increased retries number
        !           317:                 * and don't ignore NOT_READY.
        !           318:                 */
        !           319:
        !           320:                /* Use cd_interpret_sense() now. */
        !           321:                sc_link->flags |= SDEV_OPEN;
        !           322:
        !           323:                error = scsi_test_unit_ready(sc_link, TEST_READY_RETRIES,
        !           324:                    (rawopen ? SCSI_SILENT : 0) | SCSI_IGNORE_ILLEGAL_REQUEST |
        !           325:                    SCSI_IGNORE_MEDIA_CHANGE);
        !           326:
        !           327:                /* Start the cd spinning if necessary. */
        !           328:                if (error == EIO)
        !           329:                        error = scsi_start(sc_link, SSS_START,
        !           330:                            SCSI_IGNORE_ILLEGAL_REQUEST |
        !           331:                            SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT);
        !           332:
        !           333:                if (error) {
        !           334:                        if (rawopen) {
        !           335:                                error = 0;
        !           336:                                goto out;
        !           337:                        } else
        !           338:                                goto bad;
        !           339:                }
        !           340:
        !           341:                /* Lock the cd in. */
        !           342:                error = scsi_prevent(sc_link, PR_PREVENT,
        !           343:                    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE);
        !           344:                if (error)
        !           345:                        goto bad;
        !           346:
        !           347:                /* Load the physical device parameters. */
        !           348:                sc_link->flags |= SDEV_MEDIA_LOADED;
        !           349:                if (cd_get_parms(cd, 0) != 0) {
        !           350:                        sc_link->flags &= ~SDEV_MEDIA_LOADED;
        !           351:                        error = ENXIO;
        !           352:                        goto bad;
        !           353:                }
        !           354:                SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded\n"));
        !           355:
        !           356:                /* Fabricate a disk label. */
        !           357:                cdgetdisklabel(dev, cd, cd->sc_dk.dk_label, 0);
        !           358:                SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated\n"));
        !           359:        }
        !           360:
        !           361:        /* Check that the partition exists. */
        !           362:        if (part != RAW_PART && (part >= cd->sc_dk.dk_label->d_npartitions ||
        !           363:            cd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
        !           364:                error = ENXIO;
        !           365:                goto bad;
        !           366:        }
        !           367:
        !           368: out:   /* Insure only one open at a time. */
        !           369:        switch (fmt) {
        !           370:        case S_IFCHR:
        !           371:                cd->sc_dk.dk_copenmask |= (1 << part);
        !           372:                break;
        !           373:        case S_IFBLK:
        !           374:                cd->sc_dk.dk_bopenmask |= (1 << part);
        !           375:                break;
        !           376:        }
        !           377:        cd->sc_dk.dk_openmask = cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
        !           378:        sc_link->flags |= SDEV_OPEN;
        !           379:        SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
        !           380:
        !           381:        /* It's OK to fall through because dk_openmask is now non-zero. */
        !           382: bad:
        !           383:        if (cd->sc_dk.dk_openmask == 0) {
        !           384:                scsi_prevent(sc_link, PR_ALLOW,
        !           385:                    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE);
        !           386:                sc_link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED);
        !           387:        }
        !           388:
        !           389:        cdunlock(cd);
        !           390:        device_unref(&cd->sc_dev);
        !           391:        return (error);
        !           392: }
        !           393:
        !           394: /*
        !           395:  * Close the device. Only called if we are the last occurrence of an open
        !           396:  * device.
        !           397:  */
        !           398: int
        !           399: cdclose(dev_t dev, int flag, int fmt, struct proc *p)
        !           400: {
        !           401:        struct cd_softc *cd;
        !           402:        int part = DISKPART(dev);
        !           403:        int error;
        !           404:
        !           405:        cd = cdlookup(DISKUNIT(dev));
        !           406:        if (cd == NULL)
        !           407:                return ENXIO;
        !           408:
        !           409:        if ((error = cdlock(cd)) != 0) {
        !           410:                device_unref(&cd->sc_dev);
        !           411:                return error;
        !           412:        }
        !           413:
        !           414:        switch (fmt) {
        !           415:        case S_IFCHR:
        !           416:                cd->sc_dk.dk_copenmask &= ~(1 << part);
        !           417:                break;
        !           418:        case S_IFBLK:
        !           419:                cd->sc_dk.dk_bopenmask &= ~(1 << part);
        !           420:                break;
        !           421:        }
        !           422:        cd->sc_dk.dk_openmask = cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
        !           423:
        !           424:        if (cd->sc_dk.dk_openmask == 0) {
        !           425:                /* XXXX Must wait for I/O to complete! */
        !           426:
        !           427:                scsi_prevent(cd->sc_link, PR_ALLOW,
        !           428:                    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
        !           429:                cd->sc_link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED);
        !           430:
        !           431:                if (cd->sc_link->flags & SDEV_EJECTING) {
        !           432:                        scsi_start(cd->sc_link, SSS_STOP|SSS_LOEJ, 0);
        !           433:
        !           434:                        cd->sc_link->flags &= ~SDEV_EJECTING;
        !           435:                }
        !           436:
        !           437:                timeout_del(&cd->sc_timeout);
        !           438:        }
        !           439:
        !           440:        cdunlock(cd);
        !           441:
        !           442:        device_unref(&cd->sc_dev);
        !           443:        return 0;
        !           444: }
        !           445:
        !           446: /*
        !           447:  * Actually translate the requested transfer into one the physical driver can
        !           448:  * understand.  The transfer is described by a buf and will include only one
        !           449:  * physical transfer.
        !           450:  */
        !           451: void
        !           452: cdstrategy(struct buf *bp)
        !           453: {
        !           454:        struct cd_softc *cd;
        !           455:        int s;
        !           456:
        !           457:        if ((cd = cdlookup(DISKUNIT(bp->b_dev))) == NULL) {
        !           458:                bp->b_error = ENXIO;
        !           459:                goto bad;
        !           460:        }
        !           461:
        !           462:        SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdstrategy: %ld bytes @ blk %d\n",
        !           463:            bp->b_bcount, bp->b_blkno));
        !           464:        /*
        !           465:         * If the device has been made invalid, error out
        !           466:         * maybe the media changed, or no media loaded
        !           467:         */
        !           468:        if ((cd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
        !           469:                bp->b_error = EIO;
        !           470:                goto bad;
        !           471:        }
        !           472:        /*
        !           473:         * The transfer must be a whole number of blocks.
        !           474:         */
        !           475:        if ((bp->b_bcount % cd->sc_dk.dk_label->d_secsize) != 0) {
        !           476:                bp->b_error = EINVAL;
        !           477:                goto bad;
        !           478:        }
        !           479:        /*
        !           480:         * If it's a null transfer, return immediately
        !           481:         */
        !           482:        if (bp->b_bcount == 0)
        !           483:                goto done;
        !           484:
        !           485:        /*
        !           486:         * Do bounds checking, adjust transfer. if error, process.
        !           487:         * If end of partition, just return.
        !           488:         */
        !           489:        if (DISKPART(bp->b_dev) != RAW_PART &&
        !           490:            bounds_check_with_label(bp, cd->sc_dk.dk_label,
        !           491:            (cd->flags & (CDF_WLABEL|CDF_LABELLING)) != 0) <= 0)
        !           492:                goto done;
        !           493:
        !           494:        s = splbio();
        !           495:
        !           496:        /*
        !           497:         * Place it in the queue of disk activities for this disk
        !           498:         */
        !           499:        disksort(&cd->buf_queue, bp);
        !           500:
        !           501:        /*
        !           502:         * Tell the device to get going on the transfer if it's
        !           503:         * not doing anything, otherwise just wait for completion
        !           504:         */
        !           505:        cdstart(cd);
        !           506:
        !           507:        device_unref(&cd->sc_dev);
        !           508:        splx(s);
        !           509:        return;
        !           510:
        !           511: bad:
        !           512:        bp->b_flags |= B_ERROR;
        !           513: done:
        !           514:        /*
        !           515:         * Correctly set the buf to indicate a completed xfer
        !           516:         */
        !           517:        bp->b_resid = bp->b_bcount;
        !           518:        s = splbio();
        !           519:        biodone(bp);
        !           520:        splx(s);
        !           521:        if (cd != NULL)
        !           522:                device_unref(&cd->sc_dev);
        !           523: }
        !           524:
        !           525: /*
        !           526:  * cdstart looks to see if there is a buf waiting for the device
        !           527:  * and that the device is not already busy. If both are true,
        !           528:  * It deques the buf and creates a scsi command to perform the
        !           529:  * transfer in the buf. The transfer request will call scsi_done
        !           530:  * on completion, which will in turn call this routine again
        !           531:  * so that the next queued transfer is performed.
        !           532:  * The bufs are queued by the strategy routine (cdstrategy)
        !           533:  *
        !           534:  * This routine is also called after other non-queued requests
        !           535:  * have been made of the scsi driver, to ensure that the queue
        !           536:  * continues to be drained.
        !           537:  *
        !           538:  * must be called at the correct (highish) spl level
        !           539:  * cdstart() is called at splbio from cdstrategy, cdrestart and scsi_done
        !           540:  */
        !           541: void
        !           542: cdstart(void *v)
        !           543: {
        !           544:        struct cd_softc *cd = v;
        !           545:        struct scsi_link *sc_link = cd->sc_link;
        !           546:        struct buf *bp = 0;
        !           547:        struct buf *dp;
        !           548:        struct scsi_rw_big cmd_big;
        !           549:        struct scsi_rw cmd_small;
        !           550:        struct scsi_generic *cmdp;
        !           551:        int blkno, nblks, cmdlen, error;
        !           552:        struct partition *p;
        !           553:
        !           554:        splassert(IPL_BIO);
        !           555:
        !           556:        SC_DEBUG(sc_link, SDEV_DB2, ("cdstart\n"));
        !           557:        /*
        !           558:         * Check if the device has room for another command
        !           559:         */
        !           560:        while (sc_link->openings > 0) {
        !           561:                /*
        !           562:                 * there is excess capacity, but a special waits
        !           563:                 * It'll need the adapter as soon as we clear out of the
        !           564:                 * way and let it run (user level wait).
        !           565:                 */
        !           566:                if (sc_link->flags & SDEV_WAITING) {
        !           567:                        sc_link->flags &= ~SDEV_WAITING;
        !           568:                        wakeup((caddr_t)sc_link);
        !           569:                        return;
        !           570:                }
        !           571:
        !           572:                /*
        !           573:                 * See if there is a buf with work for us to do..
        !           574:                 */
        !           575:                dp = &cd->buf_queue;
        !           576:                if ((bp = dp->b_actf) == NULL)  /* yes, an assign */
        !           577:                        return;
        !           578:                dp->b_actf = bp->b_actf;
        !           579:
        !           580:                /*
        !           581:                 * If the deivce has become invalid, abort all the
        !           582:                 * reads and writes until all files have been closed and
        !           583:                 * re-opened
        !           584:                 */
        !           585:                if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
        !           586:                        bp->b_error = EIO;
        !           587:                        bp->b_flags |= B_ERROR;
        !           588:                        bp->b_resid = bp->b_bcount;
        !           589:                        biodone(bp);
        !           590:                        continue;
        !           591:                }
        !           592:
        !           593:                /*
        !           594:                 * We have a buf, now we should make a command
        !           595:                 *
        !           596:                 * First, translate the block to absolute and put it in terms
        !           597:                 * of the logical blocksize of the device.
        !           598:                 */
        !           599:                blkno =
        !           600:                    bp->b_blkno / (cd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
        !           601:                p = &cd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
        !           602:                blkno += DL_GETPOFFSET(p);
        !           603:                nblks = howmany(bp->b_bcount, cd->sc_dk.dk_label->d_secsize);
        !           604:
        !           605:                /*
        !           606:                 *  Fill out the scsi command.  If the transfer will
        !           607:                 *  fit in a "small" cdb, use it.
        !           608:                 */
        !           609:                if (!(sc_link->flags & SDEV_ATAPI) &&
        !           610:                    !(sc_link->quirks & SDEV_ONLYBIG) &&
        !           611:                    ((blkno & 0x1fffff) == blkno) &&
        !           612:                    ((nblks & 0xff) == nblks)) {
        !           613:                        /*
        !           614:                         * We can fit in a small cdb.
        !           615:                         */
        !           616:                        bzero(&cmd_small, sizeof(cmd_small));
        !           617:                        cmd_small.opcode = (bp->b_flags & B_READ) ?
        !           618:                            READ_COMMAND : WRITE_COMMAND;
        !           619:                        _lto3b(blkno, cmd_small.addr);
        !           620:                        cmd_small.length = nblks & 0xff;
        !           621:                        cmdlen = sizeof(cmd_small);
        !           622:                        cmdp = (struct scsi_generic *)&cmd_small;
        !           623:                } else {
        !           624:                        /*
        !           625:                         * Need a large cdb.
        !           626:                         */
        !           627:                        bzero(&cmd_big, sizeof(cmd_big));
        !           628:                        cmd_big.opcode = (bp->b_flags & B_READ) ?
        !           629:                            READ_BIG : WRITE_BIG;
        !           630:                        _lto4b(blkno, cmd_big.addr);
        !           631:                        _lto2b(nblks, cmd_big.length);
        !           632:                        cmdlen = sizeof(cmd_big);
        !           633:                        cmdp = (struct scsi_generic *)&cmd_big;
        !           634:                }
        !           635:
        !           636:                /* Instrumentation. */
        !           637:                disk_busy(&cd->sc_dk);
        !           638:
        !           639:                /*
        !           640:                 * Call the routine that chats with the adapter.
        !           641:                 * Note: we cannot sleep as we may be an interrupt
        !           642:                 */
        !           643:                error = scsi_scsi_cmd(sc_link, cmdp, cmdlen,
        !           644:                    (u_char *) bp->b_data, bp->b_bcount, CDRETRIES, 30000, bp,
        !           645:                    SCSI_NOSLEEP | ((bp->b_flags & B_READ) ? SCSI_DATA_IN :
        !           646:                    SCSI_DATA_OUT));
        !           647:                switch (error) {
        !           648:                case 0:
        !           649:                        timeout_del(&cd->sc_timeout);
        !           650:                        break;
        !           651:                case EAGAIN:
        !           652:                        /*
        !           653:                         * The device can't start another i/o. Try again later.
        !           654:                         */
        !           655:                        dp->b_actf = bp;
        !           656:                        disk_unbusy(&cd->sc_dk, 0, 0);
        !           657:                        timeout_add(&cd->sc_timeout, 1);
        !           658:                        return;
        !           659:                default:
        !           660:                        disk_unbusy(&cd->sc_dk, 0, 0);
        !           661:                        printf("%s: not queued, error %d\n",
        !           662:                            cd->sc_dev.dv_xname, error);
        !           663:                        break;
        !           664:                }
        !           665:        }
        !           666: }
        !           667:
        !           668: void
        !           669: cdrestart(void *v)
        !           670: {
        !           671:        int s;
        !           672:
        !           673:        s = splbio();
        !           674:        cdstart(v);
        !           675:        splx(s);
        !           676: }
        !           677:
        !           678: void
        !           679: cddone(struct scsi_xfer *xs)
        !           680: {
        !           681:        struct cd_softc *cd = xs->sc_link->device_softc;
        !           682:
        !           683:        if (xs->bp != NULL)
        !           684:                disk_unbusy(&cd->sc_dk, xs->bp->b_bcount - xs->bp->b_resid,
        !           685:                    (xs->bp->b_flags & B_READ));
        !           686: }
        !           687:
        !           688: void
        !           689: cdminphys(struct buf *bp)
        !           690: {
        !           691:        struct cd_softc *cd;
        !           692:        long max;
        !           693:
        !           694:        cd = cdlookup(DISKUNIT(bp->b_dev));
        !           695:        if (cd == NULL)
        !           696:                return;
        !           697:
        !           698:        /*
        !           699:         * If the device is ancient, we want to make sure that
        !           700:         * the transfer fits into a 6-byte cdb.
        !           701:         *
        !           702:         * XXX Note that the SCSI-I spec says that 256-block transfers
        !           703:         * are allowed in a 6-byte read/write, and are specified
        !           704:         * by setting the "length" to 0.  However, we're conservative
        !           705:         * here, allowing only 255-block transfers in case an
        !           706:         * ancient device gets confused by length == 0.  A length of 0
        !           707:         * in a 10-byte read/write actually means 0 blocks.
        !           708:         */
        !           709:        if (cd->flags & CDF_ANCIENT) {
        !           710:                max = cd->sc_dk.dk_label->d_secsize * 0xff;
        !           711:
        !           712:                if (bp->b_bcount > max)
        !           713:                        bp->b_bcount = max;
        !           714:        }
        !           715:
        !           716:        (*cd->sc_link->adapter->scsi_minphys)(bp);
        !           717:
        !           718:        device_unref(&cd->sc_dev);
        !           719: }
        !           720:
        !           721: int
        !           722: cdread(dev_t dev, struct uio *uio, int ioflag)
        !           723: {
        !           724:
        !           725:        return (physio(cdstrategy, NULL, dev, B_READ, cdminphys, uio));
        !           726: }
        !           727:
        !           728: int
        !           729: cdwrite(dev_t dev, struct uio *uio, int ioflag)
        !           730: {
        !           731:
        !           732:        return (physio(cdstrategy, NULL, dev, B_WRITE, cdminphys, uio));
        !           733: }
        !           734:
        !           735: /*
        !           736:  * conversion between minute-seconde-frame and logical block address
        !           737:  * addresses format
        !           738:  */
        !           739: void
        !           740: lba2msf (lba, m, s, f)
        !           741:        u_long lba;
        !           742:        u_char *m, *s, *f;
        !           743: {
        !           744:        u_long tmp;
        !           745:
        !           746:        tmp = lba + CD_BLOCK_OFFSET;    /* offset of first logical frame */
        !           747:        tmp &= 0xffffff;                /* negative lbas use only 24 bits */
        !           748:        *m = tmp / (CD_SECS * CD_FRAMES);
        !           749:        tmp %= (CD_SECS * CD_FRAMES);
        !           750:        *s = tmp / CD_FRAMES;
        !           751:        *f = tmp % CD_FRAMES;
        !           752: }
        !           753:
        !           754: u_long
        !           755: msf2lba (m, s, f)
        !           756:        u_char m, s, f;
        !           757: {
        !           758:
        !           759:        return ((((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET);
        !           760: }
        !           761:
        !           762:
        !           763: /*
        !           764:  * Perform special action on behalf of the user.
        !           765:  * Knows about the internals of this device
        !           766:  */
        !           767: int
        !           768: cdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
        !           769: {
        !           770:        struct cd_softc *cd;
        !           771:        struct disklabel *lp;
        !           772:        int part = DISKPART(dev);
        !           773:        int error = 0;
        !           774:
        !           775:        cd = cdlookup(DISKUNIT(dev));
        !           776:        if (cd == NULL)
        !           777:                return ENXIO;
        !           778:
        !           779:        SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%lx\n", cmd));
        !           780:
        !           781:        /*
        !           782:         * If the device is not valid.. abandon ship
        !           783:         */
        !           784:        if ((cd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
        !           785:                switch (cmd) {
        !           786:                case DIOCWLABEL:
        !           787:                case DIOCLOCK:
        !           788:                case DIOCEJECT:
        !           789:                case SCIOCIDENTIFY:
        !           790:                case SCIOCCOMMAND:
        !           791:                case SCIOCDEBUG:
        !           792:                case CDIOCLOADUNLOAD:
        !           793:                case SCIOCRESET:
        !           794:                case CDIOCGETVOL:
        !           795:                case CDIOCSETVOL:
        !           796:                case CDIOCSETMONO:
        !           797:                case CDIOCSETSTEREO:
        !           798:                case CDIOCSETMUTE:
        !           799:                case CDIOCSETLEFT:
        !           800:                case CDIOCSETRIGHT:
        !           801:                case CDIOCCLOSE:
        !           802:                case CDIOCEJECT:
        !           803:                case CDIOCALLOW:
        !           804:                case CDIOCPREVENT:
        !           805:                case CDIOCSETDEBUG:
        !           806:                case CDIOCCLRDEBUG:
        !           807:                case CDIOCRESET:
        !           808:                case DVD_AUTH:
        !           809:                case DVD_READ_STRUCT:
        !           810:                case MTIOCTOP:
        !           811:                        if (part == RAW_PART)
        !           812:                                break;
        !           813:                /* FALLTHROUGH */
        !           814:                default:
        !           815:                        if ((cd->sc_link->flags & SDEV_OPEN) == 0)
        !           816:                                error = ENODEV;
        !           817:                        else
        !           818:                                error = EIO;
        !           819:                        goto exit;
        !           820:                }
        !           821:        }
        !           822:
        !           823:        switch (cmd) {
        !           824:        case DIOCRLDINFO:
        !           825:                lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
        !           826:                cdgetdisklabel(dev, cd, lp, 0);
        !           827:                bcopy(lp, cd->sc_dk.dk_label, sizeof(*lp));
        !           828:                free(lp, M_TEMP);
        !           829:                break;
        !           830:        case DIOCGDINFO:
        !           831:        case DIOCGPDINFO:
        !           832:                *(struct disklabel *)addr = *(cd->sc_dk.dk_label);
        !           833:                break;
        !           834:
        !           835:        case DIOCGPART:
        !           836:                ((struct partinfo *)addr)->disklab = cd->sc_dk.dk_label;
        !           837:                ((struct partinfo *)addr)->part =
        !           838:                    &cd->sc_dk.dk_label->d_partitions[DISKPART(dev)];
        !           839:                break;
        !           840:
        !           841:        case DIOCWDINFO:
        !           842:        case DIOCSDINFO:
        !           843:                if ((flag & FWRITE) == 0) {
        !           844:                        error = EBADF;
        !           845:                        break;
        !           846:                }
        !           847:
        !           848:                if ((error = cdlock(cd)) != 0)
        !           849:                        break;
        !           850:
        !           851:                cd->flags |= CDF_LABELLING;
        !           852:
        !           853:                error = setdisklabel(cd->sc_dk.dk_label,
        !           854:                    (struct disklabel *)addr, /*cd->sc_dk.dk_openmask : */0);
        !           855:                if (error == 0) {
        !           856:                }
        !           857:
        !           858:                cd->flags &= ~CDF_LABELLING;
        !           859:                cdunlock(cd);
        !           860:                break;
        !           861:
        !           862:        case DIOCWLABEL:
        !           863:                error = EBADF;
        !           864:                break;
        !           865:
        !           866:        case CDIOCPLAYTRACKS: {
        !           867:                struct ioc_play_track *args = (struct ioc_play_track *)addr;
        !           868:
        !           869:                if ((error = cd_set_pa_immed(cd, 0)) != 0)
        !           870:                        break;
        !           871:                error = cd_play_tracks(cd, args->start_track,
        !           872:                    args->start_index, args->end_track, args->end_index);
        !           873:                break;
        !           874:        }
        !           875:        case CDIOCPLAYMSF: {
        !           876:                struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
        !           877:
        !           878:                if ((error = cd_set_pa_immed(cd, 0)) != 0)
        !           879:                        break;
        !           880:                error = cd_play_msf(cd, args->start_m, args->start_s,
        !           881:                    args->start_f, args->end_m, args->end_s, args->end_f);
        !           882:                break;
        !           883:        }
        !           884:        case CDIOCPLAYBLOCKS: {
        !           885:                struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
        !           886:
        !           887:                if ((error = cd_set_pa_immed(cd, 0)) != 0)
        !           888:                        break;
        !           889:                error = cd_play(cd, args->blk, args->len);
        !           890:                break;
        !           891:        }
        !           892:        case CDIOCREADSUBCHANNEL: {
        !           893:                struct ioc_read_subchannel *args
        !           894:                = (struct ioc_read_subchannel *)addr;
        !           895:                struct cd_sub_channel_info data;
        !           896:                int len = args->data_len;
        !           897:                if (len > sizeof(data) ||
        !           898:                    len < sizeof(struct cd_sub_channel_header)) {
        !           899:                        error = EINVAL;
        !           900:                        break;
        !           901:                }
        !           902:                error = cd_read_subchannel(cd, args->address_format,
        !           903:                                           args->data_format, args->track,
        !           904:                                           &data, len);
        !           905:                if (error)
        !           906:                        break;
        !           907:                len = min(len, _2btol(data.header.data_len) +
        !           908:                    sizeof(struct cd_sub_channel_header));
        !           909:                error = copyout(&data, args->data, len);
        !           910:                break;
        !           911:        }
        !           912:        case CDIOREADTOCHEADER: {
        !           913:                struct ioc_toc_header th;
        !           914:
        !           915:                if ((error = cd_read_toc(cd, 0, 0, &th, sizeof(th), 0)) != 0)
        !           916:                        break;
        !           917:                if (cd->sc_link->quirks & ADEV_LITTLETOC)
        !           918:                        th.len = letoh16(th.len);
        !           919:                else
        !           920:                        th.len = betoh16(th.len);
        !           921:                bcopy(&th, addr, sizeof(th));
        !           922:                break;
        !           923:        }
        !           924:        case CDIOREADTOCENTRYS:  {
        !           925:                struct cd_toc *toc;
        !           926:                struct ioc_read_toc_entry *te =
        !           927:                    (struct ioc_read_toc_entry *)addr;
        !           928:                struct ioc_toc_header *th;
        !           929:                struct cd_toc_entry *cte;
        !           930:                int len = te->data_len;
        !           931:                int ntracks;
        !           932:
        !           933:                MALLOC(toc, struct cd_toc *, sizeof(struct cd_toc), M_TEMP,
        !           934:                    M_WAITOK);
        !           935:                bzero(toc, sizeof(*toc));
        !           936:
        !           937:                th = &toc->header;
        !           938:
        !           939:                if (len > sizeof(toc->entries) ||
        !           940:                    len < sizeof(struct cd_toc_entry)) {
        !           941:                        FREE(toc, M_TEMP);
        !           942:                        error = EINVAL;
        !           943:                        break;
        !           944:                }
        !           945:                error = cd_read_toc(cd, te->address_format, te->starting_track,
        !           946:                    toc, len + sizeof(struct ioc_toc_header), 0);
        !           947:                if (error) {
        !           948:                        FREE(toc, M_TEMP);
        !           949:                        break;
        !           950:                }
        !           951:                if (te->address_format == CD_LBA_FORMAT)
        !           952:                        for (ntracks =
        !           953:                            th->ending_track - th->starting_track + 1;
        !           954:                            ntracks >= 0; ntracks--) {
        !           955:                                cte = &toc->entries[ntracks];
        !           956:                                cte->addr_type = CD_LBA_FORMAT;
        !           957:                                if (cd->sc_link->quirks & ADEV_LITTLETOC) {
        !           958: #if BYTE_ORDER == BIG_ENDIAN
        !           959:                                        swap16_multi((u_int16_t *)&cte->addr,
        !           960:                                            sizeof(cte->addr) / 2);
        !           961: #endif
        !           962:                                } else
        !           963:                                        cte->addr.lba = betoh32(cte->addr.lba);
        !           964:                        }
        !           965:                if (cd->sc_link->quirks & ADEV_LITTLETOC) {
        !           966:                        th->len = letoh16(th->len);
        !           967:                } else
        !           968:                        th->len = betoh16(th->len);
        !           969:                len = min(len, th->len - (sizeof(th->starting_track) +
        !           970:                    sizeof(th->ending_track)));
        !           971:
        !           972:                error = copyout(toc->entries, te->data, len);
        !           973:                FREE(toc, M_TEMP);
        !           974:                break;
        !           975:        }
        !           976:        case CDIOREADMSADDR: {
        !           977:                struct cd_toc *toc;
        !           978:                int sessno = *(int *)addr;
        !           979:                struct cd_toc_entry *cte;
        !           980:
        !           981:                if (sessno != 0) {
        !           982:                        error = EINVAL;
        !           983:                        break;
        !           984:                }
        !           985:
        !           986:                MALLOC(toc, struct cd_toc *, sizeof(struct cd_toc), M_TEMP,
        !           987:                    M_WAITOK);
        !           988:                bzero(toc, sizeof(*toc));
        !           989:
        !           990:                error = cd_read_toc(cd, 0, 0, toc,
        !           991:                  sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry),
        !           992:                  0x40 /* control word for "get MS info" */);
        !           993:
        !           994:                if (error) {
        !           995:                        FREE(toc, M_TEMP);
        !           996:                        break;
        !           997:                }
        !           998:
        !           999:                cte = &toc->entries[0];
        !          1000:                if (cd->sc_link->quirks & ADEV_LITTLETOC) {
        !          1001: #if BYTE_ORDER == BIG_ENDIAN
        !          1002:                        swap16_multi((u_int16_t *)&cte->addr,
        !          1003:                            sizeof(cte->addr) / 2);
        !          1004: #endif
        !          1005:                } else
        !          1006:                        cte->addr.lba = betoh32(cte->addr.lba);
        !          1007:                if (cd->sc_link->quirks & ADEV_LITTLETOC)
        !          1008:                        toc->header.len = letoh16(toc->header.len);
        !          1009:                else
        !          1010:                        toc->header.len = betoh16(toc->header.len);
        !          1011:
        !          1012:                *(int *)addr = (toc->header.len >= 10 && cte->track > 1) ?
        !          1013:                        cte->addr.lba : 0;
        !          1014:                FREE(toc, M_TEMP);
        !          1015:                break;
        !          1016:        }
        !          1017:        case CDIOCSETPATCH: {
        !          1018:                struct ioc_patch *arg = (struct ioc_patch *)addr;
        !          1019:
        !          1020:                error = cd_setchan(cd, arg->patch[0], arg->patch[1],
        !          1021:                    arg->patch[2], arg->patch[3], 0);
        !          1022:                break;
        !          1023:        }
        !          1024:        case CDIOCGETVOL: {
        !          1025:                struct ioc_vol *arg = (struct ioc_vol *)addr;
        !          1026:
        !          1027:                error = cd_getvol(cd, arg, 0);
        !          1028:                break;
        !          1029:        }
        !          1030:        case CDIOCSETVOL: {
        !          1031:                struct ioc_vol *arg = (struct ioc_vol *)addr;
        !          1032:
        !          1033:                error = cd_setvol(cd, arg, 0);
        !          1034:                break;
        !          1035:        }
        !          1036:
        !          1037:        case CDIOCSETMONO:
        !          1038:                error = cd_setchan(cd, BOTH_CHANNEL, BOTH_CHANNEL, MUTE_CHANNEL,
        !          1039:                    MUTE_CHANNEL, 0);
        !          1040:                break;
        !          1041:
        !          1042:        case CDIOCSETSTEREO:
        !          1043:                error = cd_setchan(cd, LEFT_CHANNEL, RIGHT_CHANNEL,
        !          1044:                    MUTE_CHANNEL, MUTE_CHANNEL, 0);
        !          1045:                break;
        !          1046:
        !          1047:        case CDIOCSETMUTE:
        !          1048:                error = cd_setchan(cd, MUTE_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL,
        !          1049:                    MUTE_CHANNEL, 0);
        !          1050:                break;
        !          1051:
        !          1052:        case CDIOCSETLEFT:
        !          1053:                error = cd_setchan(cd, LEFT_CHANNEL, LEFT_CHANNEL, MUTE_CHANNEL,
        !          1054:                    MUTE_CHANNEL, 0);
        !          1055:                break;
        !          1056:
        !          1057:        case CDIOCSETRIGHT:
        !          1058:                error = cd_setchan(cd, RIGHT_CHANNEL, RIGHT_CHANNEL,
        !          1059:                    MUTE_CHANNEL, MUTE_CHANNEL, 0);
        !          1060:                break;
        !          1061:
        !          1062:        case CDIOCRESUME:
        !          1063:                error = cd_pause(cd, 1);
        !          1064:                break;
        !          1065:
        !          1066:        case CDIOCPAUSE:
        !          1067:                error = cd_pause(cd, 0);
        !          1068:                break;
        !          1069:        case CDIOCSTART:
        !          1070:                error = scsi_start(cd->sc_link, SSS_START, 0);
        !          1071:                break;
        !          1072:
        !          1073:        case CDIOCSTOP:
        !          1074:                error = scsi_start(cd->sc_link, SSS_STOP, 0);
        !          1075:                break;
        !          1076:
        !          1077:        close_tray:
        !          1078:        case CDIOCCLOSE:
        !          1079:                error = scsi_start(cd->sc_link, SSS_START|SSS_LOEJ,
        !          1080:                    SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE);
        !          1081:                break;
        !          1082:
        !          1083:        case MTIOCTOP:
        !          1084:                if (((struct mtop *)addr)->mt_op == MTRETEN)
        !          1085:                        goto close_tray;
        !          1086:                if (((struct mtop *)addr)->mt_op != MTOFFL) {
        !          1087:                        error = EIO;
        !          1088:                        break;
        !          1089:                }
        !          1090:                /* FALLTHROUGH */
        !          1091:        case CDIOCEJECT: /* FALLTHROUGH */
        !          1092:        case DIOCEJECT:
        !          1093:                cd->sc_link->flags |= SDEV_EJECTING;
        !          1094:                break;
        !          1095:        case CDIOCALLOW:
        !          1096:                error = scsi_prevent(cd->sc_link, PR_ALLOW, 0);
        !          1097:                break;
        !          1098:        case CDIOCPREVENT:
        !          1099:                error = scsi_prevent(cd->sc_link, PR_PREVENT, 0);
        !          1100:                break;
        !          1101:        case DIOCLOCK:
        !          1102:                error = scsi_prevent(cd->sc_link,
        !          1103:                    (*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0);
        !          1104:                break;
        !          1105:        case CDIOCSETDEBUG:
        !          1106:                cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
        !          1107:                break;
        !          1108:        case CDIOCCLRDEBUG:
        !          1109:                cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
        !          1110:                break;
        !          1111:        case CDIOCRESET:
        !          1112:        case SCIOCRESET:
        !          1113:                error = cd_reset(cd);
        !          1114:                break;
        !          1115:        case CDIOCLOADUNLOAD: {
        !          1116:                struct ioc_load_unload *args = (struct ioc_load_unload *)addr;
        !          1117:
        !          1118:                error = cd_load_unload(cd, args->options, args->slot);
        !          1119:                break;
        !          1120:        }
        !          1121:
        !          1122:        case DVD_AUTH:
        !          1123:                error = dvd_auth(cd, (union dvd_authinfo *)addr);
        !          1124:                break;
        !          1125:        case DVD_READ_STRUCT:
        !          1126:                error = dvd_read_struct(cd, (union dvd_struct *)addr);
        !          1127:                break;
        !          1128:        default:
        !          1129:                if (DISKPART(dev) != RAW_PART) {
        !          1130:                        error = ENOTTY;
        !          1131:                        break;
        !          1132:                }
        !          1133:                error = scsi_do_ioctl(cd->sc_link, dev, cmd, addr, flag, p);
        !          1134:                break;
        !          1135:        }
        !          1136:
        !          1137:  exit:
        !          1138:
        !          1139:        device_unref(&cd->sc_dev);
        !          1140:        return (error);
        !          1141: }
        !          1142:
        !          1143: /*
        !          1144:  * Load the label information on the named device
        !          1145:  * Actually fabricate a disklabel
        !          1146:  *
        !          1147:  * EVENTUALLY take information about different
        !          1148:  * data tracks from the TOC and put it in the disklabel
        !          1149:  */
        !          1150: void
        !          1151: cdgetdisklabel(dev_t dev, struct cd_softc *cd, struct disklabel *lp,
        !          1152:     int spoofonly)
        !          1153: {
        !          1154:        struct cd_toc *toc;
        !          1155:        char *errstring;
        !          1156:        int tocidx, n, audioonly = 1;
        !          1157:
        !          1158:        bzero(lp, sizeof(struct disklabel));
        !          1159:
        !          1160:        MALLOC(toc, struct cd_toc *, sizeof(struct cd_toc), M_TEMP, M_WAITOK);
        !          1161:        bzero(toc, sizeof(*toc));
        !          1162:
        !          1163:        lp->d_secsize = cd->params.blksize;
        !          1164:        lp->d_ntracks = 1;
        !          1165:        lp->d_nsectors = 100;
        !          1166:        lp->d_secpercyl = 100;
        !          1167:        lp->d_ncylinders = (cd->params.disksize / 100) + 1;
        !          1168:
        !          1169:        if (cd->sc_link->flags & SDEV_ATAPI) {
        !          1170:                strncpy(lp->d_typename, "ATAPI CD-ROM", sizeof(lp->d_typename));
        !          1171:                lp->d_type = DTYPE_ATAPI;
        !          1172:        } else {
        !          1173:                strncpy(lp->d_typename, "SCSI CD-ROM", sizeof(lp->d_typename));
        !          1174:                lp->d_type = DTYPE_SCSI;
        !          1175:        }
        !          1176:
        !          1177:        strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
        !          1178:        DL_SETDSIZE(lp, cd->params.disksize);
        !          1179:        lp->d_rpm = 300;
        !          1180:        lp->d_interleave = 1;
        !          1181:        lp->d_version = 1;
        !          1182:
        !          1183:        /* XXX - these values for BBSIZE and SBSIZE assume ffs */
        !          1184:        lp->d_bbsize = BBSIZE;
        !          1185:        lp->d_sbsize = SBSIZE;
        !          1186:
        !          1187:        lp->d_magic = DISKMAGIC;
        !          1188:        lp->d_magic2 = DISKMAGIC;
        !          1189:        lp->d_checksum = dkcksum(lp);
        !          1190:
        !          1191:        if (cd_load_toc(cd, toc, CD_LBA_FORMAT)) {
        !          1192:                audioonly = 0; /* No valid TOC found == not an audio CD. */
        !          1193:                goto done;
        !          1194:        }
        !          1195:
        !          1196:        n = toc->header.ending_track - toc->header.starting_track + 1;
        !          1197:        for (tocidx = 0; tocidx < n; tocidx++)
        !          1198:                if (toc->entries[tocidx].control & 4) {
        !          1199:                        audioonly = 0; /* Found a non-audio track. */
        !          1200:                        goto done;
        !          1201:                }
        !          1202:
        !          1203: done:
        !          1204:        free(toc, M_TEMP);
        !          1205:
        !          1206:        if (!audioonly) {
        !          1207:                errstring = readdisklabel(DISKLABELDEV(dev), cdstrategy, lp,
        !          1208:                    spoofonly);
        !          1209:                /*if (errstring)
        !          1210:                        printf("%s: %s\n", cd->sc_dev.dv_xname, errstring);*/
        !          1211:        }
        !          1212: }
        !          1213:
        !          1214: /*
        !          1215:  * Find out from the device what its capacity is
        !          1216:  */
        !          1217: u_long
        !          1218: cd_size(struct cd_softc *cd, int flags)
        !          1219: {
        !          1220:        struct scsi_read_cd_cap_data rdcap;
        !          1221:        struct scsi_read_cd_capacity scsi_cmd;
        !          1222:        u_long size;
        !          1223:        int blksize;
        !          1224:
        !          1225:        /* Reasonable defaults for drives that don't support
        !          1226:           READ_CD_CAPACITY */
        !          1227:        cd->params.blksize = 2048;
        !          1228:        cd->params.disksize = 400000;
        !          1229:
        !          1230:        if (cd->sc_link->quirks & ADEV_NOCAPACITY)
        !          1231:                goto exit;
        !          1232:
        !          1233:        /*
        !          1234:         * make up a scsi command and ask the scsi driver to do
        !          1235:         * it for you.
        !          1236:         */
        !          1237:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1238:        scsi_cmd.opcode = READ_CD_CAPACITY;
        !          1239:
        !          1240:        /*
        !          1241:         * If the command works, interpret the result as a 4 byte
        !          1242:         * number of blocks and a blocksize
        !          1243:         */
        !          1244:        if (scsi_scsi_cmd(cd->sc_link,
        !          1245:            (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
        !          1246:            (u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 20000, NULL,
        !          1247:            flags | SCSI_DATA_IN) != 0)
        !          1248:                goto exit;
        !          1249:
        !          1250:        blksize = _4btol(rdcap.length);
        !          1251:        if ((blksize < 512) || ((blksize & 511) != 0))
        !          1252:                blksize = 2048; /* some drives lie ! */
        !          1253:        cd->params.blksize = blksize;
        !          1254:
        !          1255:        size = _4btol(rdcap.addr) + 1;
        !          1256:        if (size < 100)
        !          1257:                size = 400000;  /* ditto */
        !          1258:        cd->params.disksize = size;
        !          1259:
        !          1260:  exit:
        !          1261:        SC_DEBUG(cd->sc_link, SDEV_DB2, ("cd_size: %d %ld\n", blksize, size));
        !          1262:        return (cd->params.disksize);
        !          1263: }
        !          1264:
        !          1265: int
        !          1266: cd_setchan(struct cd_softc *cd, int p0, int p1, int p2, int p3, int flags)
        !          1267: {
        !          1268:        union scsi_mode_sense_buf *data;
        !          1269:        struct cd_audio_page *audio = NULL;
        !          1270:        int error, big;
        !          1271:
        !          1272:        data = malloc(sizeof(*data), M_TEMP, M_NOWAIT);
        !          1273:        if (data == NULL)
        !          1274:                return (ENOMEM);
        !          1275:
        !          1276:        error = scsi_do_mode_sense(cd->sc_link, AUDIO_PAGE, data,
        !          1277:            (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, &big);
        !          1278:        if (error == 0 && audio == NULL)
        !          1279:                error = EIO;
        !          1280:
        !          1281:        if (error == 0) {
        !          1282:                audio->port[LEFT_PORT].channels = p0;
        !          1283:                audio->port[RIGHT_PORT].channels = p1;
        !          1284:                audio->port[2].channels = p2;
        !          1285:                audio->port[3].channels = p3;
        !          1286:                if (big)
        !          1287:                        error = scsi_mode_select_big(cd->sc_link, SMS_PF,
        !          1288:                            &data->hdr_big, flags, 20000);
        !          1289:                else
        !          1290:                        error = scsi_mode_select(cd->sc_link, SMS_PF,
        !          1291:                            &data->hdr, flags, 20000);
        !          1292:        }
        !          1293:
        !          1294:        free(data, M_TEMP);
        !          1295:        return (error);
        !          1296: }
        !          1297:
        !          1298: int
        !          1299: cd_getvol(struct cd_softc *cd, struct ioc_vol *arg, int flags)
        !          1300: {
        !          1301:        union scsi_mode_sense_buf *data;
        !          1302:        struct cd_audio_page *audio = NULL;
        !          1303:        int error;
        !          1304:
        !          1305:        data = malloc(sizeof(*data), M_TEMP, M_NOWAIT);
        !          1306:        if (data == NULL)
        !          1307:                return (ENOMEM);
        !          1308:
        !          1309:        error = scsi_do_mode_sense(cd->sc_link, AUDIO_PAGE, data,
        !          1310:            (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, NULL);
        !          1311:        if (error == 0 && audio == NULL)
        !          1312:                error = EIO;
        !          1313:
        !          1314:        if (error == 0) {
        !          1315:                arg->vol[0] = audio->port[0].volume;
        !          1316:                arg->vol[1] = audio->port[1].volume;
        !          1317:                arg->vol[2] = audio->port[2].volume;
        !          1318:                arg->vol[3] = audio->port[3].volume;
        !          1319:        }
        !          1320:
        !          1321:        free(data, M_TEMP);
        !          1322:        return (0);
        !          1323: }
        !          1324:
        !          1325: int
        !          1326: cd_setvol(struct cd_softc *cd, const struct ioc_vol *arg, int flags)
        !          1327: {
        !          1328:        union scsi_mode_sense_buf *data;
        !          1329:        struct cd_audio_page *audio = NULL;
        !          1330:        u_int8_t mask_volume[4];
        !          1331:        int error, big;
        !          1332:
        !          1333:        data = malloc(sizeof(*data), M_TEMP, M_NOWAIT);
        !          1334:        if (data == NULL)
        !          1335:                return (ENOMEM);
        !          1336:
        !          1337:        error = scsi_do_mode_sense(cd->sc_link,
        !          1338:            AUDIO_PAGE | SMS_PAGE_CTRL_CHANGEABLE, data, (void **)&audio, NULL,
        !          1339:            NULL, NULL, sizeof(*audio), flags, NULL);
        !          1340:        if (error == 0 && audio == NULL)
        !          1341:                error = EIO;
        !          1342:        if (error != 0) {
        !          1343:                free(data, M_TEMP);
        !          1344:                return (error);
        !          1345:        }
        !          1346:
        !          1347:        mask_volume[0] = audio->port[0].volume;
        !          1348:        mask_volume[1] = audio->port[1].volume;
        !          1349:        mask_volume[2] = audio->port[2].volume;
        !          1350:        mask_volume[3] = audio->port[3].volume;
        !          1351:
        !          1352:        error = scsi_do_mode_sense(cd->sc_link, AUDIO_PAGE, data,
        !          1353:            (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, &big);
        !          1354:        if (error == 0 && audio == NULL)
        !          1355:                error = EIO;
        !          1356:        if (error != 0) {
        !          1357:                free(data, M_TEMP);
        !          1358:                return (error);
        !          1359:        }
        !          1360:
        !          1361:        audio->port[0].volume = arg->vol[0] & mask_volume[0];
        !          1362:        audio->port[1].volume = arg->vol[1] & mask_volume[1];
        !          1363:        audio->port[2].volume = arg->vol[2] & mask_volume[2];
        !          1364:        audio->port[3].volume = arg->vol[3] & mask_volume[3];
        !          1365:
        !          1366:        if (big)
        !          1367:                error = scsi_mode_select_big(cd->sc_link, SMS_PF,
        !          1368:                    &data->hdr_big, flags, 20000);
        !          1369:        else
        !          1370:                error = scsi_mode_select(cd->sc_link, SMS_PF,
        !          1371:                    &data->hdr, flags, 20000);
        !          1372:
        !          1373:        free(data, M_TEMP);
        !          1374:        return (error);
        !          1375: }
        !          1376:
        !          1377: int
        !          1378: cd_load_unload(struct cd_softc *cd, int options, int slot)
        !          1379: {
        !          1380:        struct scsi_load_unload cmd;
        !          1381:
        !          1382:        bzero(&cmd, sizeof(cmd));
        !          1383:        cmd.opcode = LOAD_UNLOAD;
        !          1384:        cmd.options = options;    /* ioctl uses ATAPI values */
        !          1385:        cmd.slot = slot;
        !          1386:
        !          1387:        return (scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&cmd,
        !          1388:            sizeof(cmd), 0, 0, CDRETRIES, 200000, NULL, 0));
        !          1389: }
        !          1390:
        !          1391: int
        !          1392: cd_set_pa_immed(struct cd_softc *cd, int flags)
        !          1393: {
        !          1394:        union scsi_mode_sense_buf *data;
        !          1395:        struct cd_audio_page *audio = NULL;
        !          1396:        int error, oflags, big;
        !          1397:
        !          1398:        if (cd->sc_link->flags & SDEV_ATAPI)
        !          1399:                /* XXX Noop? */
        !          1400:                return (0);
        !          1401:
        !          1402:        data = malloc(sizeof(*data), M_TEMP, M_NOWAIT);
        !          1403:        if (data == NULL)
        !          1404:                return (ENOMEM);
        !          1405:
        !          1406:        error = scsi_do_mode_sense(cd->sc_link, AUDIO_PAGE, data,
        !          1407:            (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, &big);
        !          1408:        if (error == 0 && audio == NULL)
        !          1409:                error = EIO;
        !          1410:
        !          1411:        if (error == 0) {
        !          1412:                oflags = audio->flags;
        !          1413:                audio->flags &= ~CD_PA_SOTC;
        !          1414:                audio->flags |= CD_PA_IMMED;
        !          1415:                if (audio->flags != oflags) {
        !          1416:                        if (big)
        !          1417:                                error = scsi_mode_select_big(cd->sc_link,
        !          1418:                                    SMS_PF, &data->hdr_big, flags,
        !          1419:                                    20000);
        !          1420:                        else
        !          1421:                                error = scsi_mode_select(cd->sc_link, SMS_PF,
        !          1422:                                    &data->hdr, flags, 20000);
        !          1423:                }
        !          1424:        }
        !          1425:
        !          1426:        free(data, M_TEMP);
        !          1427:        return (error);
        !          1428: }
        !          1429:
        !          1430: /*
        !          1431:  * Get scsi driver to send a "start playing" command
        !          1432:  */
        !          1433: int
        !          1434: cd_play(struct cd_softc *cd, int blkno, int nblks)
        !          1435: {
        !          1436:        struct scsi_play scsi_cmd;
        !          1437:
        !          1438:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1439:        scsi_cmd.opcode = PLAY;
        !          1440:        _lto4b(blkno, scsi_cmd.blk_addr);
        !          1441:        _lto2b(nblks, scsi_cmd.xfer_len);
        !          1442:        return (scsi_scsi_cmd(cd->sc_link,
        !          1443:            (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
        !          1444:            0, 0, CDRETRIES, 200000, NULL, 0));
        !          1445: }
        !          1446:
        !          1447: /*
        !          1448:  * Get scsi driver to send a "start playing" command
        !          1449:  */
        !          1450: int
        !          1451: cd_play_tracks(struct cd_softc *cd, int strack, int sindex, int etrack,
        !          1452:     int eindex)
        !          1453: {
        !          1454:        struct cd_toc *toc;
        !          1455:        u_char endf, ends, endm;
        !          1456:        int error;
        !          1457:
        !          1458:        if (!etrack)
        !          1459:                return (EIO);
        !          1460:        if (strack > etrack)
        !          1461:                return (EINVAL);
        !          1462:
        !          1463:        MALLOC(toc, struct cd_toc *, sizeof(struct cd_toc), M_TEMP, M_WAITOK);
        !          1464:        bzero(toc, sizeof(*toc));
        !          1465:
        !          1466:        if ((error = cd_load_toc(cd, toc, CD_MSF_FORMAT)) != 0)
        !          1467:                goto done;
        !          1468:
        !          1469:        if (++etrack > (toc->header.ending_track+1))
        !          1470:                etrack = toc->header.ending_track+1;
        !          1471:
        !          1472:        strack -= toc->header.starting_track;
        !          1473:        etrack -= toc->header.starting_track;
        !          1474:        if (strack < 0) {
        !          1475:                error = EINVAL;
        !          1476:                goto done;
        !          1477:        }
        !          1478:
        !          1479:        /*
        !          1480:         * The track ends one frame before the next begins.  The last track
        !          1481:         * is taken care of by the leadoff track.
        !          1482:         */
        !          1483:        endm = toc->entries[etrack].addr.msf.minute;
        !          1484:        ends = toc->entries[etrack].addr.msf.second;
        !          1485:        endf = toc->entries[etrack].addr.msf.frame;
        !          1486:        if (endf-- == 0) {
        !          1487:                endf = CD_FRAMES - 1;
        !          1488:                if (ends-- == 0) {
        !          1489:                        ends = CD_SECS - 1;
        !          1490:                        if (endm-- == 0) {
        !          1491:                                error = EINVAL;
        !          1492:                                goto done;
        !          1493:                        }
        !          1494:                }
        !          1495:        }
        !          1496:
        !          1497:        error = cd_play_msf(cd, toc->entries[strack].addr.msf.minute,
        !          1498:            toc->entries[strack].addr.msf.second,
        !          1499:            toc->entries[strack].addr.msf.frame,
        !          1500:            endm, ends, endf);
        !          1501:
        !          1502: done:
        !          1503:        FREE(toc, M_TEMP);
        !          1504:        return (error);
        !          1505: }
        !          1506:
        !          1507: /*
        !          1508:  * Get scsi driver to send a "play msf" command
        !          1509:  */
        !          1510: int
        !          1511: cd_play_msf(struct cd_softc *cd, int startm, int starts, int startf, int endm,
        !          1512:     int ends, int endf)
        !          1513: {
        !          1514:        struct scsi_play_msf scsi_cmd;
        !          1515:
        !          1516:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1517:        scsi_cmd.opcode = PLAY_MSF;
        !          1518:        scsi_cmd.start_m = startm;
        !          1519:        scsi_cmd.start_s = starts;
        !          1520:        scsi_cmd.start_f = startf;
        !          1521:        scsi_cmd.end_m = endm;
        !          1522:        scsi_cmd.end_s = ends;
        !          1523:        scsi_cmd.end_f = endf;
        !          1524:        return (scsi_scsi_cmd(cd->sc_link,
        !          1525:            (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
        !          1526:            0, 0, CDRETRIES, 20000, NULL, 0));
        !          1527: }
        !          1528:
        !          1529: /*
        !          1530:  * Get scsi driver to send a "start up" command
        !          1531:  */
        !          1532: int
        !          1533: cd_pause(struct cd_softc *cd, int go)
        !          1534: {
        !          1535:        struct scsi_pause scsi_cmd;
        !          1536:
        !          1537:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1538:        scsi_cmd.opcode = PAUSE;
        !          1539:        scsi_cmd.resume = go;
        !          1540:        return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
        !          1541:            sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
        !          1542: }
        !          1543:
        !          1544: /*
        !          1545:  * Get scsi driver to send a "RESET" command
        !          1546:  */
        !          1547: int
        !          1548: cd_reset(struct cd_softc *cd)
        !          1549: {
        !          1550:        return scsi_scsi_cmd(cd->sc_link, 0, 0, 0, 0, CDRETRIES, 2000, NULL,
        !          1551:            SCSI_RESET);
        !          1552: }
        !          1553:
        !          1554: /*
        !          1555:  * Read subchannel
        !          1556:  */
        !          1557: int
        !          1558: cd_read_subchannel(struct cd_softc *cd, int mode, int format, int track,
        !          1559:     struct cd_sub_channel_info *data, int len)
        !          1560: {
        !          1561:        struct scsi_read_subchannel scsi_cmd;
        !          1562:
        !          1563:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1564:        scsi_cmd.opcode = READ_SUBCHANNEL;
        !          1565:        if (mode == CD_MSF_FORMAT)
        !          1566:                scsi_cmd.byte2 |= CD_MSF;
        !          1567:        scsi_cmd.byte3 = SRS_SUBQ;
        !          1568:        scsi_cmd.subchan_format = format;
        !          1569:        scsi_cmd.track = track;
        !          1570:        _lto2b(len, scsi_cmd.data_len);
        !          1571:        return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
        !          1572:            sizeof(struct scsi_read_subchannel), (u_char *)data, len,
        !          1573:            CDRETRIES, 5000, NULL, SCSI_DATA_IN|SCSI_SILENT);
        !          1574: }
        !          1575:
        !          1576: /*
        !          1577:  * Read table of contents
        !          1578:  */
        !          1579: int
        !          1580: cd_read_toc(struct cd_softc *cd, int mode, int start, void *data, int len,
        !          1581:     int control)
        !          1582: {
        !          1583:        struct scsi_read_toc scsi_cmd;
        !          1584:
        !          1585:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1586:        bzero(data, len);
        !          1587:
        !          1588:        scsi_cmd.opcode = READ_TOC;
        !          1589:        if (mode == CD_MSF_FORMAT)
        !          1590:                scsi_cmd.byte2 |= CD_MSF;
        !          1591:        scsi_cmd.from_track = start;
        !          1592:        _lto2b(len, scsi_cmd.data_len);
        !          1593:        scsi_cmd.control = control;
        !          1594:
        !          1595:        return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
        !          1596:            sizeof(struct scsi_read_toc), (u_char *)data, len, CDRETRIES,
        !          1597:            5000, NULL, SCSI_DATA_IN | SCSI_IGNORE_ILLEGAL_REQUEST);
        !          1598: }
        !          1599:
        !          1600: int
        !          1601: cd_load_toc(struct cd_softc *cd, struct cd_toc *toc, int fmt)
        !          1602: {
        !          1603:        int n, len, error;
        !          1604:
        !          1605:        error = cd_read_toc(cd, 0, 0, toc, sizeof(toc->header), 0);
        !          1606:
        !          1607:        if (error == 0) {
        !          1608:                if (toc->header.ending_track < toc->header.starting_track)
        !          1609:                        return (EIO);
        !          1610:                /* +2 to account for leading out track. */
        !          1611:                n = toc->header.ending_track - toc->header.starting_track + 2;
        !          1612:                len = n * sizeof(struct cd_toc_entry) + sizeof(toc->header);
        !          1613:                error = cd_read_toc(cd, fmt, 0, toc, len, 0);
        !          1614:        }
        !          1615:
        !          1616:        return (error);
        !          1617: }
        !          1618:
        !          1619:
        !          1620: /*
        !          1621:  * Get the scsi driver to send a full inquiry to the device and use the
        !          1622:  * results to fill out the disk parameter structure.
        !          1623:  */
        !          1624: int
        !          1625: cd_get_parms(struct cd_softc *cd, int flags)
        !          1626: {
        !          1627:        /*
        !          1628:         * give a number of sectors so that sec * trks * cyls
        !          1629:         * is <= disk_size
        !          1630:         */
        !          1631:        if (cd_size(cd, flags) == 0)
        !          1632:                return (ENXIO);
        !          1633:        return (0);
        !          1634: }
        !          1635:
        !          1636: daddr64_t
        !          1637: cdsize(dev_t dev)
        !          1638: {
        !          1639:
        !          1640:        /* CD-ROMs are read-only. */
        !          1641:        return -1;
        !          1642: }
        !          1643:
        !          1644: int
        !          1645: cddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size)
        !          1646: {
        !          1647:        /* Not implemented. */
        !          1648:        return ENXIO;
        !          1649: }
        !          1650:
        !          1651: #define        dvd_copy_key(dst, src)          bcopy((src), (dst), DVD_KEY_SIZE)
        !          1652: #define        dvd_copy_challenge(dst, src)    bcopy((src), (dst), DVD_CHALLENGE_SIZE)
        !          1653:
        !          1654: int
        !          1655: dvd_auth(struct cd_softc *cd, union dvd_authinfo *a)
        !          1656: {
        !          1657:        struct scsi_generic cmd;
        !          1658:        u_int8_t buf[20];
        !          1659:        int error;
        !          1660:
        !          1661:        bzero(cmd.bytes, sizeof(cmd.bytes));
        !          1662:        bzero(buf, sizeof(buf));
        !          1663:
        !          1664:        switch (a->type) {
        !          1665:        case DVD_LU_SEND_AGID:
        !          1666:                cmd.opcode = GPCMD_REPORT_KEY;
        !          1667:                cmd.bytes[8] = 8;
        !          1668:                cmd.bytes[9] = 0 | (0 << 6);
        !          1669:                error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8,
        !          1670:                    CDRETRIES, 30000, NULL, SCSI_DATA_IN);
        !          1671:                if (error)
        !          1672:                        return (error);
        !          1673:                a->lsa.agid = buf[7] >> 6;
        !          1674:                return (0);
        !          1675:
        !          1676:        case DVD_LU_SEND_CHALLENGE:
        !          1677:                cmd.opcode = GPCMD_REPORT_KEY;
        !          1678:                cmd.bytes[8] = 16;
        !          1679:                cmd.bytes[9] = 1 | (a->lsc.agid << 6);
        !          1680:                error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 16,
        !          1681:                    CDRETRIES, 30000, NULL, SCSI_DATA_IN);
        !          1682:                if (error)
        !          1683:                        return (error);
        !          1684:                dvd_copy_challenge(a->lsc.chal, &buf[4]);
        !          1685:                return (0);
        !          1686:
        !          1687:        case DVD_LU_SEND_KEY1:
        !          1688:                cmd.opcode = GPCMD_REPORT_KEY;
        !          1689:                cmd.bytes[8] = 12;
        !          1690:                cmd.bytes[9] = 2 | (a->lsk.agid << 6);
        !          1691:                error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 12,
        !          1692:                    CDRETRIES, 30000, NULL, SCSI_DATA_IN);
        !          1693:                if (error)
        !          1694:                        return (error);
        !          1695:                dvd_copy_key(a->lsk.key, &buf[4]);
        !          1696:                return (0);
        !          1697:
        !          1698:        case DVD_LU_SEND_TITLE_KEY:
        !          1699:                cmd.opcode = GPCMD_REPORT_KEY;
        !          1700:                _lto4b(a->lstk.lba, &cmd.bytes[1]);
        !          1701:                cmd.bytes[8] = 12;
        !          1702:                cmd.bytes[9] = 4 | (a->lstk.agid << 6);
        !          1703:                error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 12,
        !          1704:                    CDRETRIES, 30000, NULL, SCSI_DATA_IN);
        !          1705:                if (error)
        !          1706:                        return (error);
        !          1707:                a->lstk.cpm = (buf[4] >> 7) & 1;
        !          1708:                a->lstk.cp_sec = (buf[4] >> 6) & 1;
        !          1709:                a->lstk.cgms = (buf[4] >> 4) & 3;
        !          1710:                dvd_copy_key(a->lstk.title_key, &buf[5]);
        !          1711:                return (0);
        !          1712:
        !          1713:        case DVD_LU_SEND_ASF:
        !          1714:                cmd.opcode = GPCMD_REPORT_KEY;
        !          1715:                cmd.bytes[8] = 8;
        !          1716:                cmd.bytes[9] = 5 | (a->lsasf.agid << 6);
        !          1717:                error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8,
        !          1718:                    CDRETRIES, 30000, NULL, SCSI_DATA_IN);
        !          1719:                if (error)
        !          1720:                        return (error);
        !          1721:                a->lsasf.asf = buf[7] & 1;
        !          1722:                return (0);
        !          1723:
        !          1724:        case DVD_HOST_SEND_CHALLENGE:
        !          1725:                cmd.opcode = GPCMD_SEND_KEY;
        !          1726:                cmd.bytes[8] = 16;
        !          1727:                cmd.bytes[9] = 1 | (a->hsc.agid << 6);
        !          1728:                buf[1] = 14;
        !          1729:                dvd_copy_challenge(&buf[4], a->hsc.chal);
        !          1730:                error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 16,
        !          1731:                    CDRETRIES, 30000, NULL, SCSI_DATA_OUT);
        !          1732:                if (error)
        !          1733:                        return (error);
        !          1734:                a->type = DVD_LU_SEND_KEY1;
        !          1735:                return (0);
        !          1736:
        !          1737:        case DVD_HOST_SEND_KEY2:
        !          1738:                cmd.opcode = GPCMD_SEND_KEY;
        !          1739:                cmd.bytes[8] = 12;
        !          1740:                cmd.bytes[9] = 3 | (a->hsk.agid << 6);
        !          1741:                buf[1] = 10;
        !          1742:                dvd_copy_key(&buf[4], a->hsk.key);
        !          1743:                error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 12,
        !          1744:                    CDRETRIES, 30000, NULL, SCSI_DATA_OUT);
        !          1745:                if (error) {
        !          1746:                        a->type = DVD_AUTH_FAILURE;
        !          1747:                        return (error);
        !          1748:                }
        !          1749:                a->type = DVD_AUTH_ESTABLISHED;
        !          1750:                return (0);
        !          1751:
        !          1752:        case DVD_INVALIDATE_AGID:
        !          1753:                cmd.opcode = GPCMD_REPORT_KEY;
        !          1754:                cmd.bytes[9] = 0x3f | (a->lsa.agid << 6);
        !          1755:                error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 16,
        !          1756:                    CDRETRIES, 30000, NULL, 0);
        !          1757:                if (error)
        !          1758:                        return (error);
        !          1759:                return (0);
        !          1760:
        !          1761:        case DVD_LU_SEND_RPC_STATE:
        !          1762:                cmd.opcode = GPCMD_REPORT_KEY;
        !          1763:                cmd.bytes[8] = 8;
        !          1764:                cmd.bytes[9] = 8 | (0 << 6);
        !          1765:                error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8,
        !          1766:                    CDRETRIES, 30000, NULL, SCSI_DATA_IN);
        !          1767:                if (error)
        !          1768:                        return (error);
        !          1769:                a->lrpcs.type = (buf[4] >> 6) & 3;
        !          1770:                a->lrpcs.vra = (buf[4] >> 3) & 7;
        !          1771:                a->lrpcs.ucca = (buf[4]) & 7;
        !          1772:                a->lrpcs.region_mask = buf[5];
        !          1773:                a->lrpcs.rpc_scheme = buf[6];
        !          1774:                return (0);
        !          1775:
        !          1776:        case DVD_HOST_SEND_RPC_STATE:
        !          1777:                cmd.opcode = GPCMD_SEND_KEY;
        !          1778:                cmd.bytes[8] = 8;
        !          1779:                cmd.bytes[9] = 6 | (0 << 6);
        !          1780:                buf[1] = 6;
        !          1781:                buf[4] = a->hrpcs.pdrc;
        !          1782:                error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8,
        !          1783:                    CDRETRIES, 30000, NULL, SCSI_DATA_OUT);
        !          1784:                if (error)
        !          1785:                        return (error);
        !          1786:                return (0);
        !          1787:
        !          1788:        default:
        !          1789:                return (ENOTTY);
        !          1790:        }
        !          1791: }
        !          1792:
        !          1793: int
        !          1794: dvd_read_physical(cd, s)
        !          1795:        struct cd_softc *cd;
        !          1796:        union dvd_struct *s;
        !          1797: {
        !          1798:        struct scsi_generic cmd;
        !          1799:        u_int8_t buf[4 + 4 * 20], *bufp;
        !          1800:        int error;
        !          1801:        struct dvd_layer *layer;
        !          1802:        int i;
        !          1803:
        !          1804:        bzero(cmd.bytes, sizeof(cmd.bytes));
        !          1805:        bzero(buf, sizeof(buf));
        !          1806:        cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
        !          1807:        cmd.bytes[6] = s->type;
        !          1808:        _lto2b(sizeof(buf), &cmd.bytes[7]);
        !          1809:
        !          1810:        cmd.bytes[5] = s->physical.layer_num;
        !          1811:        error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, sizeof(buf),
        !          1812:            CDRETRIES, 30000, NULL, SCSI_DATA_IN);
        !          1813:        if (error)
        !          1814:                return (error);
        !          1815:        for (i = 0, bufp = &buf[4], layer = &s->physical.layer[0]; i < 4;
        !          1816:            i++, bufp += 20, layer++) {
        !          1817:                bzero(layer, sizeof(*layer));
        !          1818:                layer->book_version = bufp[0] & 0xf;
        !          1819:                layer->book_type = bufp[0] >> 4;
        !          1820:                layer->min_rate = bufp[1] & 0xf;
        !          1821:                layer->disc_size = bufp[1] >> 4;
        !          1822:                layer->layer_type = bufp[2] & 0xf;
        !          1823:                layer->track_path = (bufp[2] >> 4) & 1;
        !          1824:                layer->nlayers = (bufp[2] >> 5) & 3;
        !          1825:                layer->track_density = bufp[3] & 0xf;
        !          1826:                layer->linear_density = bufp[3] >> 4;
        !          1827:                layer->start_sector = _4btol(&bufp[4]);
        !          1828:                layer->end_sector = _4btol(&bufp[8]);
        !          1829:                layer->end_sector_l0 = _4btol(&bufp[12]);
        !          1830:                layer->bca = bufp[16] >> 7;
        !          1831:        }
        !          1832:        return (0);
        !          1833: }
        !          1834:
        !          1835: int
        !          1836: dvd_read_copyright(cd, s)
        !          1837:        struct cd_softc *cd;
        !          1838:        union dvd_struct *s;
        !          1839: {
        !          1840:        struct scsi_generic cmd;
        !          1841:        u_int8_t buf[8];
        !          1842:        int error;
        !          1843:
        !          1844:        bzero(cmd.bytes, sizeof(cmd.bytes));
        !          1845:        bzero(buf, sizeof(buf));
        !          1846:        cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
        !          1847:        cmd.bytes[6] = s->type;
        !          1848:        _lto2b(sizeof(buf), &cmd.bytes[7]);
        !          1849:
        !          1850:        cmd.bytes[5] = s->copyright.layer_num;
        !          1851:        error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, sizeof(buf),
        !          1852:            CDRETRIES, 30000, NULL, SCSI_DATA_IN);
        !          1853:        if (error)
        !          1854:                return (error);
        !          1855:        s->copyright.cpst = buf[4];
        !          1856:        s->copyright.rmi = buf[5];
        !          1857:        return (0);
        !          1858: }
        !          1859:
        !          1860: int
        !          1861: dvd_read_disckey(cd, s)
        !          1862:        struct cd_softc *cd;
        !          1863:        union dvd_struct *s;
        !          1864: {
        !          1865:        struct scsi_read_dvd_structure cmd;
        !          1866:        struct scsi_read_dvd_structure_data *buf;
        !          1867:        int error;
        !          1868:
        !          1869:        buf = malloc(sizeof(*buf), M_TEMP, M_WAITOK);
        !          1870:        if (buf == NULL)
        !          1871:                return (ENOMEM);
        !          1872:        bzero(buf, sizeof(*buf));
        !          1873:
        !          1874:        bzero(&cmd, sizeof(cmd));
        !          1875:        cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
        !          1876:        cmd.format = s->type;
        !          1877:        cmd.agid = s->disckey.agid << 6;
        !          1878:        _lto2b(sizeof(*buf), cmd.length);
        !          1879:
        !          1880:        error = scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&cmd,
        !          1881:            sizeof(cmd), (u_char *)buf, sizeof(*buf), CDRETRIES, 30000, NULL,
        !          1882:            SCSI_DATA_IN);
        !          1883:        if (error == 0)
        !          1884:                bcopy(buf->data, s->disckey.value, sizeof(s->disckey.value));
        !          1885:
        !          1886:        free(buf, M_TEMP);
        !          1887:        return (error);
        !          1888: }
        !          1889:
        !          1890: int
        !          1891: dvd_read_bca(cd, s)
        !          1892:        struct cd_softc *cd;
        !          1893:        union dvd_struct *s;
        !          1894: {
        !          1895:        struct scsi_generic cmd;
        !          1896:        u_int8_t buf[4 + 188];
        !          1897:        int error;
        !          1898:
        !          1899:        bzero(cmd.bytes, sizeof(cmd.bytes));
        !          1900:        bzero(buf, sizeof(buf));
        !          1901:        cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
        !          1902:        cmd.bytes[6] = s->type;
        !          1903:        _lto2b(sizeof(buf), &cmd.bytes[7]);
        !          1904:
        !          1905:        error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, sizeof(buf),
        !          1906:            CDRETRIES, 30000, NULL, SCSI_DATA_IN);
        !          1907:        if (error)
        !          1908:                return (error);
        !          1909:        s->bca.len = _2btol(&buf[0]);
        !          1910:        if (s->bca.len < 12 || s->bca.len > 188)
        !          1911:                return (EIO);
        !          1912:        bcopy(&buf[4], s->bca.value, s->bca.len);
        !          1913:        return (0);
        !          1914: }
        !          1915:
        !          1916: int
        !          1917: dvd_read_manufact(cd, s)
        !          1918:        struct cd_softc *cd;
        !          1919:        union dvd_struct *s;
        !          1920: {
        !          1921:        struct scsi_read_dvd_structure cmd;
        !          1922:        struct scsi_read_dvd_structure_data *buf;
        !          1923:        int error;
        !          1924:
        !          1925:        buf = malloc(sizeof(*buf), M_TEMP, M_WAITOK);
        !          1926:        if (buf == NULL)
        !          1927:                return (ENOMEM);
        !          1928:        bzero(buf, sizeof(*buf));
        !          1929:
        !          1930:        bzero(&cmd, sizeof(cmd));
        !          1931:        cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
        !          1932:        cmd.format = s->type;
        !          1933:        _lto2b(sizeof(*buf), cmd.length);
        !          1934:
        !          1935:        error = scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&cmd,
        !          1936:            sizeof(cmd), (u_char *)buf, sizeof(*buf), CDRETRIES, 30000, NULL,
        !          1937:            SCSI_DATA_IN);
        !          1938:        if (error == 0) {
        !          1939:                s->manufact.len = _2btol(buf->len);
        !          1940:                if (s->manufact.len >= 0 && s->manufact.len <= 2048)
        !          1941:                        bcopy(buf->data, s->manufact.value, s->manufact.len);
        !          1942:                else
        !          1943:                        error = EIO;
        !          1944:        }
        !          1945:
        !          1946:        free(buf, M_TEMP);
        !          1947:        return (error);
        !          1948: }
        !          1949:
        !          1950: int
        !          1951: dvd_read_struct(cd, s)
        !          1952:        struct cd_softc *cd;
        !          1953:        union dvd_struct *s;
        !          1954: {
        !          1955:
        !          1956:        switch (s->type) {
        !          1957:        case DVD_STRUCT_PHYSICAL:
        !          1958:                return (dvd_read_physical(cd, s));
        !          1959:        case DVD_STRUCT_COPYRIGHT:
        !          1960:                return (dvd_read_copyright(cd, s));
        !          1961:        case DVD_STRUCT_DISCKEY:
        !          1962:                return (dvd_read_disckey(cd, s));
        !          1963:        case DVD_STRUCT_BCA:
        !          1964:                return (dvd_read_bca(cd, s));
        !          1965:        case DVD_STRUCT_MANUFACT:
        !          1966:                return (dvd_read_manufact(cd, s));
        !          1967:        default:
        !          1968:                return (EINVAL);
        !          1969:        }
        !          1970: }
        !          1971:
        !          1972: void
        !          1973: cd_powerhook(int why, void *arg)
        !          1974: {
        !          1975:        struct cd_softc *cd = arg;
        !          1976:
        !          1977:        /*
        !          1978:         * When resuming, hardware may have forgotten we locked it. So if
        !          1979:         * there are any open partitions, lock the CD.
        !          1980:         */
        !          1981:        if (why == PWR_RESUME && cd->sc_dk.dk_openmask != 0)
        !          1982:                scsi_prevent(cd->sc_link, PR_PREVENT,
        !          1983:                    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE);
        !          1984: }
        !          1985:
        !          1986: int
        !          1987: cd_interpret_sense(struct scsi_xfer *xs)
        !          1988: {
        !          1989:        struct scsi_sense_data *sense = &xs->sense;
        !          1990:        struct scsi_link *sc_link = xs->sc_link;
        !          1991:        u_int8_t skey = sense->flags & SSD_KEY;
        !          1992:        u_int8_t serr = sense->error_code & SSD_ERRCODE;
        !          1993:
        !          1994:        if (((sc_link->flags & SDEV_OPEN) == 0) ||
        !          1995:            (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED))
        !          1996:                return (EJUSTRETURN); /* let the generic code handle it */
        !          1997:
        !          1998:        /*
        !          1999:         * We do custom processing in cd for the unit becoming ready
        !          2000:         * case.  We do not allow xs->retries to be decremented on the
        !          2001:         * "Unit Becoming Ready" case. This is because CD drives
        !          2002:         * report "Unit Becoming Ready" when loading media and can
        !          2003:         * take a long time.  Rather than having a massive timeout for
        !          2004:         * all operations (which would cause other problems), we allow
        !          2005:         * operations to wait (but be interruptable with Ctrl-C)
        !          2006:         * forever as long as the drive is reporting that it is
        !          2007:         * becoming ready.  All other cases of not being ready are
        !          2008:         * handled by the default handler.
        !          2009:         */
        !          2010:        switch(skey) {
        !          2011:        case SKEY_NOT_READY:
        !          2012:                if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0)
        !          2013:                        return (0);
        !          2014:                if (ASC_ASCQ(sense) == SENSE_NOT_READY_BECOMING_READY) {
        !          2015:                        SC_DEBUG(sc_link, SDEV_DB1, ("not ready: busy (%#x)\n",
        !          2016:                            sense->add_sense_code_qual));
        !          2017:                        /* don't count this as a retry */
        !          2018:                        xs->retries++;
        !          2019:                        return (scsi_delay(xs, 1));
        !          2020:                }
        !          2021:                break;
        !          2022:        /* XXX more to come here for a few other cases */
        !          2023:        default:
        !          2024:                break;
        !          2025:        }
        !          2026:        return (EJUSTRETURN); /* use generic handler in scsi_base */
        !          2027: }
        !          2028:
        !          2029: /*
        !          2030:  * Remove unprocessed buffers from queue.
        !          2031:  */
        !          2032: void
        !          2033: cd_kill_buffers(struct cd_softc *cd)
        !          2034: {
        !          2035:        struct buf *dp, *bp;
        !          2036:        int s;
        !          2037:
        !          2038:        s = splbio();
        !          2039:        for (dp = &cd->buf_queue; (bp = dp->b_actf) != NULL; ) {
        !          2040:                dp->b_actf = bp->b_actf;
        !          2041:
        !          2042:                bp->b_error = ENXIO;
        !          2043:                bp->b_flags |= B_ERROR;
        !          2044:                biodone(bp);
        !          2045:        }
        !          2046:        splx(s);
        !          2047: }

CVSweb