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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 8caf9ac9b6aee1b0cd703b92f9d7da97


[ 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.