The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/scsipi/cd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: cd.c,v 1.220.2.2 2006/04/27 20:37:42 tron Exp $        */
    2 
    3 /*-
    4  * Copyright (c) 1998, 2001, 2003, 2004 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Charles M. Hannum.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Originally written by Julian Elischer (julian@tfs.com)
   41  * for TRW Financial Systems for use under the MACH(2.5) operating system.
   42  *
   43  * TRW Financial Systems, in accordance with their agreement with Carnegie
   44  * Mellon University, makes this software available to CMU to distribute
   45  * or use in any manner that they see fit as long as this message is kept with
   46  * the software. For this reason TFS also grants any other persons or
   47  * organisations permission to use or modify this software.
   48  *
   49  * TFS supplies this software to be publicly redistributed
   50  * on the understanding that TFS is not responsible for the correct
   51  * functioning of this software in any circumstances.
   52  *
   53  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
   54  */
   55 
   56 #include <sys/cdefs.h>
   57 __KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.220.2.2 2006/04/27 20:37:42 tron Exp $");
   58 
   59 #include "rnd.h"
   60 
   61 #include <sys/param.h>
   62 #include <sys/systm.h>
   63 #include <sys/kernel.h>
   64 #include <sys/file.h>
   65 #include <sys/stat.h>
   66 #include <sys/ioctl.h>
   67 #include <sys/buf.h>
   68 #include <sys/bufq.h>
   69 #include <sys/uio.h>
   70 #include <sys/malloc.h>
   71 #include <sys/errno.h>
   72 #include <sys/device.h>
   73 #include <sys/disklabel.h>
   74 #include <sys/disk.h>
   75 #include <sys/cdio.h>
   76 #include <sys/dvdio.h>
   77 #include <sys/scsiio.h>
   78 #include <sys/proc.h>
   79 #include <sys/conf.h>
   80 #include <sys/vnode.h>
   81 #if NRND > 0
   82 #include <sys/rnd.h>
   83 #endif
   84 
   85 #include <dev/scsipi/scsi_spc.h>
   86 #include <dev/scsipi/scsipi_all.h>
   87 #include <dev/scsipi/scsipi_cd.h>
   88 #include <dev/scsipi/scsipi_disk.h>     /* rw_big and start_stop come */
   89 #include <dev/scsipi/scsi_all.h>
   90                                         /* from there */
   91 #include <dev/scsipi/scsi_disk.h>       /* rw comes from there */
   92 #include <dev/scsipi/scsipiconf.h>
   93 #include <dev/scsipi/scsipi_base.h>
   94 #include <dev/scsipi/cdvar.h>
   95 
   96 #define CDUNIT(z)                       DISKUNIT(z)
   97 #define CDPART(z)                       DISKPART(z)
   98 #define CDMINOR(unit, part)             DISKMINOR(unit, part)
   99 #define MAKECDDEV(maj, unit, part)      MAKEDISKDEV(maj, unit, part)
  100 
  101 #define MAXTRACK        99
  102 #define CD_BLOCK_OFFSET 150
  103 #define CD_FRAMES       75
  104 #define CD_SECS         60
  105 
  106 struct cd_toc {
  107         struct ioc_toc_header header;
  108         struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */
  109                                                  /* leadout */
  110 };
  111 
  112 static void     cdstart(struct scsipi_periph *);
  113 static void     cdrestart(void *);
  114 static void     cdminphys(struct buf *);
  115 static void     cdgetdefaultlabel(struct cd_softc *, struct disklabel *);
  116 static void     cdgetdisklabel(struct cd_softc *);
  117 static void     cddone(struct scsipi_xfer *, int);
  118 static void     cdbounce(struct buf *);
  119 static int      cd_interpret_sense(struct scsipi_xfer *);
  120 static u_long   cd_size(struct cd_softc *, int);
  121 static int      cd_play(struct cd_softc *, int, int);
  122 static int      cd_play_tracks(struct cd_softc *, int, int, int, int);
  123 static int      cd_play_msf(struct cd_softc *, int, int, int, int, int, int);
  124 static int      cd_pause(struct cd_softc *, int);
  125 static int      cd_reset(struct cd_softc *);
  126 static int      cd_read_subchannel(struct cd_softc *, int, int, int,
  127                     struct cd_sub_channel_info *, int, int);
  128 static int      cd_read_toc_f0(struct cd_softc *, int, int, void *, int, int, int);
  129 static int      cd_get_parms(struct cd_softc *, int);
  130 static int      cd_load_toc(struct cd_softc *, struct cd_toc *, int);
  131 static int      cdreadmsaddr(struct cd_softc *, int *);
  132 
  133 static int      dvd_auth(struct cd_softc *, dvd_authinfo *);
  134 static int      dvd_read_physical(struct cd_softc *, dvd_struct *);
  135 static int      dvd_read_copyright(struct cd_softc *, dvd_struct *);
  136 static int      dvd_read_disckey(struct cd_softc *, dvd_struct *);
  137 static int      dvd_read_bca(struct cd_softc *, dvd_struct *);
  138 static int      dvd_read_manufact(struct cd_softc *, dvd_struct *);
  139 static int      dvd_read_struct(struct cd_softc *, dvd_struct *);
  140 
  141 static int      cd_mode_sense(struct cd_softc *, u_int8_t, void *, size_t, int,
  142                     int, int *);
  143 static int      cd_mode_select(struct cd_softc *, u_int8_t, void *, size_t,
  144                     int, int);
  145 static int      cd_setchan(struct cd_softc *, int, int, int, int, int);
  146 static int      cd_getvol(struct cd_softc *, struct ioc_vol *, int);
  147 static int      cd_setvol(struct cd_softc *, const struct ioc_vol *, int);
  148 static int      cd_set_pa_immed(struct cd_softc *, int);
  149 static int      cd_load_unload(struct cd_softc *, struct ioc_load_unload *);
  150 static int      cd_setblksize(struct cd_softc *);
  151 
  152 static int      cdmatch(struct device *, struct cfdata *, void *);
  153 static void     cdattach(struct device *, struct device *, void *);
  154 static int      cdactivate(struct device *, enum devact);
  155 static int      cddetach(struct device *, int);
  156 
  157 CFATTACH_DECL(cd, sizeof(struct cd_softc), cdmatch, cdattach, cddetach,
  158     cdactivate);
  159 
  160 extern struct cfdriver cd_cd;
  161 
  162 static const struct scsipi_inquiry_pattern cd_patterns[] = {
  163         {T_CDROM, T_REMOV,
  164          "",         "",                 ""},
  165         {T_WORM, T_REMOV,
  166          "",         "",                 ""},
  167 #if 0
  168         {T_CDROM, T_REMOV, /* more luns */
  169          "PIONEER ", "CD-ROM DRM-600  ", ""},
  170 #endif
  171         {T_DIRECT, T_REMOV,
  172          "NEC                 CD-ROM DRIVE:260", "", ""},
  173 };
  174 
  175 static dev_type_open(cdopen);
  176 static dev_type_close(cdclose);
  177 static dev_type_read(cdread);
  178 static dev_type_write(cdwrite);
  179 static dev_type_ioctl(cdioctl);
  180 static dev_type_strategy(cdstrategy);
  181 static dev_type_dump(cddump);
  182 static dev_type_size(cdsize);
  183 
  184 const struct bdevsw cd_bdevsw = {
  185         cdopen, cdclose, cdstrategy, cdioctl, cddump, cdsize, D_DISK
  186 };
  187 
  188 const struct cdevsw cd_cdevsw = {
  189         cdopen, cdclose, cdread, cdwrite, cdioctl,
  190         nostop, notty, nopoll, nommap, nokqfilter, D_DISK
  191 };
  192 
  193 static struct dkdriver cddkdriver = { cdstrategy };
  194 
  195 static const struct scsipi_periphsw cd_switch = {
  196         cd_interpret_sense,     /* use our error handler first */
  197         cdstart,                /* we have a queue, which is started by this */
  198         NULL,                   /* we do not have an async handler */
  199         cddone,                 /* deal with stats at interrupt time */
  200 };
  201 
  202 /*
  203  * The routine called by the low level scsi routine when it discovers
  204  * A device suitable for this driver
  205  */
  206 static int
  207 cdmatch(struct device *parent, struct cfdata *match, void *aux)
  208 {
  209         struct scsipibus_attach_args *sa = aux;
  210         int priority;
  211 
  212         (void)scsipi_inqmatch(&sa->sa_inqbuf,
  213             (caddr_t)cd_patterns, sizeof(cd_patterns) / sizeof(cd_patterns[0]),
  214             sizeof(cd_patterns[0]), &priority);
  215 
  216         return (priority);
  217 }
  218 
  219 static void
  220 cdattach(struct device *parent, struct device *self, void *aux)
  221 {
  222         struct cd_softc *cd = (void *)self;
  223         struct scsipibus_attach_args *sa = aux;
  224         struct scsipi_periph *periph = sa->sa_periph;
  225 
  226         SC_DEBUG(periph, SCSIPI_DB2, ("cdattach: "));
  227 
  228         lockinit(&cd->sc_lock, PRIBIO | PCATCH, "cdlock", 0, 0);
  229 
  230         if (scsipi_periph_bustype(sa->sa_periph) == SCSIPI_BUSTYPE_SCSI &&
  231             periph->periph_version == 0)
  232                 cd->flags |= CDF_ANCIENT;
  233 
  234         bufq_alloc(&cd->buf_queue, BUFQ_DISKSORT|BUFQ_SORT_RAWBLOCK);
  235 
  236         callout_init(&cd->sc_callout);
  237 
  238         /*
  239          * Store information needed to contact our base driver
  240          */
  241         cd->sc_periph = periph;
  242 
  243         periph->periph_dev = &cd->sc_dev;
  244         periph->periph_switch = &cd_switch;
  245 
  246         /*
  247          * Increase our openings to the maximum-per-periph
  248          * supported by the adapter.  This will either be
  249          * clamped down or grown by the adapter if necessary.
  250          */
  251         periph->periph_openings =
  252             SCSIPI_CHAN_MAX_PERIPH(periph->periph_channel);
  253         periph->periph_flags |= PERIPH_GROW_OPENINGS;
  254 
  255         /*
  256          * Initialize and attach the disk structure.
  257          */
  258         cd->sc_dk.dk_driver = &cddkdriver;
  259         cd->sc_dk.dk_name = cd->sc_dev.dv_xname;
  260         disk_attach(&cd->sc_dk);
  261 
  262         printf("\n");
  263 
  264 #if NRND > 0
  265         rnd_attach_source(&cd->rnd_source, cd->sc_dev.dv_xname,
  266                           RND_TYPE_DISK, 0);
  267 #endif
  268 }
  269 
  270 static int
  271 cdactivate(struct device *self, enum devact act)
  272 {
  273         int rv = 0;
  274 
  275         switch (act) {
  276         case DVACT_ACTIVATE:
  277                 rv = EOPNOTSUPP;
  278                 break;
  279 
  280         case DVACT_DEACTIVATE:
  281                 /*
  282                  * Nothing to do; we key off the device's DVF_ACTIVE.
  283                  */
  284                 break;
  285         }
  286         return (rv);
  287 }
  288 
  289 static int
  290 cddetach(struct device *self, int flags)
  291 {
  292         struct cd_softc *cd = (struct cd_softc *) self;
  293         int s, bmaj, cmaj, i, mn;
  294 
  295         /* locate the major number */
  296         bmaj = bdevsw_lookup_major(&cd_bdevsw);
  297         cmaj = cdevsw_lookup_major(&cd_cdevsw);
  298 
  299         /* Nuke the vnodes for any open instances */
  300         for (i = 0; i < MAXPARTITIONS; i++) {
  301                 mn = CDMINOR(self->dv_unit, i);
  302                 vdevgone(bmaj, mn, mn, VBLK);
  303                 vdevgone(cmaj, mn, mn, VCHR);
  304         }
  305 
  306         /* kill any pending restart */
  307         callout_stop(&cd->sc_callout);
  308 
  309         s = splbio();
  310 
  311         /* Kill off any queued buffers. */
  312         bufq_drain(&cd->buf_queue);
  313 
  314         bufq_free(&cd->buf_queue);
  315 
  316         /* Kill off any pending commands. */
  317         scsipi_kill_pending(cd->sc_periph);
  318 
  319         splx(s);
  320 
  321         lockmgr(&cd->sc_lock, LK_DRAIN, 0);
  322 
  323         /* Detach from the disk list. */
  324         disk_detach(&cd->sc_dk);
  325 
  326 #if 0
  327         /* Get rid of the shutdown hook. */
  328         if (cd->sc_sdhook != NULL)
  329                 shutdownhook_disestablish(cd->sc_sdhook);
  330 #endif
  331 
  332 #if NRND > 0
  333         /* Unhook the entropy source. */
  334         rnd_detach_source(&cd->rnd_source);
  335 #endif
  336 
  337         return (0);
  338 }
  339 
  340 /*
  341  * open the device. Make sure the partition info is a up-to-date as can be.
  342  */
  343 static int
  344 cdopen(dev_t dev, int flag, int fmt, struct proc *p)
  345 {
  346         struct cd_softc *cd;
  347         struct scsipi_periph *periph;
  348         struct scsipi_adapter *adapt;
  349         int unit, part;
  350         int error;
  351         int rawpart;
  352 
  353         unit = CDUNIT(dev);
  354         if (unit >= cd_cd.cd_ndevs)
  355                 return (ENXIO);
  356         cd = cd_cd.cd_devs[unit];
  357         if (cd == NULL)
  358                 return (ENXIO);
  359 
  360         periph = cd->sc_periph;
  361         adapt = periph->periph_channel->chan_adapter;
  362         part = CDPART(dev);
  363 
  364         SC_DEBUG(periph, SCSIPI_DB1,
  365             ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
  366             cd_cd.cd_ndevs, CDPART(dev)));
  367 
  368         /*
  369          * If this is the first open of this device, add a reference
  370          * to the adapter.
  371          */
  372         if (cd->sc_dk.dk_openmask == 0 &&
  373             (error = scsipi_adapter_addref(adapt)) != 0)
  374                 return (error);
  375 
  376         if ((error = lockmgr(&cd->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
  377                 goto bad4;
  378 
  379         rawpart = (part == RAW_PART && fmt == S_IFCHR);
  380         if ((periph->periph_flags & PERIPH_OPEN) != 0) {
  381                 /*
  382                  * If any partition is open, but the disk has been invalidated,
  383                  * disallow further opens.
  384                  */
  385                 if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0 &&
  386                         !rawpart) {
  387                         error = EIO;
  388                         goto bad3;
  389                 }
  390         } else {
  391                 int silent;
  392 
  393                 if (rawpart)
  394                         silent = XS_CTL_SILENT;
  395                 else
  396                         silent = 0;
  397 
  398                 /* Check that it is still responding and ok. */
  399                 error = scsipi_test_unit_ready(periph,
  400                     XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE |
  401                     silent);
  402 
  403                 /*
  404                  * Start the pack spinning if necessary. Always allow the
  405                  * raw parition to be opened, for raw IOCTLs. Data transfers
  406                  * will check for SDEV_MEDIA_LOADED.
  407                  */
  408                 if (error == EIO) {
  409                         int error2;
  410 
  411                         error2 = scsipi_start(periph, SSS_START, silent);
  412                         switch (error2) {
  413                         case 0:
  414                                 error = 0;
  415                                 break;
  416                         case EIO:
  417                         case EINVAL:
  418                                 break;
  419                         default:
  420                                 error = error2;
  421                                 break;
  422                         }
  423                 }
  424                 if (error) {
  425                         if (rawpart)
  426                                 goto out;
  427                         goto bad3;
  428                 }
  429 
  430                 periph->periph_flags |= PERIPH_OPEN;
  431 
  432                 /* Lock the pack in. */
  433                 error = scsipi_prevent(periph, SPAMR_PREVENT_DT,
  434                     XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE);
  435                 SC_DEBUG(periph, SCSIPI_DB1,
  436                     ("cdopen: scsipi_prevent, error=%d\n", error));
  437                 if (error) {
  438                         if (rawpart)
  439                                 goto out;
  440                         goto bad;
  441                 }
  442 
  443                 if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
  444                         /* Load the physical device parameters. */
  445                         if (cd_get_parms(cd, 0) != 0) {
  446                                 if (rawpart)
  447                                         goto out;
  448                                 error = ENXIO;
  449                                 goto bad;
  450                         }
  451                         periph->periph_flags |= PERIPH_MEDIA_LOADED;
  452                         SC_DEBUG(periph, SCSIPI_DB3, ("Params loaded "));
  453 
  454                         /* Fabricate a disk label. */
  455                         cdgetdisklabel(cd);
  456                         SC_DEBUG(periph, SCSIPI_DB3, ("Disklabel fabricated "));
  457                 }
  458         }
  459 
  460         /* Check that the partition exists. */
  461         if (part != RAW_PART &&
  462             (part >= cd->sc_dk.dk_label->d_npartitions ||
  463             cd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
  464                 error = ENXIO;
  465                 goto bad;
  466         }
  467 
  468 out:    /* Insure only one open at a time. */
  469         switch (fmt) {
  470         case S_IFCHR:
  471                 cd->sc_dk.dk_copenmask |= (1 << part);
  472                 break;
  473         case S_IFBLK:
  474                 cd->sc_dk.dk_bopenmask |= (1 << part);
  475                 break;
  476         }
  477         cd->sc_dk.dk_openmask =
  478             cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
  479 
  480         SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
  481         lockmgr(&cd->sc_lock, LK_RELEASE, NULL);
  482         return (0);
  483 
  484         periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
  485 
  486 bad:
  487         if (cd->sc_dk.dk_openmask == 0) {
  488                 scsipi_prevent(periph, SPAMR_ALLOW,
  489                     XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE);
  490                 periph->periph_flags &= ~PERIPH_OPEN;
  491         }
  492 
  493 bad3:
  494         lockmgr(&cd->sc_lock, LK_RELEASE, NULL);
  495 bad4:
  496         if (cd->sc_dk.dk_openmask == 0)
  497                 scsipi_adapter_delref(adapt);
  498         return (error);
  499 }
  500 
  501 /*
  502  * close the device.. only called if we are the LAST
  503  * occurence of an open device
  504  */
  505 static int
  506 cdclose(dev_t dev, int flag, int fmt, struct proc *p)
  507 {
  508         struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(dev)];
  509         struct scsipi_periph *periph = cd->sc_periph;
  510         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
  511         int part = CDPART(dev);
  512         int error;
  513 
  514         if ((error = lockmgr(&cd->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
  515                 return (error);
  516 
  517         switch (fmt) {
  518         case S_IFCHR:
  519                 cd->sc_dk.dk_copenmask &= ~(1 << part);
  520                 break;
  521         case S_IFBLK:
  522                 cd->sc_dk.dk_bopenmask &= ~(1 << part);
  523                 break;
  524         }
  525         cd->sc_dk.dk_openmask =
  526             cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
  527 
  528         if (cd->sc_dk.dk_openmask == 0) {
  529                 scsipi_wait_drain(periph);
  530 
  531                 scsipi_prevent(periph, SPAMR_ALLOW,
  532                     XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE |
  533                     XS_CTL_IGNORE_NOT_READY);
  534                 periph->periph_flags &= ~PERIPH_OPEN;
  535 
  536                 scsipi_wait_drain(periph);
  537 
  538                 scsipi_adapter_delref(adapt);
  539         }
  540 
  541         lockmgr(&cd->sc_lock, LK_RELEASE, NULL);
  542         return (0);
  543 }
  544 
  545 /*
  546  * Actually translate the requested transfer into one the physical driver can
  547  * understand.  The transfer is described by a buf and will include only one
  548  * physical transfer.
  549  */
  550 static void
  551 cdstrategy(struct buf *bp)
  552 {
  553         struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(bp->b_dev)];
  554         struct disklabel *lp;
  555         struct scsipi_periph *periph = cd->sc_periph;
  556         daddr_t blkno;
  557         int s;
  558 
  559         SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdstrategy "));
  560         SC_DEBUG(cd->sc_periph, SCSIPI_DB1,
  561             ("%d bytes @ blk %" PRId64 "\n", bp->b_bcount, bp->b_blkno));
  562         /*
  563          * If the device has been made invalid, error out
  564          * maybe the media changed
  565          */
  566         if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
  567                 if (periph->periph_flags & PERIPH_OPEN)
  568                         bp->b_error = EIO;
  569                 else
  570                         bp->b_error = ENODEV;
  571                 goto bad;
  572         }
  573 
  574         lp = cd->sc_dk.dk_label;
  575 
  576         /*
  577          * The transfer must be a whole number of blocks, offset must not
  578          * be negative.
  579          */
  580         if ((bp->b_bcount % lp->d_secsize) != 0 ||
  581             bp->b_blkno < 0 ) {
  582                 bp->b_error = EINVAL;
  583                 goto bad;
  584         }
  585         /*
  586          * If it's a null transfer, return immediately
  587          */
  588         if (bp->b_bcount == 0)
  589                 goto done;
  590 
  591         /*
  592          * Do bounds checking, adjust transfer. if error, process.
  593          * If end of partition, just return.
  594          */
  595         if (CDPART(bp->b_dev) == RAW_PART) {
  596                 if (bounds_check_with_mediasize(bp, DEV_BSIZE,
  597                     cd->params.disksize512) <= 0)
  598                         goto done;
  599         } else {
  600                 if (bounds_check_with_label(&cd->sc_dk, bp,
  601                     (cd->flags & (CDF_WLABEL|CDF_LABELLING)) != 0) <= 0)
  602                         goto done;
  603         }
  604 
  605         /*
  606          * Now convert the block number to absolute and put it in
  607          * terms of the device's logical block size.
  608          */
  609         blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
  610         if (CDPART(bp->b_dev) != RAW_PART)
  611                 blkno += lp->d_partitions[CDPART(bp->b_dev)].p_offset;
  612 
  613         bp->b_rawblkno = blkno;
  614 
  615         /*
  616          * If the disklabel sector size does not match the device
  617          * sector size we may need to do some extra work.
  618          */
  619         if (lp->d_secsize != cd->params.blksize) {
  620 
  621                 /*
  622                  * If the xfer is not a multiple of the device block size
  623                  * or it is not block aligned, we need to bounce it.
  624                  */
  625                 if ((bp->b_bcount % cd->params.blksize) != 0 ||
  626                         ((blkno * lp->d_secsize) % cd->params.blksize) != 0) {
  627                         struct buf *nbp;
  628                         void *bounce = NULL;
  629                         long count;
  630 
  631                         if ((bp->b_flags & B_READ) == 0) {
  632 
  633                                 /* XXXX We don't support bouncing writes. */
  634                                 bp->b_error = EACCES;
  635                                 goto bad;
  636                         }
  637                         count = ((blkno * lp->d_secsize) % cd->params.blksize);
  638                         /* XXX Store starting offset in bp->b_rawblkno */
  639                         bp->b_rawblkno = count;
  640 
  641                         count += bp->b_bcount;
  642                         count = roundup(count, cd->params.blksize);
  643 
  644                         blkno = ((blkno * lp->d_secsize) / cd->params.blksize);
  645                         s = splbio();
  646                         nbp = pool_get(&bufpool, PR_NOWAIT);
  647                         splx(s);
  648                         if (!nbp) {
  649                                 /* No memory -- fail the iop. */
  650                                 bp->b_error = ENOMEM;
  651                                 goto bad;
  652                         }
  653                         bounce = malloc(count, M_DEVBUF, M_NOWAIT);
  654                         if (!bounce) {
  655                                 /* No memory -- fail the iop. */
  656                                 s = splbio();
  657                                 pool_put(&bufpool, nbp);
  658                                 splx(s);
  659                                 bp->b_error = ENOMEM;
  660                                 goto bad;
  661                         }
  662 
  663                         /* Set up the IOP to the bounce buffer. */
  664                         BUF_INIT(nbp);
  665                         nbp->b_error = 0;
  666                         nbp->b_proc = bp->b_proc;
  667                         nbp->b_vp = NULLVP;
  668 
  669                         nbp->b_bcount = count;
  670                         nbp->b_bufsize = count;
  671                         nbp->b_data = bounce;
  672 
  673                         nbp->b_rawblkno = blkno;
  674 
  675                         /* We need to do a read-modify-write operation */
  676                         nbp->b_flags = bp->b_flags | B_READ | B_CALL;
  677                         nbp->b_iodone = cdbounce;
  678 
  679                         /* Put ptr to orig buf in b_private and use new buf */
  680                         nbp->b_private = bp;
  681 
  682                         BIO_COPYPRIO(nbp, bp);
  683 
  684                         bp = nbp;
  685 
  686                 } else {
  687                         /* Xfer is aligned -- just adjust the start block */
  688                         bp->b_rawblkno = (blkno * lp->d_secsize) /
  689                                 cd->params.blksize;
  690                 }
  691         }
  692         s = splbio();
  693 
  694         /*
  695          * Place it in the queue of disk activities for this disk.
  696          *
  697          * XXX Only do disksort() if the current operating mode does not
  698          * XXX include tagged queueing.
  699          */
  700         BUFQ_PUT(&cd->buf_queue, bp);
  701 
  702         /*
  703          * Tell the device to get going on the transfer if it's
  704          * not doing anything, otherwise just wait for completion
  705          */
  706         cdstart(cd->sc_periph);
  707 
  708         splx(s);
  709         return;
  710 
  711 bad:
  712         bp->b_flags |= B_ERROR;
  713 done:
  714         /*
  715          * Correctly set the buf to indicate a completed xfer
  716          */
  717         bp->b_resid = bp->b_bcount;
  718         biodone(bp);
  719 }
  720 
  721 /*
  722  * cdstart looks to see if there is a buf waiting for the device
  723  * and that the device is not already busy. If both are true,
  724  * It deques the buf and creates a scsi command to perform the
  725  * transfer in the buf. The transfer request will call scsipi_done
  726  * on completion, which will in turn call this routine again
  727  * so that the next queued transfer is performed.
  728  * The bufs are queued by the strategy routine (cdstrategy)
  729  *
  730  * This routine is also called after other non-queued requests
  731  * have been made of the scsi driver, to ensure that the queue
  732  * continues to be drained.
  733  *
  734  * must be called at the correct (highish) spl level
  735  * cdstart() is called at splbio from cdstrategy, cdrestart and scsipi_done
  736  */
  737 static void
  738 cdstart(struct scsipi_periph *periph)
  739 {
  740         struct cd_softc *cd = (void *)periph->periph_dev;
  741         struct buf *bp = 0;
  742         struct scsipi_rw_10 cmd_big;
  743         struct scsi_rw_6 cmd_small;
  744         struct scsipi_generic *cmdp;
  745         struct scsipi_xfer *xs;
  746         int flags, nblks, cmdlen, error;
  747 
  748         SC_DEBUG(periph, SCSIPI_DB2, ("cdstart "));
  749         /*
  750          * Check if the device has room for another command
  751          */
  752         while (periph->periph_active < periph->periph_openings) {
  753                 /*
  754                  * there is excess capacity, but a special waits
  755                  * It'll need the adapter as soon as we clear out of the
  756                  * way and let it run (user level wait).
  757                  */
  758                 if (periph->periph_flags & PERIPH_WAITING) {
  759                         periph->periph_flags &= ~PERIPH_WAITING;
  760                         wakeup((caddr_t)periph);
  761                         return;
  762                 }
  763 
  764                 /*
  765                  * If the device has become invalid, abort all the
  766                  * reads and writes until all files have been closed and
  767                  * re-opened
  768                  */
  769                 if (__predict_false(
  770                     (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)) {
  771                         if ((bp = BUFQ_GET(&cd->buf_queue)) != NULL) {
  772                                 bp->b_error = EIO;
  773                                 bp->b_flags |= B_ERROR;
  774                                 bp->b_resid = bp->b_bcount;
  775                                 biodone(bp);
  776                                 continue;
  777                         } else {
  778                                 return;
  779                         }
  780                 }
  781 
  782                 /*
  783                  * See if there is a buf with work for us to do..
  784                  */
  785                 if ((bp = BUFQ_PEEK(&cd->buf_queue)) == NULL)
  786                         return;
  787 
  788                 /*
  789                  * We have a buf, now we should make a command.
  790                  */
  791 
  792                 nblks = howmany(bp->b_bcount, cd->params.blksize);
  793 
  794                 /*
  795                  *  Fill out the scsi command.  If the transfer will
  796                  *  fit in a "small" cdb, use it.
  797                  */
  798                 if (((bp->b_rawblkno & 0x1fffff) == bp->b_rawblkno) &&
  799                     ((nblks & 0xff) == nblks) &&
  800                     !(periph->periph_quirks & PQUIRK_ONLYBIG)) {
  801                         /*
  802                          * We can fit in a small cdb.
  803                          */
  804                         memset(&cmd_small, 0, sizeof(cmd_small));
  805                         cmd_small.opcode = (bp->b_flags & B_READ) ?
  806                             SCSI_READ_6_COMMAND : SCSI_WRITE_6_COMMAND;
  807                         _lto3b(bp->b_rawblkno, cmd_small.addr);
  808                         cmd_small.length = nblks & 0xff;
  809                         cmdlen = sizeof(cmd_small);
  810                         cmdp = (struct scsipi_generic *)&cmd_small;
  811                 } else {
  812                         /*
  813                          * Need a large cdb.
  814                          */
  815                         memset(&cmd_big, 0, sizeof(cmd_big));
  816                         cmd_big.opcode = (bp->b_flags & B_READ) ?
  817                             READ_10 : WRITE_10;
  818                         _lto4b(bp->b_rawblkno, cmd_big.addr);
  819                         _lto2b(nblks, cmd_big.length);
  820                         cmdlen = sizeof(cmd_big);
  821                         cmdp = (struct scsipi_generic *)&cmd_big;
  822                 }
  823 
  824                 /* Instrumentation. */
  825                 disk_busy(&cd->sc_dk);
  826 
  827                 /*
  828                  * Figure out what flags to use.
  829                  */
  830                 flags = XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_SIMPLE_TAG;
  831                 if (bp->b_flags & B_READ)
  832                         flags |= XS_CTL_DATA_IN;
  833                 else
  834                         flags |= XS_CTL_DATA_OUT;
  835 
  836                 /*
  837                  * Call the routine that chats with the adapter.
  838                  * Note: we cannot sleep as we may be an interrupt
  839                  */
  840                 xs = scsipi_make_xs(periph, cmdp, cmdlen,
  841                     (u_char *)bp->b_data, bp->b_bcount,
  842                     CDRETRIES, 30000, bp, flags);
  843                 if (__predict_false(xs == NULL)) {
  844                         /*
  845                          * out of memory. Keep this buffer in the queue, and
  846                          * retry later.
  847                          */
  848                         callout_reset(&cd->sc_callout, hz / 2, cdrestart,
  849                             periph);
  850                         return;
  851                 }
  852                 /*
  853                  * need to dequeue the buffer before queuing the command,
  854                  * because cdstart may be called recursively from the
  855                  * HBA driver
  856                  */
  857 #ifdef DIAGNOSTIC
  858                 if (BUFQ_GET(&cd->buf_queue) != bp)
  859                         panic("cdstart(): dequeued wrong buf");
  860 #else
  861                 BUFQ_GET(&cd->buf_queue);
  862 #endif
  863                 error = scsipi_execute_xs(xs);
  864                 /* with a scsipi_xfer preallocated, scsipi_command can't fail */
  865                 KASSERT(error == 0);
  866         }
  867 }
  868 
  869 static void
  870 cdrestart(void *v)
  871 {
  872         int s = splbio();
  873         cdstart((struct scsipi_periph *)v);
  874         splx(s);
  875 }
  876 
  877 static void
  878 cddone(struct scsipi_xfer *xs, int error)
  879 {
  880         struct cd_softc *cd = (void *)xs->xs_periph->periph_dev;
  881         struct buf *bp = xs->bp;
  882 
  883         if (bp) {
  884                 bp->b_error = error;
  885                 bp->b_resid = xs->resid;
  886                 if (error)
  887                         bp->b_flags |= B_ERROR;
  888 
  889                 disk_unbusy(&cd->sc_dk, bp->b_bcount - bp->b_resid,
  890                     (bp->b_flags & B_READ));
  891 #if NRND > 0
  892                 rnd_add_uint32(&cd->rnd_source, bp->b_rawblkno);
  893 #endif
  894 
  895                 biodone(bp);
  896         }
  897 }
  898 
  899 static void
  900 cdbounce(struct buf *bp)
  901 {
  902         struct buf *obp = (struct buf *)bp->b_private;
  903 
  904         if (bp->b_flags & B_ERROR) {
  905                 /* EEK propagate the error and free the memory */
  906                 goto done;
  907         }
  908         if (obp->b_flags & B_READ) {
  909                 /* Copy data to the final destination and free the buf. */
  910                 memcpy(obp->b_data, bp->b_data+obp->b_rawblkno,
  911                         obp->b_bcount);
  912         } else {
  913                 /*
  914                  * XXXX This is a CD-ROM -- READ ONLY -- why do we bother with
  915                  * XXXX any of this write stuff?
  916                  */
  917                 if (bp->b_flags & B_READ) {
  918                         struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(bp->b_dev)];
  919                         struct buf *nbp;
  920                         int s;
  921 
  922                         /* Read part of RMW complete. */
  923                         memcpy(bp->b_data+obp->b_rawblkno, obp->b_data,
  924                                 obp->b_bcount);
  925 
  926                         s = splbio();
  927 
  928                         /* We need to alloc a new buf. */
  929                         nbp = pool_get(&bufpool, PR_NOWAIT);
  930                         if (!nbp) {
  931                                 splx(s);
  932                                 /* No buf available. */
  933                                 bp->b_flags |= B_ERROR;
  934                                 bp->b_error = ENOMEM;
  935                                 bp->b_resid = bp->b_bcount;
  936                         }
  937 
  938                         /* Set up the IOP to the bounce buffer. */
  939                         BUF_INIT(nbp);
  940                         nbp->b_error = 0;
  941                         nbp->b_proc = bp->b_proc;
  942                         nbp->b_vp = NULLVP;
  943 
  944                         nbp->b_bcount = bp->b_bcount;
  945                         nbp->b_bufsize = bp->b_bufsize;
  946                         nbp->b_data = bp->b_data;
  947 
  948                         nbp->b_rawblkno = bp->b_rawblkno;
  949 
  950                         /* We need to do a read-modify-write operation */
  951                         nbp->b_flags = obp->b_flags | B_CALL;
  952                         nbp->b_iodone = cdbounce;
  953 
  954                         /* Put ptr to orig buf in b_private and use new buf */
  955                         nbp->b_private = obp;
  956 
  957                         /*
  958                          * Place it in the queue of disk activities for this
  959                          * disk.
  960                          *
  961                          * XXX Only do disksort() if the current operating mode
  962                          * XXX does not include tagged queueing.
  963                          */
  964                         BUFQ_PUT(&cd->buf_queue, nbp);
  965 
  966                         /*
  967                          * Tell the device to get going on the transfer if it's
  968                          * not doing anything, otherwise just wait for
  969                          * completion
  970                          */
  971                         cdstart(cd->sc_periph);
  972 
  973                         splx(s);
  974                         return;
  975 
  976                 }
  977         }
  978 done:
  979         obp->b_flags |= (bp->b_flags&(B_EINTR|B_ERROR));
  980         obp->b_error = bp->b_error;
  981         obp->b_resid = bp->b_resid;
  982         free(bp->b_data, M_DEVBUF);
  983         biodone(obp);
  984 }
  985 
  986 static int
  987 cd_interpret_sense(struct scsipi_xfer *xs)
  988 {
  989         struct scsipi_periph *periph = xs->xs_periph;
  990         struct scsi_sense_data *sense = &xs->sense.scsi_sense;
  991         int retval = EJUSTRETURN;
  992 
  993         /*
  994          * If it isn't a extended or extended/deferred error, let
  995          * the generic code handle it.
  996          */
  997         if ((sense->response_code & SSD_RCODE_VALID) == 0 ||
  998             (SSD_RCODE(sense->response_code) != SSD_RCODE_CURRENT &&
  999              SSD_RCODE(sense->response_code) != SSD_RCODE_DEFERRED))
 1000                 return (retval);
 1001 
 1002         /*
 1003          * If we got a "Unit not ready" (SKEY_NOT_READY) and "Logical Unit
 1004          * Is In The Process of Becoming Ready" (Sense code 0x04,0x01), then
 1005          * wait a bit for the drive to spin up
 1006          */
 1007 
 1008         if (SSD_SENSE_KEY(sense->flags) == SKEY_NOT_READY &&
 1009             sense->asc == 0x4 &&
 1010             sense->ascq == 0x01)        {
 1011                 /*
 1012                  * Sleep for 5 seconds to wait for the drive to spin up
 1013                  */
 1014 
 1015                 SC_DEBUG(periph, SCSIPI_DB1, ("Waiting 5 sec for CD "
 1016                                                 "spinup\n"));
 1017                 if (!callout_pending(&periph->periph_callout))
 1018                         scsipi_periph_freeze(periph, 1);
 1019                 callout_reset(&periph->periph_callout,
 1020                     5 * hz, scsipi_periph_timed_thaw, periph);
 1021                 retval = ERESTART;
 1022         }
 1023         return (retval);
 1024 }
 1025 
 1026 static void
 1027 cdminphys(struct buf *bp)
 1028 {
 1029         struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(bp->b_dev)];
 1030         long max;
 1031 
 1032         /*
 1033          * If the device is ancient, we want to make sure that
 1034          * the transfer fits into a 6-byte cdb.
 1035          *
 1036          * XXX Note that the SCSI-I spec says that 256-block transfers
 1037          * are allowed in a 6-byte read/write, and are specified
 1038          * by settng the "length" to 0.  However, we're conservative
 1039          * here, allowing only 255-block transfers in case an
 1040          * ancient device gets confused by length == 0.  A length of 0
 1041          * in a 10-byte read/write actually means 0 blocks.
 1042          */
 1043         if (cd->flags & CDF_ANCIENT) {
 1044                 max = cd->sc_dk.dk_label->d_secsize * 0xff;
 1045 
 1046                 if (bp->b_bcount > max)
 1047                         bp->b_bcount = max;
 1048         }
 1049 
 1050         (*cd->sc_periph->periph_channel->chan_adapter->adapt_minphys)(bp);
 1051 }
 1052 
 1053 static int
 1054 cdread(dev_t dev, struct uio *uio, int ioflag)
 1055 {
 1056 
 1057         return (physio(cdstrategy, NULL, dev, B_READ, cdminphys, uio));
 1058 }
 1059 
 1060 static int
 1061 cdwrite(dev_t dev, struct uio *uio, int ioflag)
 1062 {
 1063 
 1064         return (physio(cdstrategy, NULL, dev, B_WRITE, cdminphys, uio));
 1065 }
 1066 
 1067 #if 0   /* XXX Not used */
 1068 /*
 1069  * conversion between minute-seconde-frame and logical block address
 1070  * addresses format
 1071  */
 1072 static void
 1073 lba2msf(u_long lba, u_char *m, u_char *s, u_char *f)
 1074 {
 1075         u_long tmp;
 1076 
 1077         tmp = lba + CD_BLOCK_OFFSET;    /* offset of first logical frame */
 1078         tmp &= 0xffffff;                /* negative lbas use only 24 bits */
 1079         *m = tmp / (CD_SECS * CD_FRAMES);
 1080         tmp %= (CD_SECS * CD_FRAMES);
 1081         *s = tmp / CD_FRAMES;
 1082         *f = tmp % CD_FRAMES;
 1083 }
 1084 
 1085 static u_long
 1086 msf2lba(u_char m, u_char s, u_char f)
 1087 {
 1088 
 1089         return ((((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET);
 1090 }
 1091 #endif /* XXX Not used */
 1092 
 1093 static int
 1094 cdreadmsaddr(struct cd_softc *cd, int *addr)
 1095 {
 1096         struct scsipi_periph *periph = cd->sc_periph;
 1097         int error;
 1098         struct cd_toc toc;
 1099         struct cd_toc_entry *cte;
 1100 
 1101         error = cd_read_toc_f0(cd, 0, 0, &toc,
 1102             sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry),
 1103             XS_CTL_DATA_ONSTACK,
 1104             0x40 /* control word for "get MS info" */);
 1105 
 1106         if (error)
 1107                 return (error);
 1108 
 1109         cte = &toc.entries[0];
 1110         if (periph->periph_quirks & PQUIRK_LITTLETOC) {
 1111                 cte->addr.lba = le32toh(cte->addr.lba);
 1112                 toc.header.len = le16toh(toc.header.len);
 1113         } else {
 1114                 cte->addr.lba = be32toh(cte->addr.lba);
 1115                 toc.header.len = be16toh(toc.header.len);
 1116         }
 1117 
 1118         *addr = (toc.header.len >= 10 && cte->track > 1) ?
 1119                 cte->addr.lba : 0;
 1120         return 0;
 1121 }
 1122 
 1123 /*
 1124  * Perform special action on behalf of the user.
 1125  * Knows about the internals of this device
 1126  */
 1127 static int
 1128 cdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
 1129 {
 1130         struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(dev)];
 1131         struct scsipi_periph *periph = cd->sc_periph;
 1132         int part = CDPART(dev);
 1133         int error = 0;
 1134 #ifdef __HAVE_OLD_DISKLABEL
 1135         struct disklabel *newlabel = NULL;
 1136 #endif
 1137 
 1138         SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdioctl 0x%lx ", cmd));
 1139 
 1140         /*
 1141          * If the device is not valid, some IOCTLs can still be
 1142          * handled on the raw partition. Check this here.
 1143          */
 1144         if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
 1145                 switch (cmd) {
 1146                 case DIOCWLABEL:
 1147                 case DIOCLOCK:
 1148                 case ODIOCEJECT:
 1149                 case DIOCEJECT:
 1150                 case SCIOCIDENTIFY:
 1151                 case OSCIOCIDENTIFY:
 1152                 case SCIOCCOMMAND:
 1153                 case SCIOCDEBUG:
 1154                 case CDIOCGETVOL:
 1155                 case CDIOCSETVOL:
 1156                 case CDIOCSETMONO:
 1157                 case CDIOCSETSTEREO:
 1158                 case CDIOCSETMUTE:
 1159                 case CDIOCSETLEFT:
 1160                 case CDIOCSETRIGHT:
 1161                 case CDIOCCLOSE:
 1162                 case CDIOCEJECT:
 1163                 case CDIOCALLOW:
 1164                 case CDIOCPREVENT:
 1165                 case CDIOCSETDEBUG:
 1166                 case CDIOCCLRDEBUG:
 1167                 case CDIOCRESET:
 1168                 case SCIOCRESET:
 1169                 case CDIOCLOADUNLOAD:
 1170                 case DVD_AUTH:
 1171                 case DVD_READ_STRUCT:
 1172                         if (part == RAW_PART)
 1173                                 break;
 1174                 /* FALLTHROUGH */
 1175                 default:
 1176                         if ((periph->periph_flags & PERIPH_OPEN) == 0)
 1177                                 return (ENODEV);
 1178                         else
 1179                                 return (EIO);
 1180                 }
 1181         }
 1182 
 1183         switch (cmd) {
 1184         case DIOCGDINFO:
 1185                 *(struct disklabel *)addr = *(cd->sc_dk.dk_label);
 1186                 return (0);
 1187 #ifdef __HAVE_OLD_DISKLABEL
 1188         case ODIOCGDINFO:
 1189                 newlabel = malloc(sizeof (*newlabel), M_TEMP, M_WAITOK);
 1190                 if (newlabel == NULL)
 1191                         return (EIO);
 1192                 memcpy(newlabel, cd->sc_dk.dk_label, sizeof (*newlabel));
 1193                 if (newlabel->d_npartitions > OLDMAXPARTITIONS)
 1194                         error = ENOTTY;
 1195                 else
 1196                         memcpy(addr, newlabel, sizeof (struct olddisklabel));
 1197                 free(newlabel, M_TEMP);
 1198                 return error;
 1199 #endif
 1200 
 1201         case DIOCGPART:
 1202                 ((struct partinfo *)addr)->disklab = cd->sc_dk.dk_label;
 1203                 ((struct partinfo *)addr)->part =
 1204                     &cd->sc_dk.dk_label->d_partitions[part];
 1205                 return (0);
 1206 
 1207         case DIOCWDINFO:
 1208         case DIOCSDINFO:
 1209 #ifdef __HAVE_OLD_DISKLABEL
 1210         case ODIOCWDINFO:
 1211         case ODIOCSDINFO:
 1212 #endif
 1213         {
 1214                 struct disklabel *lp;
 1215 
 1216                 if ((flag & FWRITE) == 0)
 1217                         return (EBADF);
 1218 
 1219 #ifdef __HAVE_OLD_DISKLABEL
 1220                 if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
 1221                         newlabel = malloc(sizeof (*newlabel), M_TEMP, M_WAITOK);
 1222                         if (newlabel == NULL)
 1223                                 return (EIO);
 1224                         memset(newlabel, 0, sizeof newlabel);
 1225                         memcpy(newlabel, addr, sizeof (struct olddisklabel));
 1226                         lp = newlabel;
 1227                 } else
 1228 #endif
 1229                 lp = (struct disklabel *)addr;
 1230 
 1231                 if ((error = lockmgr(&cd->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
 1232                         goto bad;
 1233                 cd->flags |= CDF_LABELLING;
 1234 
 1235                 error = setdisklabel(cd->sc_dk.dk_label,
 1236                     lp, /*cd->sc_dk.dk_openmask : */0,
 1237                     cd->sc_dk.dk_cpulabel);
 1238                 if (error == 0) {
 1239                         /* XXX ? */
 1240                 }
 1241 
 1242                 cd->flags &= ~CDF_LABELLING;
 1243                 lockmgr(&cd->sc_lock, LK_RELEASE, NULL);
 1244 bad:
 1245 #ifdef __HAVE_OLD_DISKLABEL
 1246                 if (newlabel != NULL)
 1247                         free(newlabel, M_TEMP);
 1248 #endif
 1249                 return (error);
 1250         }
 1251 
 1252         case DIOCWLABEL:
 1253                 return (EBADF);
 1254 
 1255         case DIOCGDEFLABEL:
 1256                 cdgetdefaultlabel(cd, (struct disklabel *)addr);
 1257                 return (0);
 1258 
 1259 #ifdef __HAVE_OLD_DISKLABEL
 1260         case ODIOCGDEFLABEL:
 1261                 newlabel = malloc(sizeof (*newlabel), M_TEMP, M_WAITOK);
 1262                 if (newlabel == NULL)
 1263                         return (EIO);
 1264                 cdgetdefaultlabel(cd, newlabel);
 1265                 if (newlabel->d_npartitions > OLDMAXPARTITIONS)
 1266                         error = ENOTTY;
 1267                 else
 1268                         memcpy(addr, newlabel, sizeof (struct olddisklabel));
 1269                 free(newlabel, M_TEMP);
 1270                 return error;
 1271 #endif
 1272 
 1273         case CDIOCPLAYTRACKS: {
 1274                 struct ioc_play_track *args = (struct ioc_play_track *)addr;
 1275 
 1276                 if ((error = cd_set_pa_immed(cd, 0)) != 0)
 1277                         return (error);
 1278                 return (cd_play_tracks(cd, args->start_track,
 1279                     args->start_index, args->end_track, args->end_index));
 1280         }
 1281         case CDIOCPLAYMSF: {
 1282                 struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
 1283 
 1284                 if ((error = cd_set_pa_immed(cd, 0)) != 0)
 1285                         return (error);
 1286                 return (cd_play_msf(cd, args->start_m, args->start_s,
 1287                     args->start_f, args->end_m, args->end_s, args->end_f));
 1288         }
 1289         case CDIOCPLAYBLOCKS: {
 1290                 struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
 1291 
 1292                 if ((error = cd_set_pa_immed(cd, 0)) != 0)
 1293                         return (error);
 1294                 return (cd_play(cd, args->blk, args->len));
 1295         }
 1296         case CDIOCREADSUBCHANNEL: {
 1297                 struct ioc_read_subchannel *args =
 1298                     (struct ioc_read_subchannel *)addr;
 1299                 struct cd_sub_channel_info data;
 1300                 u_int len = args->data_len;
 1301 
 1302                 if (len > sizeof(data) ||
 1303                     len < sizeof(struct cd_sub_channel_header))
 1304                         return (EINVAL);
 1305                 error = cd_read_subchannel(cd, args->address_format,
 1306                     args->data_format, args->track, &data, len,
 1307                     XS_CTL_DATA_ONSTACK);
 1308                 if (error)
 1309                         return (error);
 1310                 len = min(len, _2btol(data.header.data_len) +
 1311                     sizeof(struct cd_sub_channel_header));
 1312                 return (copyout(&data, args->data, len));
 1313         }
 1314         case CDIOREADTOCHEADER: {
 1315                 struct ioc_toc_header th;
 1316 
 1317                 if ((error = cd_read_toc_f0(cd, 0, 0, &th, sizeof(th),
 1318                     XS_CTL_DATA_ONSTACK, 0)) != 0)
 1319                         return (error);
 1320                 if (cd->sc_periph->periph_quirks & PQUIRK_LITTLETOC)
 1321                         th.len = le16toh(th.len);
 1322                 else
 1323                         th.len = be16toh(th.len);
 1324                 memcpy(addr, &th, sizeof(th));
 1325                 return (0);
 1326         }
 1327         case CDIOREADTOCENTRYS: {
 1328                 struct cd_toc toc;
 1329                 struct ioc_read_toc_entry *te =
 1330                     (struct ioc_read_toc_entry *)addr;
 1331                 struct ioc_toc_header *th;
 1332                 struct cd_toc_entry *cte;
 1333                 u_int len = te->data_len;
 1334                 int ntracks;
 1335 
 1336                 th = &toc.header;
 1337 
 1338                 if (len > sizeof(toc.entries) ||
 1339                     len < sizeof(struct cd_toc_entry))
 1340                         return (EINVAL);
 1341                 error = cd_read_toc_f0(cd, te->address_format, te->starting_track,
 1342                     &toc, len + sizeof(struct ioc_toc_header),
 1343                     XS_CTL_DATA_ONSTACK, 0);
 1344                 if (error)
 1345                         return (error);
 1346                 if (te->address_format == CD_LBA_FORMAT)
 1347                         for (ntracks =
 1348                             th->ending_track - th->starting_track + 1;
 1349                             ntracks >= 0; ntracks--) {
 1350                                 cte = &toc.entries[ntracks];
 1351                                 cte->addr_type = CD_LBA_FORMAT;
 1352                                 if (periph->periph_quirks & PQUIRK_LITTLETOC)
 1353                                         cte->addr.lba = le32toh(cte->addr.lba);
 1354                                 else
 1355                                         cte->addr.lba = be32toh(cte->addr.lba);
 1356                         }
 1357                 if (periph->periph_quirks & PQUIRK_LITTLETOC)
 1358                         th->len = le16toh(th->len);
 1359                 else
 1360                         th->len = be16toh(th->len);
 1361                 len = min(len, th->len - (sizeof(th->starting_track) +
 1362                     sizeof(th->ending_track)));
 1363                 return (copyout(toc.entries, te->data, len));
 1364         }
 1365         case CDIOREADMSADDR: {
 1366                 int sessno = *(int*)addr;
 1367 
 1368                 if (sessno != 0)
 1369                         return (EINVAL);
 1370 
 1371                 return (cdreadmsaddr(cd, (int*)addr));
 1372         }
 1373         case CDIOCSETPATCH: {
 1374                 struct ioc_patch *arg = (struct ioc_patch *)addr;
 1375 
 1376                 return (cd_setchan(cd, arg->patch[0], arg->patch[1],
 1377                     arg->patch[2], arg->patch[3], 0));
 1378         }
 1379         case CDIOCGETVOL: {
 1380                 struct ioc_vol *arg = (struct ioc_vol *)addr;
 1381 
 1382                 return (cd_getvol(cd, arg, 0));
 1383         }
 1384         case CDIOCSETVOL: {
 1385                 struct ioc_vol *arg = (struct ioc_vol *)addr;
 1386 
 1387                 return (cd_setvol(cd, arg, 0));
 1388         }
 1389 
 1390         case CDIOCSETMONO:
 1391                 return (cd_setchan(cd, BOTH_CHANNEL, BOTH_CHANNEL,
 1392                     MUTE_CHANNEL, MUTE_CHANNEL, 0));
 1393 
 1394         case CDIOCSETSTEREO:
 1395                 return (cd_setchan(cd, LEFT_CHANNEL, RIGHT_CHANNEL,
 1396                     MUTE_CHANNEL, MUTE_CHANNEL, 0));
 1397 
 1398         case CDIOCSETMUTE:
 1399                 return (cd_setchan(cd, MUTE_CHANNEL, MUTE_CHANNEL,
 1400                     MUTE_CHANNEL, MUTE_CHANNEL, 0));
 1401 
 1402         case CDIOCSETLEFT:
 1403                 return (cd_setchan(cd, LEFT_CHANNEL, LEFT_CHANNEL,
 1404                     MUTE_CHANNEL, MUTE_CHANNEL, 0));
 1405 
 1406         case CDIOCSETRIGHT:
 1407                 return (cd_setchan(cd, RIGHT_CHANNEL, RIGHT_CHANNEL,
 1408                     MUTE_CHANNEL, MUTE_CHANNEL, 0));
 1409 
 1410         case CDIOCRESUME:
 1411                 return (cd_pause(cd, PA_RESUME));
 1412         case CDIOCPAUSE:
 1413                 return (cd_pause(cd, PA_PAUSE));
 1414         case CDIOCSTART:
 1415                 return (scsipi_start(periph, SSS_START, 0));
 1416         case CDIOCSTOP:
 1417                 return (scsipi_start(periph, SSS_STOP, 0));
 1418         case CDIOCCLOSE:
 1419                 return (scsipi_start(periph, SSS_START|SSS_LOEJ,
 1420                     XS_CTL_IGNORE_NOT_READY | XS_CTL_IGNORE_MEDIA_CHANGE));
 1421         case DIOCEJECT:
 1422                 if (*(int *)addr == 0) {
 1423                         /*
 1424                          * Don't force eject: check that we are the only
 1425                          * partition open. If so, unlock it.
 1426                          */
 1427                         if ((cd->sc_dk.dk_openmask & ~(1 << part)) == 0 &&
 1428                             cd->sc_dk.dk_bopenmask + cd->sc_dk.dk_copenmask ==
 1429                             cd->sc_dk.dk_openmask) {
 1430                                 error = scsipi_prevent(periph, SPAMR_ALLOW,
 1431                                     XS_CTL_IGNORE_NOT_READY);
 1432                                 if (error)
 1433                                         return (error);
 1434                         } else {
 1435                                 return (EBUSY);
 1436                         }
 1437                 }
 1438                 /* FALLTHROUGH */
 1439         case CDIOCEJECT: /* FALLTHROUGH */
 1440         case ODIOCEJECT:
 1441                 return (scsipi_start(periph, SSS_STOP|SSS_LOEJ, 0));
 1442         case CDIOCALLOW:
 1443                 return (scsipi_prevent(periph, SPAMR_ALLOW, 0));
 1444         case CDIOCPREVENT:
 1445                 return (scsipi_prevent(periph, SPAMR_PREVENT_DT, 0));
 1446         case DIOCLOCK:
 1447                 return (scsipi_prevent(periph,
 1448                     (*(int *)addr) ? SPAMR_PREVENT_DT : SPAMR_ALLOW, 0));
 1449         case CDIOCSETDEBUG:
 1450                 cd->sc_periph->periph_dbflags |= (SCSIPI_DB1 | SCSIPI_DB2);
 1451                 return (0);
 1452         case CDIOCCLRDEBUG:
 1453                 cd->sc_periph->periph_dbflags &= ~(SCSIPI_DB1 | SCSIPI_DB2);
 1454                 return (0);
 1455         case CDIOCRESET:
 1456         case SCIOCRESET:
 1457                 return (cd_reset(cd));
 1458         case CDIOCLOADUNLOAD:
 1459                 return (cd_load_unload(cd, (struct ioc_load_unload *)addr));
 1460         case DVD_AUTH:
 1461                 return (dvd_auth(cd, (dvd_authinfo *)addr));
 1462         case DVD_READ_STRUCT:
 1463                 return (dvd_read_struct(cd, (dvd_struct *)addr));
 1464 
 1465         default:
 1466                 if (part != RAW_PART)
 1467                         return (ENOTTY);
 1468                 return (scsipi_do_ioctl(periph, dev, cmd, addr, flag, p));
 1469         }
 1470 
 1471 #ifdef DIAGNOSTIC
 1472         panic("cdioctl: impossible");
 1473 #endif
 1474 }
 1475 
 1476 static void
 1477 cdgetdefaultlabel(struct cd_softc *cd, struct disklabel *lp)
 1478 {
 1479         int lastsession;
 1480 
 1481         memset(lp, 0, sizeof(struct disklabel));
 1482 
 1483         lp->d_secsize = cd->params.blksize;
 1484         lp->d_ntracks = 1;
 1485         lp->d_nsectors = 100;
 1486         lp->d_ncylinders = (cd->params.disksize / 100) + 1;
 1487         lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
 1488 
 1489         switch (scsipi_periph_bustype(cd->sc_periph)) {
 1490         case SCSIPI_BUSTYPE_SCSI:
 1491                 lp->d_type = DTYPE_SCSI;
 1492                 break;
 1493         case SCSIPI_BUSTYPE_ATAPI:
 1494                 lp->d_type = DTYPE_ATAPI;
 1495                 break;
 1496         }
 1497         /*
 1498          * XXX
 1499          * We could probe the mode pages to figure out what kind of disc it is.
 1500          * Is this worthwhile?
 1501          */
 1502         strncpy(lp->d_typename, "mydisc", 16);
 1503         strncpy(lp->d_packname, "fictitious", 16);
 1504         lp->d_secperunit = cd->params.disksize;
 1505         lp->d_rpm = 300;
 1506         lp->d_interleave = 1;
 1507         lp->d_flags = D_REMOVABLE;
 1508 
 1509         if (cdreadmsaddr(cd, &lastsession) != 0)
 1510                 lastsession = 0;
 1511 
 1512         lp->d_partitions[0].p_offset = 0;
 1513 #ifdef notyet /* have to fix bounds_check_with_label() first */
 1514         lp->d_partitions[0].p_size = lp->d_secperunit;
 1515 #else
 1516         lp->d_partitions[0].p_size =
 1517             lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
 1518 #endif
 1519         lp->d_partitions[0].p_cdsession = lastsession;
 1520         lp->d_partitions[0].p_fstype = FS_ISO9660;
 1521         lp->d_partitions[RAW_PART].p_offset = 0;
 1522 #ifdef notyet
 1523         lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
 1524 #else
 1525         lp->d_partitions[RAW_PART].p_size =
 1526             lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
 1527 #endif
 1528         lp->d_partitions[RAW_PART].p_fstype = FS_ISO9660;
 1529         lp->d_npartitions = RAW_PART + 1;
 1530 
 1531         lp->d_magic = DISKMAGIC;
 1532         lp->d_magic2 = DISKMAGIC;
 1533         lp->d_checksum = dkcksum(lp);
 1534 }
 1535 
 1536 /*
 1537  * Load the label information on the named device
 1538  * Actually fabricate a disklabel
 1539  *
 1540  * EVENTUALLY take information about different
 1541  * data tracks from the TOC and put it in the disklabel
 1542  */
 1543 static void
 1544 cdgetdisklabel(struct cd_softc *cd)
 1545 {
 1546         struct disklabel *lp = cd->sc_dk.dk_label;
 1547         const char *errstring;
 1548 
 1549         memset(cd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
 1550 
 1551         cdgetdefaultlabel(cd, lp);
 1552 
 1553         /*
 1554          * Call the generic disklabel extraction routine
 1555          */
 1556         errstring = readdisklabel(MAKECDDEV(0, cd->sc_dev.dv_unit, RAW_PART),
 1557             cdstrategy, lp, cd->sc_dk.dk_cpulabel);
 1558         if (errstring) {
 1559                 printf("%s: %s\n", cd->sc_dev.dv_xname, errstring);
 1560                 goto error;
 1561         }
 1562         return;
 1563 
 1564 error:
 1565         /* Reset to default label -- should print a warning */
 1566         memset(cd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
 1567 
 1568         cdgetdefaultlabel(cd, lp);
 1569 }
 1570 
 1571 /*
 1572  * Find out from the device what it's capacity is
 1573  */
 1574 static u_long
 1575 cd_size(struct cd_softc *cd, int flags)
 1576 {
 1577         struct scsipi_read_cd_capacity cmd;
 1578         struct scsipi_read_cd_cap_data data;
 1579         int blksize;
 1580         u_long size;
 1581 
 1582         if (cd->sc_periph->periph_quirks & PQUIRK_NOCAPACITY) {
 1583                 /*
 1584                  * the drive doesn't support the READ_CD_CAPACITY command
 1585                  * use a fake size
 1586                  */
 1587                 cd->params.blksize = 2048;
 1588                 cd->params.disksize = 400000;
 1589                 cd->params.disksize512 = 1600000;
 1590                 return (400000);
 1591         }
 1592 
 1593         /*
 1594          * make up a scsi command and ask the scsi driver to do
 1595          * it for you.
 1596          */
 1597         memset(&cmd, 0, sizeof(cmd));
 1598         cmd.opcode = READ_CD_CAPACITY;
 1599 
 1600         /*
 1601          * If the command works, interpret the result as a 4 byte
 1602          * number of blocks and a blocksize
 1603          */
 1604         if (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd),
 1605             (void *)&data, sizeof(data), CDRETRIES, 30000, NULL,
 1606             flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK) != 0)
 1607                 return (0);
 1608 
 1609         blksize = _4btol(data.length);
 1610         if ((blksize < 512) || ((blksize & 511) != 0))
 1611                 blksize = 2048; /* some drives lie ! */
 1612         if (blksize != 2048) {
 1613                 if (cd_setblksize(cd) == 0)
 1614                         blksize = 2048;
 1615         }
 1616         cd->params.blksize = blksize;
 1617 
 1618         size = _4btol(data.addr) + 1;
 1619         if (size < 100)
 1620                 size = 400000;  /* ditto */
 1621         cd->params.disksize = size;
 1622         cd->params.disksize512 = ((u_int64_t)cd->params.disksize * blksize) / DEV_BSIZE;
 1623 
 1624         SC_DEBUG(cd->sc_periph, SCSIPI_DB2,
 1625             ("cd_size: %d %ld\n", blksize, size));
 1626         return (size);
 1627 }
 1628 
 1629 /*
 1630  * Get scsi driver to send a "start playing" command
 1631  */
 1632 static int
 1633 cd_play(struct cd_softc *cd, int blkno, int nblks)
 1634 {
 1635         struct scsipi_play cmd;
 1636 
 1637         memset(&cmd, 0, sizeof(cmd));
 1638         cmd.opcode = PLAY;
 1639         _lto4b(blkno, cmd.blk_addr);
 1640         _lto2b(nblks, cmd.xfer_len);
 1641 
 1642         return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
 1643             CDRETRIES, 30000, NULL, 0));
 1644 }
 1645 
 1646 /*
 1647  * Get scsi driver to send a "start playing" command
 1648  */
 1649 static int
 1650 cd_play_tracks(struct cd_softc *cd, int strack, int sindex, int etrack,
 1651     int eindex)
 1652 {
 1653         struct cd_toc toc;
 1654         int error;
 1655 
 1656         if (!etrack)
 1657                 return (EIO);
 1658         if (strack > etrack)
 1659                 return (EINVAL);
 1660 
 1661         if ((error = cd_load_toc(cd, &toc, XS_CTL_DATA_ONSTACK)) != 0)
 1662                 return (error);
 1663 
 1664         if (++etrack > (toc.header.ending_track+1))
 1665                 etrack = toc.header.ending_track+1;
 1666 
 1667         strack -= toc.header.starting_track;
 1668         etrack -= toc.header.starting_track;
 1669         if (strack < 0)
 1670                 return (EINVAL);
 1671 
 1672         return (cd_play_msf(cd, toc.entries[strack].addr.msf.minute,
 1673             toc.entries[strack].addr.msf.second,
 1674             toc.entries[strack].addr.msf.frame,
 1675             toc.entries[etrack].addr.msf.minute,
 1676             toc.entries[etrack].addr.msf.second,
 1677             toc.entries[etrack].addr.msf.frame));
 1678 }
 1679 
 1680 /*
 1681  * Get scsi driver to send a "play msf" command
 1682  */
 1683 static int
 1684 cd_play_msf(struct cd_softc *cd, int startm, int starts, int startf, int endm,
 1685     int ends, int endf)
 1686 {
 1687         struct scsipi_play_msf cmd;
 1688 
 1689         memset(&cmd, 0, sizeof(cmd));
 1690         cmd.opcode = PLAY_MSF;
 1691         cmd.start_m = startm;
 1692         cmd.start_s = starts;
 1693         cmd.start_f = startf;
 1694         cmd.end_m = endm;
 1695         cmd.end_s = ends;
 1696         cmd.end_f = endf;
 1697 
 1698         return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
 1699             CDRETRIES, 30000, NULL, 0));
 1700 }
 1701 
 1702 /*
 1703  * Get scsi driver to send a "start up" command
 1704  */
 1705 static int
 1706 cd_pause(struct cd_softc *cd, int go)
 1707 {
 1708         struct scsipi_pause cmd;
 1709 
 1710         memset(&cmd, 0, sizeof(cmd));
 1711         cmd.opcode = PAUSE;
 1712         cmd.resume = go & 0xff;
 1713 
 1714         return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
 1715             CDRETRIES, 30000, NULL, 0));
 1716 }
 1717 
 1718 /*
 1719  * Get scsi driver to send a "RESET" command
 1720  */
 1721 static int
 1722 cd_reset(struct cd_softc *cd)
 1723 {
 1724 
 1725         return (scsipi_command(cd->sc_periph, 0, 0, 0, 0,
 1726             CDRETRIES, 30000, NULL, XS_CTL_RESET));
 1727 }
 1728 
 1729 /*
 1730  * Read subchannel
 1731  */
 1732 static int
 1733 cd_read_subchannel(struct cd_softc *cd, int mode, int format, int track,
 1734     struct cd_sub_channel_info *data, int len, int flags)
 1735 {
 1736         struct scsipi_read_subchannel cmd;
 1737 
 1738         memset(&cmd, 0, sizeof(cmd));
 1739         cmd.opcode = READ_SUBCHANNEL;
 1740         if (mode == CD_MSF_FORMAT)
 1741                 cmd.byte2 |= CD_MSF;
 1742         cmd.byte3 = SRS_SUBQ;
 1743         cmd.subchan_format = format;
 1744         cmd.track = track;
 1745         _lto2b(len, cmd.data_len);
 1746 
 1747         return (scsipi_command(cd->sc_periph,
 1748             (void *)&cmd, sizeof(struct scsipi_read_subchannel),
 1749             (void *)data, len,
 1750             CDRETRIES, 30000, NULL, flags | XS_CTL_DATA_IN | XS_CTL_SILENT));
 1751 }
 1752 
 1753 /*
 1754  * Read table of contents
 1755  */
 1756 static int
 1757 cd_read_toc_f0(struct cd_softc *cd, int mode, int start, void *data, int len,
 1758     int flags, int control)
 1759 {
 1760         struct scsipi_read_toc cmd;
 1761         int ntoc;
 1762 
 1763         memset(&cmd, 0, sizeof(cmd));
 1764 #if 0
 1765         if (len != sizeof(struct ioc_toc_header))
 1766                 ntoc = ((len) - sizeof(struct ioc_toc_header)) /
 1767                     sizeof(struct cd_toc_entry);
 1768         else
 1769 #endif
 1770         ntoc = len;
 1771         cmd.opcode = READ_TOC;
 1772         if (mode == CD_MSF_FORMAT)
 1773                 cmd.addr_mode |= CD_MSF;
 1774         cmd.resp_format = 0;
 1775         cmd.from_track = start;
 1776         _lto2b(ntoc, cmd.data_len);
 1777         cmd.control = control;
 1778 
 1779         return (scsipi_command(cd->sc_periph,
 1780             (void *)&cmd, sizeof(cmd), (void *)data, len, CDRETRIES,
 1781             30000, NULL, flags | XS_CTL_DATA_IN));
 1782 }
 1783 
 1784 static int
 1785 cd_load_toc(struct cd_softc *cd, struct cd_toc *toc, int flags)
 1786 {
 1787         int ntracks, len, error;
 1788 
 1789         if ((error = cd_read_toc_f0(cd, 0, 0, toc, sizeof(toc->header),
 1790             flags, 0)) != 0)
 1791                 return (error);
 1792 
 1793         ntracks = toc->header.ending_track - toc->header.starting_track + 1;
 1794         len = (ntracks + 1) * sizeof(struct cd_toc_entry) +
 1795             sizeof(toc->header);
 1796         if ((error = cd_read_toc_f0(cd, CD_MSF_FORMAT, 0, toc, len,
 1797             flags, 0)) != 0)
 1798                 return (error);
 1799         return (0);
 1800 }
 1801 
 1802 /*
 1803  * Get the scsi driver to send a full inquiry to the device and use the
 1804  * results to fill out the disk parameter structure.
 1805  */
 1806 static int
 1807 cd_get_parms(struct cd_softc *cd, int flags)
 1808 {
 1809 
 1810         /*
 1811          * give a number of sectors so that sec * trks * cyls
 1812          * is <= disk_size
 1813          */
 1814         if (cd_size(cd, flags) == 0)
 1815                 return (ENXIO);
 1816         return (0);
 1817 }
 1818 
 1819 static int
 1820 cdsize(dev_t dev)
 1821 {
 1822 
 1823         /* CD-ROMs are read-only. */
 1824         return (-1);
 1825 }
 1826 
 1827 static int
 1828 cddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
 1829 {
 1830 
 1831         /* Not implemented. */
 1832         return (ENXIO);
 1833 }
 1834 
 1835 #define dvd_copy_key(dst, src)          memcpy((dst), (src), sizeof(dvd_key))
 1836 #define dvd_copy_challenge(dst, src)    memcpy((dst), (src), sizeof(dvd_challenge))
 1837 
 1838 static int
 1839 dvd_auth(struct cd_softc *cd, dvd_authinfo *a)
 1840 {
 1841         struct scsipi_generic cmd;
 1842         u_int8_t buf[20];
 1843         int error;
 1844 
 1845         memset(cmd.bytes, 0, 15);
 1846         memset(buf, 0, sizeof(buf));
 1847 
 1848         switch (a->type) {
 1849         case DVD_LU_SEND_AGID:
 1850                 cmd.opcode = GPCMD_REPORT_KEY;
 1851                 cmd.bytes[8] = 8;
 1852                 cmd.bytes[9] = 0 | (0 << 6);
 1853                 error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 8,
 1854                     CDRETRIES, 30000, NULL,
 1855                     XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 1856                 if (error)
 1857                         return (error);
 1858                 a->lsa.agid = buf[7] >> 6;
 1859                 return (0);
 1860 
 1861         case DVD_LU_SEND_CHALLENGE:
 1862                 cmd.opcode = GPCMD_REPORT_KEY;
 1863                 cmd.bytes[8] = 16;
 1864                 cmd.bytes[9] = 1 | (a->lsc.agid << 6);
 1865                 error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 16,
 1866                     CDRETRIES, 30000, NULL,
 1867                     XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 1868                 if (error)
 1869                         return (error);
 1870                 dvd_copy_challenge(a->lsc.chal, &buf[4]);
 1871                 return (0);
 1872 
 1873         case DVD_LU_SEND_KEY1:
 1874                 cmd.opcode = GPCMD_REPORT_KEY;
 1875                 cmd.bytes[8] = 12;
 1876                 cmd.bytes[9] = 2 | (a->lsk.agid << 6);
 1877                 error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 12,
 1878                     CDRETRIES, 30000, NULL,
 1879                     XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 1880                 if (error)
 1881                         return (error);
 1882                 dvd_copy_key(a->lsk.key, &buf[4]);
 1883                 return (0);
 1884 
 1885         case DVD_LU_SEND_TITLE_KEY:
 1886                 cmd.opcode = GPCMD_REPORT_KEY;
 1887                 _lto4b(a->lstk.lba, &cmd.bytes[1]);
 1888                 cmd.bytes[8] = 12;
 1889                 cmd.bytes[9] = 4 | (a->lstk.agid << 6);
 1890                 error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 12,
 1891                     CDRETRIES, 30000, NULL,
 1892                     XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 1893                 if (error)
 1894                         return (error);
 1895                 a->lstk.cpm = (buf[4] >> 7) & 1;
 1896                 a->lstk.cp_sec = (buf[4] >> 6) & 1;
 1897                 a->lstk.cgms = (buf[4] >> 4) & 3;
 1898                 dvd_copy_key(a->lstk.title_key, &buf[5]);
 1899                 return (0);
 1900 
 1901         case DVD_LU_SEND_ASF:
 1902                 cmd.opcode = GPCMD_REPORT_KEY;
 1903                 cmd.bytes[8] = 8;
 1904                 cmd.bytes[9] = 5 | (a->lsasf.agid << 6);
 1905                 error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 8,
 1906                     CDRETRIES, 30000, NULL,
 1907                     XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 1908                 if (error)
 1909                         return (error);
 1910                 a->lsasf.asf = buf[7] & 1;
 1911                 return (0);
 1912 
 1913         case DVD_HOST_SEND_CHALLENGE:
 1914                 cmd.opcode = GPCMD_SEND_KEY;
 1915                 cmd.bytes[8] = 16;
 1916                 cmd.bytes[9] = 1 | (a->hsc.agid << 6);
 1917                 buf[1] = 14;
 1918                 dvd_copy_challenge(&buf[4], a->hsc.chal);
 1919                 error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 16,
 1920                     CDRETRIES, 30000, NULL,
 1921                     XS_CTL_DATA_OUT|XS_CTL_DATA_ONSTACK);
 1922                 if (error)
 1923                         return (error);
 1924                 a->type = DVD_LU_SEND_KEY1;
 1925                 return (0);
 1926 
 1927         case DVD_HOST_SEND_KEY2:
 1928                 cmd.opcode = GPCMD_SEND_KEY;
 1929                 cmd.bytes[8] = 12;
 1930                 cmd.bytes[9] = 3 | (a->hsk.agid << 6);
 1931                 buf[1] = 10;
 1932                 dvd_copy_key(&buf[4], a->hsk.key);
 1933                 error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 12,
 1934                     CDRETRIES, 30000, NULL,
 1935                     XS_CTL_DATA_OUT|XS_CTL_DATA_ONSTACK);
 1936                 if (error) {
 1937                         a->type = DVD_AUTH_FAILURE;
 1938                         return (error);
 1939                 }
 1940                 a->type = DVD_AUTH_ESTABLISHED;
 1941                 return (0);
 1942 
 1943         case DVD_INVALIDATE_AGID:
 1944                 cmd.opcode = GPCMD_REPORT_KEY;
 1945                 cmd.bytes[9] = 0x3f | (a->lsa.agid << 6);
 1946                 error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 16,
 1947                     CDRETRIES, 30000, NULL, 0);
 1948                 if (error)
 1949                         return (error);
 1950                 return (0);
 1951 
 1952         case DVD_LU_SEND_RPC_STATE:
 1953                 cmd.opcode = GPCMD_REPORT_KEY;
 1954                 cmd.bytes[8] = 8;
 1955                 cmd.bytes[9] = 8 | (0 << 6);
 1956                 error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 8,
 1957                     CDRETRIES, 30000, NULL,
 1958                     XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 1959                 if (error)
 1960                         return (error);
 1961                 a->lrpcs.type = (buf[4] >> 6) & 3;
 1962                 a->lrpcs.vra = (buf[4] >> 3) & 7;
 1963                 a->lrpcs.ucca = (buf[4]) & 7;
 1964                 a->lrpcs.region_mask = buf[5];
 1965                 a->lrpcs.rpc_scheme = buf[6];
 1966                 return (0);
 1967 
 1968         case DVD_HOST_SEND_RPC_STATE:
 1969                 cmd.opcode = GPCMD_SEND_KEY;
 1970                 cmd.bytes[8] = 8;
 1971                 cmd.bytes[9] = 6 | (0 << 6);
 1972                 buf[1] = 6;
 1973                 buf[4] = a->hrpcs.pdrc;
 1974                 error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 8,
 1975                     CDRETRIES, 30000, NULL,
 1976                     XS_CTL_DATA_OUT|XS_CTL_DATA_ONSTACK);
 1977                 if (error)
 1978                         return (error);
 1979                 return (0);
 1980 
 1981         default:
 1982                 return (ENOTTY);
 1983         }
 1984 }
 1985 
 1986 static int
 1987 dvd_read_physical(struct cd_softc *cd, dvd_struct *s)
 1988 {
 1989         struct scsipi_generic cmd;
 1990         u_int8_t buf[4 + 4 * 20], *bufp;
 1991         int error;
 1992         struct dvd_layer *layer;
 1993         int i;
 1994 
 1995         memset(cmd.bytes, 0, 15);
 1996         memset(buf, 0, sizeof(buf));
 1997         cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
 1998         cmd.bytes[6] = s->type;
 1999         _lto2b(sizeof(buf), &cmd.bytes[7]);
 2000 
 2001         cmd.bytes[5] = s->physical.layer_num;
 2002         error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
 2003             CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 2004         if (error)
 2005                 return (error);
 2006         for (i = 0, bufp = &buf[4], layer = &s->physical.layer[0]; i < 4;
 2007              i++, bufp += 20, layer++) {
 2008                 memset(layer, 0, sizeof(*layer));
 2009                 layer->book_version = bufp[0] & 0xf;
 2010                 layer->book_type = bufp[0] >> 4;
 2011                 layer->min_rate = bufp[1] & 0xf;
 2012                 layer->disc_size = bufp[1] >> 4;
 2013                 layer->layer_type = bufp[2] & 0xf;
 2014                 layer->track_path = (bufp[2] >> 4) & 1;
 2015                 layer->nlayers = (bufp[2] >> 5) & 3;
 2016                 layer->track_density = bufp[3] & 0xf;
 2017                 layer->linear_density = bufp[3] >> 4;
 2018                 layer->start_sector = _4btol(&bufp[4]);
 2019                 layer->end_sector = _4btol(&bufp[8]);
 2020                 layer->end_sector_l0 = _4btol(&bufp[12]);
 2021                 layer->bca = bufp[16] >> 7;
 2022         }
 2023         return (0);
 2024 }
 2025 
 2026 static int
 2027 dvd_read_copyright(struct cd_softc *cd, dvd_struct *s)
 2028 {
 2029         struct scsipi_generic cmd;
 2030         u_int8_t buf[8];
 2031         int error;
 2032 
 2033         memset(cmd.bytes, 0, 15);
 2034         memset(buf, 0, sizeof(buf));
 2035         cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
 2036         cmd.bytes[6] = s->type;
 2037         _lto2b(sizeof(buf), &cmd.bytes[7]);
 2038 
 2039         cmd.bytes[5] = s->copyright.layer_num;
 2040         error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
 2041             CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 2042         if (error)
 2043                 return (error);
 2044         s->copyright.cpst = buf[4];
 2045         s->copyright.rmi = buf[5];
 2046         return (0);
 2047 }
 2048 
 2049 static int
 2050 dvd_read_disckey(struct cd_softc *cd, dvd_struct *s)
 2051 {
 2052         struct scsipi_generic cmd;
 2053         u_int8_t *buf;
 2054         int error;
 2055 
 2056         buf = malloc(4 + 2048, M_TEMP, M_WAITOK|M_ZERO);
 2057         if (buf == NULL)
 2058                 return EIO;
 2059         memset(cmd.bytes, 0, 15);
 2060         cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
 2061         cmd.bytes[6] = s->type;
 2062         _lto2b(4 + 2048, &cmd.bytes[7]);
 2063 
 2064         cmd.bytes[9] = s->disckey.agid << 6;
 2065         error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 4 + 2048,
 2066             CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 2067         if (error == 0)
 2068                 memcpy(s->disckey.value, &buf[4], 2048);
 2069         free(buf, M_TEMP);
 2070         return error;
 2071 }
 2072 
 2073 static int
 2074 dvd_read_bca(struct cd_softc *cd, dvd_struct *s)
 2075 {
 2076         struct scsipi_generic cmd;
 2077         u_int8_t buf[4 + 188];
 2078         int error;
 2079 
 2080         memset(cmd.bytes, 0, 15);
 2081         memset(buf, 0, sizeof(buf));
 2082         cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
 2083         cmd.bytes[6] = s->type;
 2084         _lto2b(sizeof(buf), &cmd.bytes[7]);
 2085 
 2086         error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
 2087             CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 2088         if (error)
 2089                 return (error);
 2090         s->bca.len = _2btol(&buf[0]);
 2091         if (s->bca.len < 12 || s->bca.len > 188)
 2092                 return (EIO);
 2093         memcpy(s->bca.value, &buf[4], s->bca.len);
 2094         return (0);
 2095 }
 2096 
 2097 static int
 2098 dvd_read_manufact(struct cd_softc *cd, dvd_struct *s)
 2099 {
 2100         struct scsipi_generic cmd;
 2101         u_int8_t *buf;
 2102         int error;
 2103 
 2104         buf = malloc(4 + 2048, M_TEMP, M_WAITOK|M_ZERO);
 2105         if (buf == NULL)
 2106                 return (EIO);
 2107         memset(cmd.bytes, 0, 15);
 2108         cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
 2109         cmd.bytes[6] = s->type;
 2110         _lto2b(4 + 2048, &cmd.bytes[7]);
 2111 
 2112         error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 4 + 2048,
 2113             CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
 2114         if (error == 0) {
 2115                 s->manufact.len = _2btol(&buf[0]);
 2116                 if (s->manufact.len >= 0 && s->manufact.len <= 2048)
 2117                         memcpy(s->manufact.value, &buf[4], s->manufact.len);
 2118                 else
 2119                         error = EIO;
 2120         }
 2121         free(buf, M_TEMP);
 2122         return error;
 2123 }
 2124 
 2125 static int
 2126 dvd_read_struct(struct cd_softc *cd, dvd_struct *s)
 2127 {
 2128 
 2129         switch (s->type) {
 2130         case DVD_STRUCT_PHYSICAL:
 2131                 return (dvd_read_physical(cd, s));
 2132         case DVD_STRUCT_COPYRIGHT:
 2133                 return (dvd_read_copyright(cd, s));
 2134         case DVD_STRUCT_DISCKEY:
 2135                 return (dvd_read_disckey(cd, s));
 2136         case DVD_STRUCT_BCA:
 2137                 return (dvd_read_bca(cd, s));
 2138         case DVD_STRUCT_MANUFACT:
 2139                 return (dvd_read_manufact(cd, s));
 2140         default:
 2141                 return (EINVAL);
 2142         }
 2143 }
 2144 
 2145 static int
 2146 cd_mode_sense(struct cd_softc *cd, u_int8_t byte2, void *sense, size_t size,
 2147     int page, int flags, int *big)
 2148 {
 2149 
 2150         if (cd->sc_periph->periph_quirks & PQUIRK_ONLYBIG) {
 2151                 *big = 1;
 2152                 return scsipi_mode_sense_big(cd->sc_periph, byte2, page, sense,
 2153                     size + sizeof(struct scsi_mode_parameter_header_10),
 2154                     flags | XS_CTL_DATA_ONSTACK, CDRETRIES, 20000);
 2155         } else {
 2156                 *big = 0;
 2157                 return scsipi_mode_sense(cd->sc_periph, byte2, page, sense,
 2158                     size + sizeof(struct scsi_mode_parameter_header_6),
 2159                     flags | XS_CTL_DATA_ONSTACK, CDRETRIES, 20000);
 2160         }
 2161 }
 2162 
 2163 static int
 2164 cd_mode_select(struct cd_softc *cd, u_int8_t byte2, void *sense, size_t size,
 2165     int flags, int big)
 2166 {
 2167 
 2168         if (big) {
 2169                 struct scsi_mode_parameter_header_10 *header = sense;
 2170 
 2171                 _lto2b(0, header->data_length);
 2172                 return scsipi_mode_select_big(cd->sc_periph, byte2, sense,
 2173                     size + sizeof(struct scsi_mode_parameter_header_10),
 2174                     flags | XS_CTL_DATA_ONSTACK, CDRETRIES, 20000);
 2175         } else {
 2176                 struct scsi_mode_parameter_header_6 *header = sense;
 2177 
 2178                 header->data_length = 0;
 2179                 return scsipi_mode_select(cd->sc_periph, byte2, sense,
 2180                     size + sizeof(struct scsi_mode_parameter_header_6),
 2181                     flags | XS_CTL_DATA_ONSTACK, CDRETRIES, 20000);
 2182         }
 2183 }
 2184 
 2185 static int
 2186 cd_set_pa_immed(struct cd_softc *cd, int flags)
 2187 {
 2188         struct {
 2189                 union {
 2190                         struct scsi_mode_parameter_header_6 small;
 2191                         struct scsi_mode_parameter_header_10 big;
 2192                 } header;
 2193                 struct cd_audio_page page;
 2194         } data;
 2195         int error;
 2196         uint8_t oflags;
 2197         int big, byte2;
 2198         struct cd_audio_page *page;
 2199 
 2200         byte2 = SMS_DBD;
 2201 try_again:
 2202         if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page),
 2203             AUDIO_PAGE, flags, &big)) != 0) {
 2204                 if (byte2 == SMS_DBD) {
 2205                         /* Device may not understand DBD; retry without */
 2206                         byte2 = 0;
 2207                         goto try_again;
 2208                 }
 2209                 return (error);
 2210         }
 2211 
 2212         if (big)
 2213                 page = (void *)((u_long)&data.header.big +
 2214                                 sizeof data.header.big +
 2215                                 _2btol(data.header.big.blk_desc_len));
 2216         else
 2217                 page = (void *)((u_long)&data.header.small +
 2218                                 sizeof data.header.small +
 2219                                 data.header.small.blk_desc_len);
 2220 
 2221         oflags = page->flags;
 2222         page->flags &= ~CD_PA_SOTC;
 2223         page->flags |= CD_PA_IMMED;
 2224         if (oflags == page->flags)
 2225                 return (0);
 2226 
 2227         return (cd_mode_select(cd, SMS_PF, &data,
 2228             sizeof(struct scsi_mode_page_header) + page->pg_length,
 2229             flags, big));
 2230 }
 2231 
 2232 static int
 2233 cd_setchan(struct cd_softc *cd, int p0, int p1, int p2, int p3, int flags)
 2234 {
 2235         struct {
 2236                 union {
 2237                         struct scsi_mode_parameter_header_6 small;
 2238                         struct scsi_mode_parameter_header_10 big;
 2239                 } header;
 2240                 struct cd_audio_page page;
 2241         } data;
 2242         int error;
 2243         int big, byte2;
 2244         struct cd_audio_page *page;
 2245 
 2246         byte2 = SMS_DBD;
 2247 try_again:
 2248         if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page),
 2249             AUDIO_PAGE, flags, &big)) != 0) {
 2250                 if (byte2 == SMS_DBD) {
 2251                         /* Device may not understand DBD; retry without */
 2252                         byte2 = 0;
 2253                         goto try_again;
 2254                 }
 2255                 return (error);
 2256         }
 2257 
 2258         if (big)
 2259                 page = (void *)((u_long)&data.header.big +
 2260                                 sizeof data.header.big +
 2261                                 _2btol(data.header.big.blk_desc_len));
 2262         else
 2263                 page = (void *)((u_long)&data.header.small +
 2264                                 sizeof data.header.small +
 2265                                 data.header.small.blk_desc_len);
 2266 
 2267         page->port[0].channels = p0;
 2268         page->port[1].channels = p1;
 2269         page->port[2].channels = p2;
 2270         page->port[3].channels = p3;
 2271 
 2272         return (cd_mode_select(cd, SMS_PF, &data,
 2273             sizeof(struct scsi_mode_page_header) + page->pg_length,
 2274             flags, big));
 2275 }
 2276 
 2277 static int
 2278 cd_getvol(struct cd_softc *cd, struct ioc_vol *arg, int flags)
 2279 {
 2280         struct {
 2281                 union {
 2282                         struct scsi_mode_parameter_header_6 small;
 2283                         struct scsi_mode_parameter_header_10 big;
 2284                 } header;
 2285                 struct cd_audio_page page;
 2286         } data;
 2287         int error;
 2288         int big, byte2;
 2289         struct cd_audio_page *page;
 2290 
 2291         byte2 = SMS_DBD;
 2292 try_again:
 2293         if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page),
 2294             AUDIO_PAGE, flags, &big)) != 0) {
 2295                 if (byte2 == SMS_DBD) {
 2296                         /* Device may not understand DBD; retry without */
 2297                         byte2 = 0;
 2298                         goto try_again;
 2299                 }
 2300                 return (error);
 2301         }
 2302 
 2303         if (big)
 2304                 page = (void *)((u_long)&data.header.big +
 2305                                 sizeof data.header.big +
 2306                                 _2btol(data.header.big.blk_desc_len));
 2307         else
 2308                 page = (void *)((u_long)&data.header.small +
 2309                                 sizeof data.header.small +
 2310                                 data.header.small.blk_desc_len);
 2311 
 2312         arg->vol[0] = page->port[0].volume;
 2313         arg->vol[1] = page->port[1].volume;
 2314         arg->vol[2] = page->port[2].volume;
 2315         arg->vol[3] = page->port[3].volume;
 2316 
 2317         return (0);
 2318 }
 2319 
 2320 static int
 2321 cd_setvol(struct cd_softc *cd, const struct ioc_vol *arg, int flags)
 2322 {
 2323         struct {
 2324                 union {
 2325                         struct scsi_mode_parameter_header_6 small;
 2326                         struct scsi_mode_parameter_header_10 big;
 2327                 } header;
 2328                 struct cd_audio_page page;
 2329         } data, mask;
 2330         int error;
 2331         int big, byte2;
 2332         struct cd_audio_page *page, *page2;
 2333 
 2334         byte2 = SMS_DBD;
 2335 try_again:
 2336         if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page),
 2337             AUDIO_PAGE, flags, &big)) != 0) {
 2338                 if (byte2 == SMS_DBD) {
 2339                         /* Device may not understand DBD; retry without */
 2340                         byte2 = 0;
 2341                         goto try_again;
 2342                 }
 2343                 return (error);
 2344         }
 2345         if ((error = cd_mode_sense(cd, byte2, &mask, sizeof(mask.page),
 2346             AUDIO_PAGE|SMS_PCTRL_CHANGEABLE, flags, &big)) != 0)
 2347                 return (error);
 2348 
 2349         if (big) {
 2350                 page = (void *)((u_long)&data.header.big +
 2351                                 sizeof data.header.big +
 2352                                 _2btol(data.header.big.blk_desc_len));
 2353                 page2 = (void *)((u_long)&mask.header.big +
 2354                                 sizeof mask.header.big +
 2355                                 _2btol(mask.header.big.blk_desc_len));
 2356         } else {
 2357                 page = (void *)((u_long)&data.header.small +
 2358                                 sizeof data.header.small +
 2359                                 data.header.small.blk_desc_len);
 2360                 page2 = (void *)((u_long)&mask.header.small +
 2361                                 sizeof mask.header.small +
 2362                                 mask.header.small.blk_desc_len);
 2363         }
 2364 
 2365         page->port[0].volume = arg->vol[0] & page2->port[0].volume;
 2366         page->port[1].volume = arg->vol[1] & page2->port[1].volume;
 2367         page->port[2].volume = arg->vol[2] & page2->port[2].volume;
 2368         page->port[3].volume = arg->vol[3] & page2->port[3].volume;
 2369 
 2370         page->port[0].channels = CHANNEL_0;
 2371         page->port[1].channels = CHANNEL_1;
 2372 
 2373         return (cd_mode_select(cd, SMS_PF, &data,
 2374             sizeof(struct scsi_mode_page_header) + page->pg_length,
 2375             flags, big));
 2376 }
 2377 
 2378 static int
 2379 cd_load_unload(struct cd_softc *cd, struct ioc_load_unload *args)
 2380 {
 2381         struct scsipi_load_unload cmd;
 2382 
 2383         memset(&cmd, 0, sizeof(cmd));
 2384         cmd.opcode = LOAD_UNLOAD;
 2385         cmd.options = args->options;    /* ioctl uses MMC values */
 2386         cmd.slot = args->slot;
 2387 
 2388         return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
 2389             CDRETRIES, 200000, NULL, 0));
 2390 }
 2391 
 2392 static int
 2393 cd_setblksize(struct cd_softc *cd)
 2394 {
 2395         struct {
 2396                 union {
 2397                         struct scsi_mode_parameter_header_6 small;
 2398                         struct scsi_mode_parameter_header_10 big;
 2399                 } header;
 2400                 struct scsi_general_block_descriptor blk_desc;
 2401         } data;
 2402         int error;
 2403         int big, bsize;
 2404         struct scsi_general_block_descriptor *bdesc;
 2405 
 2406         if ((error = cd_mode_sense(cd, 0, &data, sizeof(data.blk_desc), 0, 0,
 2407             &big)) != 0)
 2408                 return (error);
 2409 
 2410         if (big) {
 2411                 bdesc = (void *)(&data.header.big + 1);
 2412                 bsize = _2btol(data.header.big.blk_desc_len);
 2413         } else {
 2414                 bdesc = (void *)(&data.header.small + 1);
 2415                 bsize = data.header.small.blk_desc_len;
 2416         }
 2417 
 2418         if (bsize == 0) {
 2419 printf("cd_setblksize: trying to change bsize, but no blk_desc\n");
 2420                 return (EINVAL);
 2421         }
 2422         if (_3btol(bdesc->blklen) == 2048) {
 2423 printf("cd_setblksize: trying to change bsize, but blk_desc is correct\n");
 2424                 return (EINVAL);
 2425         }
 2426 
 2427         _lto3b(2048, bdesc->blklen);
 2428 
 2429         return (cd_mode_select(cd, SMS_PF, &data, sizeof(data.blk_desc), 0,
 2430             big));
 2431 }

Cache object: 64d7285dc27d4d7ea32171e161097216


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.