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


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

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

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

    1 /*      $NetBSD: cd.c,v 1.354 2022/06/26 21:00:28 andvar Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1998, 2001, 2003, 2004, 2005, 2008 The NetBSD Foundation,
    5  * Inc.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Charles M. Hannum.
    9  *
   10  * MMC framework implemented and contributed to the NetBSD Foundation by
   11  * Reinoud Zandijk.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32  * POSSIBILITY OF SUCH DAMAGE.
   33  */
   34 
   35 /*
   36  * Originally written by Julian Elischer (julian@tfs.com)
   37  * for TRW Financial Systems for use under the MACH(2.5) operating system.
   38  *
   39  * TRW Financial Systems, in accordance with their agreement with Carnegie
   40  * Mellon University, makes this software available to CMU to distribute
   41  * or use in any manner that they see fit as long as this message is kept with
   42  * the software. For this reason TFS also grants any other persons or
   43  * organisations permission to use or modify this software.
   44  *
   45  * TFS supplies this software to be publicly redistributed
   46  * on the understanding that TFS is not responsible for the correct
   47  * functioning of this software in any circumstances.
   48  *
   49  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
   50  */
   51 
   52 #include <sys/cdefs.h>
   53 __KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.354 2022/06/26 21:00:28 andvar Exp $");
   54 
   55 #include <sys/param.h>
   56 #include <sys/systm.h>
   57 #include <sys/kernel.h>
   58 #include <sys/file.h>
   59 #include <sys/stat.h>
   60 #include <sys/ioctl.h>
   61 #include <sys/buf.h>
   62 #include <sys/bufq.h>
   63 #include <sys/uio.h>
   64 #include <sys/malloc.h>
   65 #include <sys/errno.h>
   66 #include <sys/device.h>
   67 #include <sys/disklabel.h>
   68 #include <sys/disk.h>
   69 #include <sys/cdio.h>
   70 #include <sys/dvdio.h>
   71 #include <sys/scsiio.h>
   72 #include <sys/proc.h>
   73 #include <sys/conf.h>
   74 #include <sys/vnode.h>
   75 #include <sys/rndsource.h>
   76 
   77 #include <dev/scsipi/scsi_spc.h>
   78 #include <dev/scsipi/scsipi_all.h>
   79 #include <dev/scsipi/scsipi_cd.h>
   80 #include <dev/scsipi/scsipi_disk.h>     /* rw_big and start_stop come */
   81 #include <dev/scsipi/scsi_all.h>
   82                                         /* from there */
   83 #include <dev/scsipi/scsi_disk.h>       /* rw comes from there */
   84 #include <dev/scsipi/scsipiconf.h>
   85 #include <dev/scsipi/scsipi_base.h>
   86 #include <dev/scsipi/cdvar.h>
   87 
   88 #include <prop/proplib.h>
   89 
   90 #define CDUNIT(z)                       DISKUNIT(z)
   91 #define CDPART(z)                       DISKPART(z)
   92 #define CDMINOR(unit, part)             DISKMINOR(unit, part)
   93 #define MAKECDDEV(maj, unit, part)      MAKEDISKDEV(maj, unit, part)
   94 
   95 #define MAXTRACK        99
   96 #define CD_BLOCK_OFFSET 150
   97 #define CD_FRAMES       75
   98 #define CD_SECS         60
   99 
  100 #define CD_TOC_FORM     0       /* formatted TOC, exposed to userland     */
  101 #define CD_TOC_MSINFO   1       /* multi-session info                     */
  102 #define CD_TOC_RAW      2       /* raw TOC as on disc, unprocessed        */
  103 #define CD_TOC_PMA      3       /* PMA, used as intermediate (rare use)   */
  104 #define CD_TOC_ATIP     4       /* pressed space of recordable            */
  105 #define CD_TOC_CDTEXT   5       /* special CD-TEXT, rarely used           */
  106 
  107 #define P5LEN   0x32
  108 #define MS5LEN  (P5LEN + 8 + 2)
  109 
  110 struct cd_formatted_toc {
  111         struct ioc_toc_header header;
  112         struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */
  113                                                  /* leadout */
  114 };
  115 
  116 struct cdbounce {
  117         struct buf *obp;        /* original buf */
  118         struct buf *lbp;        /* first buffer */
  119         struct buf *rbp;        /* second buffer */
  120         int lerr;               /* error returned for first buffer */
  121         int rerr;               /* error returned for second buffer */
  122         int head;               /* bytes skipped at the start */
  123         int lcount;             /* bytes copied to first buffer */
  124         int rcount;             /* bytes copied to second buffer */
  125 };
  126 
  127 static void     cdstart(struct scsipi_periph *);
  128 static void     cdrestart(void *);
  129 static void     cdminphys(struct buf *);
  130 static void     cddone(struct scsipi_xfer *, int);
  131 static int      cd_interpret_sense(struct scsipi_xfer *);
  132 static int      cd_diskstart(device_t, struct buf *);
  133 static void     cd_iosize(device_t, int *);
  134 static int      cd_lastclose(device_t);
  135 static int      cd_firstopen(device_t, dev_t, int, int);
  136 static void     cd_label(device_t, struct disklabel *);
  137 static u_long   cd_size(struct cd_softc *, int);
  138 static int      cd_play(struct cd_softc *, int, int);
  139 static int      cd_play_tracks(struct cd_softc *, struct cd_formatted_toc *,
  140                     int, int, int, int);
  141 static int      cd_play_msf(struct cd_softc *, int, int, int, int, int, int);
  142 static int      cd_pause(struct cd_softc *, int);
  143 static int      cd_reset(struct cd_softc *);
  144 static int      cd_read_subchannel(struct cd_softc *, int, int, int,
  145                     struct cd_sub_channel_info *, int, int);
  146 static int      cd_read_toc(struct cd_softc *, int, int, int,
  147                     struct cd_formatted_toc *, int, int, int);
  148 static int      cd_get_parms(struct cd_softc *, int);
  149 static int      cd_load_toc(struct cd_softc *, int, struct cd_formatted_toc *, int);
  150 static int      cdreadmsaddr(struct cd_softc *, struct cd_formatted_toc *,int *);
  151 static int      cdcachesync(struct scsipi_periph *periph, int flags);
  152 
  153 static int      dvd_auth(struct cd_softc *, dvd_authinfo *);
  154 static int      dvd_read_physical(struct cd_softc *, dvd_struct *);
  155 static int      dvd_read_copyright(struct cd_softc *, dvd_struct *);
  156 static int      dvd_read_disckey(struct cd_softc *, dvd_struct *);
  157 static int      dvd_read_bca(struct cd_softc *, dvd_struct *);
  158 static int      dvd_read_manufact(struct cd_softc *, dvd_struct *);
  159 static int      dvd_read_struct(struct cd_softc *, dvd_struct *);
  160 
  161 static int      cd_mode_sense(struct cd_softc *, u_int8_t, void *, size_t, int,
  162                     int, int *);
  163 static int      cd_mode_select(struct cd_softc *, u_int8_t, void *, size_t,
  164                     int, int);
  165 static int      cd_setchan(struct cd_softc *, int, int, int, int, int);
  166 static int      cd_getvol(struct cd_softc *, struct ioc_vol *, int);
  167 static int      cd_setvol(struct cd_softc *, const struct ioc_vol *, int);
  168 static int      cd_set_pa_immed(struct cd_softc *, int);
  169 static int      cd_load_unload(struct cd_softc *, struct ioc_load_unload *);
  170 static int      cd_setblksize(struct cd_softc *);
  171 
  172 static int      cdmatch(device_t, cfdata_t, void *);
  173 static void     cdattach(device_t, device_t, void *);
  174 static int      cddetach(device_t, int);
  175 
  176 static int      mmc_getdiscinfo(struct scsipi_periph *, struct mmc_discinfo *);
  177 static int      mmc_gettrackinfo(struct scsipi_periph *, struct mmc_trackinfo *);
  178 static int      mmc_do_op(struct scsipi_periph *, struct mmc_op *);
  179 static int      mmc_setup_writeparams(struct scsipi_periph *, struct mmc_writeparams *);
  180 
  181 static void     cd_set_geometry(struct cd_softc *);
  182 
  183 CFATTACH_DECL3_NEW(cd, sizeof(struct cd_softc), cdmatch, cdattach, cddetach,
  184     NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
  185 
  186 extern struct cfdriver cd_cd;
  187 
  188 static const struct scsipi_inquiry_pattern cd_patterns[] = {
  189         {T_CDROM, T_REMOV,
  190          "",         "",                 ""},
  191         {T_WORM, T_REMOV,
  192          "",         "",                 ""},
  193 #if 0
  194         {T_CDROM, T_REMOV, /* more luns */
  195          "PIONEER ", "CD-ROM DRM-600  ", ""},
  196 #endif
  197         {T_DIRECT, T_REMOV,
  198          "NEC                 CD-ROM DRIVE:260", "", ""},
  199 };
  200 
  201 static dev_type_open(cdopen);
  202 static dev_type_close(cdclose);
  203 static dev_type_read(cdread);
  204 static dev_type_write(cdwrite);
  205 static dev_type_ioctl(cdioctl);
  206 static dev_type_strategy(cdstrategy);
  207 static dev_type_dump(cddump);
  208 static dev_type_size(cdsize);
  209 
  210 const struct bdevsw cd_bdevsw = {
  211         .d_open = cdopen,
  212         .d_close = cdclose,
  213         .d_strategy = cdstrategy,
  214         .d_ioctl = cdioctl,
  215         .d_dump = cddump,
  216         .d_psize = cdsize,
  217         .d_discard = nodiscard,
  218         .d_flag = D_DISK | D_MPSAFE
  219 };
  220 
  221 const struct cdevsw cd_cdevsw = {
  222         .d_open = cdopen,
  223         .d_close = cdclose,
  224         .d_read = cdread,
  225         .d_write = cdwrite,
  226         .d_ioctl = cdioctl,
  227         .d_stop = nostop,
  228         .d_tty = notty,
  229         .d_poll = nopoll,
  230         .d_mmap = nommap,
  231         .d_kqfilter = nokqfilter,
  232         .d_discard = nodiscard,
  233         .d_flag = D_DISK | D_MPSAFE
  234 };
  235 
  236 static const struct dkdriver cddkdriver = {
  237         .d_open = cdopen,
  238         .d_close = cdclose,
  239         .d_strategy = cdstrategy,
  240         .d_minphys = cdminphys,
  241         .d_diskstart = cd_diskstart,
  242         .d_firstopen = cd_firstopen,
  243         .d_lastclose = cd_lastclose,
  244         .d_label = cd_label,
  245 };
  246 
  247 static const struct scsipi_periphsw cd_switch = {
  248         cd_interpret_sense,     /* use our error handler first */
  249         cdstart,                /* we have a queue, which is started by this */
  250         NULL,                   /* we do not have an async handler */
  251         cddone,                 /* deal with stats at interrupt time */
  252 };
  253 
  254 /*
  255  * The routine called by the low level scsi routine when it discovers
  256  * A device suitable for this driver
  257  */
  258 static int
  259 cdmatch(device_t parent, cfdata_t match, void *aux)
  260 {
  261         struct scsipibus_attach_args *sa = aux;
  262         int priority;
  263 
  264         (void)scsipi_inqmatch(&sa->sa_inqbuf,
  265             cd_patterns, sizeof(cd_patterns) / sizeof(cd_patterns[0]),
  266             sizeof(cd_patterns[0]), &priority);
  267 
  268         return (priority);
  269 }
  270 
  271 static void
  272 cdattach(device_t parent, device_t self, void *aux)
  273 {
  274         struct cd_softc *cd = device_private(self);
  275         struct dk_softc *dksc = &cd->sc_dksc;
  276         struct scsipibus_attach_args *sa = aux;
  277         struct scsipi_periph *periph = sa->sa_periph;
  278         int dtype;
  279 
  280         SC_DEBUG(periph, SCSIPI_DB2, ("cdattach: "));
  281 
  282         switch (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(sa->sa_periph))) {
  283         case SCSIPI_BUSTYPE_SCSI:
  284                 dtype = DKTYPE_SCSI;
  285                 if (periph->periph_version == 0)
  286                         cd->flags |= CDF_ANCIENT;
  287                 break; 
  288         case SCSIPI_BUSTYPE_ATAPI:
  289                 dtype = DKTYPE_ATAPI;
  290                 break;
  291         default:
  292                 dtype = DKTYPE_UNKNOWN;
  293                 break; 
  294         }
  295 
  296         /*
  297          * Initialize and attach the disk structure.
  298          */
  299         dk_init(dksc, self, dtype);
  300         disk_init(&dksc->sc_dkdev, dksc->sc_xname, &cddkdriver);
  301 
  302         dk_attach(dksc);
  303         disk_attach(&dksc->sc_dkdev);
  304 
  305         bufq_alloc(&dksc->sc_bufq, "disksort", BUFQ_SORT_RAWBLOCK);
  306 
  307         callout_init(&cd->sc_callout, 0);
  308 
  309         /*
  310          * Store information needed to contact our base driver
  311          */
  312         cd->sc_periph = periph;
  313 
  314         periph->periph_dev = dksc->sc_dev;
  315         periph->periph_switch = &cd_switch;
  316 
  317         /*
  318          * Increase our openings to the maximum-per-periph
  319          * supported by the adapter.  This will either be
  320          * clamped down or grown by the adapter if necessary.
  321          */
  322         periph->periph_openings =
  323             SCSIPI_CHAN_MAX_PERIPH(periph->periph_channel);
  324         periph->periph_flags |= PERIPH_GROW_OPENINGS;
  325 
  326         aprint_naive("\n");
  327         aprint_normal("\n");
  328 
  329         if (!pmf_device_register(self, NULL, NULL))
  330                 aprint_error_dev(self, "couldn't establish power handler\n");
  331 }
  332 
  333 static int
  334 cddetach(device_t self, int flags)
  335 {
  336         struct cd_softc *cd = device_private(self);
  337         struct dk_softc *dksc = &cd->sc_dksc;
  338         struct scsipi_periph *periph = cd->sc_periph;
  339         struct scsipi_channel *chan = periph->periph_channel;
  340         int bmaj, cmaj, i, mn, rc;
  341 
  342         if ((rc = disk_begindetach(&dksc->sc_dkdev, cd_lastclose, self, flags)) != 0)
  343                 return rc;
  344 
  345         /* locate the major number */
  346         bmaj = bdevsw_lookup_major(&cd_bdevsw);
  347         cmaj = cdevsw_lookup_major(&cd_cdevsw);
  348 
  349         /* Nuke the vnodes for any open instances */
  350         for (i = 0; i < MAXPARTITIONS; i++) {
  351                 mn = CDMINOR(device_unit(self), i);
  352                 vdevgone(bmaj, mn, mn, VBLK);
  353                 vdevgone(cmaj, mn, mn, VCHR);
  354         }
  355 
  356         /* kill any pending restart */
  357         callout_halt(&cd->sc_callout, NULL);
  358 
  359         dk_drain(dksc);
  360 
  361         /* Kill off any pending commands. */
  362         mutex_enter(chan_mtx(chan));
  363         scsipi_kill_pending(cd->sc_periph);
  364         mutex_exit(chan_mtx(chan));
  365 
  366         bufq_free(dksc->sc_bufq);
  367 
  368         /* Detach from the disk list. */
  369         disk_detach(&dksc->sc_dkdev);
  370         disk_destroy(&dksc->sc_dkdev);
  371 
  372         dk_detach(dksc);
  373 
  374         callout_destroy(&cd->sc_callout);
  375 
  376         pmf_device_deregister(self);
  377 
  378         return (0);
  379 }
  380 
  381 /*
  382  * Serialized by caller
  383  */
  384 static int
  385 cd_firstopen(device_t self, dev_t dev, int flag, int fmt)
  386 {
  387         struct cd_softc *cd = device_private(self);
  388         struct scsipi_periph *periph = cd->sc_periph;
  389         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
  390         int error, silent;
  391         int part;
  392 
  393         part = CDPART(dev);
  394 
  395         error = scsipi_adapter_addref(adapt);
  396         if (error)
  397                 return error;
  398 
  399         if ((part == RAW_PART && fmt == S_IFCHR) || (flag & FSILENT))
  400                 silent = XS_CTL_SILENT;
  401         else
  402                 silent = 0;
  403 
  404         /* make cdclose() silent */
  405         cd->flags |= CDF_EJECTED;
  406 
  407         /* Check that it is still responding and ok. */
  408         error = scsipi_test_unit_ready(periph,
  409             XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE |
  410             XS_CTL_SILENT);
  411 
  412         /*
  413          * Start the pack spinning if necessary. Always allow the
  414          * raw partition to be opened, for raw IOCTLs. Data transfers
  415          * will check for SDEV_MEDIA_LOADED.
  416          */
  417         if (error == EIO) {
  418                 error = scsipi_start(periph, SSS_START, silent);
  419                 if (error == EINVAL)
  420                         error = EIO;
  421         }
  422         if (error) {
  423                 if (part == RAW_PART)
  424                         goto out;
  425                 goto bad;
  426         }
  427 
  428         /* Lock the pack in. */
  429         error = scsipi_prevent(periph, SPAMR_PREVENT_DT,
  430             XS_CTL_IGNORE_ILLEGAL_REQUEST |
  431             XS_CTL_IGNORE_MEDIA_CHANGE);
  432         SC_DEBUG(periph, SCSIPI_DB1,
  433             ("cdopen: scsipi_prevent, error=%d\n", error));
  434         if (error) {
  435                 if (part == RAW_PART)
  436                         goto out;
  437                 goto bad;
  438         }
  439 
  440         if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
  441                 int param_error;
  442 
  443                 /* Load the physical device parameters. */
  444                 param_error = cd_get_parms(cd, 0);
  445                 if (param_error == CDGP_RESULT_OFFLINE) {
  446                         error = ENXIO;
  447                         goto bad2;
  448                 }
  449                 periph->periph_flags |= PERIPH_MEDIA_LOADED;
  450 
  451                 SC_DEBUG(periph, SCSIPI_DB3, ("Params loaded "));
  452 
  453                 cd_set_geometry(cd);
  454 
  455                 /* make cdclose() loud again */
  456                 cd->flags &= ~CDF_EJECTED;
  457         }
  458 
  459         periph->periph_flags |= PERIPH_OPEN;
  460 
  461 out:
  462         return 0;
  463 
  464 bad2:
  465         scsipi_prevent(periph, SPAMR_ALLOW,
  466             XS_CTL_IGNORE_ILLEGAL_REQUEST |
  467             XS_CTL_IGNORE_MEDIA_CHANGE |
  468             XS_CTL_SILENT);
  469 
  470 bad:
  471         scsipi_adapter_delref(adapt);
  472         return error;
  473 }
  474 
  475 /*
  476  * open the device. Make sure the partition info is a up-to-date as can be.
  477  */
  478 static int
  479 cdopen(dev_t dev, int flag, int fmt, struct lwp *l)
  480 {
  481         struct cd_softc *cd;
  482         struct dk_softc *dksc;
  483         struct scsipi_periph *periph;
  484         int unit, part;
  485         int error;
  486 
  487         unit = CDUNIT(dev);
  488         cd = device_lookup_private(&cd_cd, unit);
  489         if (cd == NULL)
  490                 return (ENXIO);
  491         dksc = &cd->sc_dksc;
  492 
  493         periph = cd->sc_periph;
  494         part = CDPART(dev);
  495 
  496         SC_DEBUG(periph, SCSIPI_DB1,
  497             ("cdopen: dev=0x%"PRIu64" (unit %"PRIu32" (of %d), partition %d)\n",
  498             dev, unit, cd_cd.cd_ndevs, CDPART(dev)));
  499 
  500         /*
  501          * If any partition is open, but the disk has been invalidated,
  502          * disallow further opens of non-raw partition
  503          */
  504         if ((periph->periph_flags & (PERIPH_OPEN | PERIPH_MEDIA_LOADED)) ==
  505             PERIPH_OPEN) {
  506                 if (part != RAW_PART || fmt != S_IFCHR)
  507                         return EIO;
  508         }
  509 
  510         error = dk_open(dksc, dev, flag, fmt, l);
  511 
  512         SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
  513 
  514         return error;
  515 }
  516 
  517 /*      
  518  * Serialized by caller
  519  */     
  520 static int
  521 cd_lastclose(device_t self)
  522 { 
  523         struct cd_softc *cd = device_private(self);
  524         struct scsipi_periph *periph = cd->sc_periph;
  525         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
  526         int silent;
  527 
  528         if ((cd->flags & CDF_EJECTED) != 0 ||
  529             (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)
  530                 silent = XS_CTL_SILENT;
  531         else
  532                 silent = 0;
  533 
  534         cdcachesync(periph, silent);
  535 
  536         scsipi_wait_drain(periph);  
  537 
  538         scsipi_prevent(periph, SPAMR_ALLOW,
  539             XS_CTL_IGNORE_ILLEGAL_REQUEST |
  540             XS_CTL_IGNORE_NOT_READY |
  541             XS_CTL_SILENT);
  542         periph->periph_flags &= ~PERIPH_OPEN;
  543 
  544         scsipi_wait_drain(periph);
  545 
  546         scsipi_adapter_delref(adapt); 
  547 
  548         return 0;
  549 }
  550 
  551 /*
  552  * close the device.. only called if we are the LAST
  553  * occurrence of an open device
  554  */
  555 static int
  556 cdclose(dev_t dev, int flag, int fmt, struct lwp *l)
  557 {
  558         struct cd_softc *cd;
  559         struct dk_softc *dksc;
  560         int unit;
  561 
  562         unit = CDUNIT(dev);
  563         cd = device_lookup_private(&cd_cd, unit);
  564         dksc = &cd->sc_dksc;
  565 
  566         return dk_close(dksc, dev, flag, fmt, l);
  567 }
  568 
  569 static void
  570 cd_bounce_buffer_done(struct buf *bp)
  571 {
  572         struct cdbounce *bounce = bp->b_private;
  573         struct buf *obp = bounce->obp;
  574 
  575         if (bp == bounce->lbp) {
  576                 if ((bounce->lerr = bp->b_error) == 0)
  577                         memcpy(obp->b_data, (char *)bp->b_data + bounce->head, bounce->lcount);
  578                 bounce->lbp = NULL;
  579         }
  580 
  581         if (bp == bounce->rbp) {
  582                 if ((bounce->rerr = bp->b_error) == 0)
  583                         memcpy((char *)obp->b_data + bounce->lcount, bp->b_data, bounce->rcount);
  584                 bounce->rbp = NULL;
  585         }
  586 
  587         free(bp->b_data, M_DEVBUF);
  588         putiobuf(bp);
  589 
  590         if (bounce->lbp != NULL || bounce->rbp != NULL)
  591                 return;
  592 
  593         obp->b_error = bounce->rerr;
  594         if (bounce->lerr)
  595                 obp->b_error = bounce->lerr;
  596 
  597         obp->b_resid = 0;
  598         if (obp->b_error)
  599                 obp->b_resid = obp->b_bcount;
  600 
  601         free(bounce, M_DEVBUF);
  602         biodone(obp);
  603 }
  604 
  605 static int
  606 cd_make_bounce_buffer(struct cd_softc *cd, struct buf *bp, daddr_t blkno, int count, struct buf **nbpp, void *priv)
  607 {
  608         struct buf *nbp;
  609 
  610         /* We don't support bouncing writes */
  611         if ((bp->b_flags & B_READ) == 0)
  612                 return EACCES; /* XXX */
  613 
  614         nbp = getiobuf(NULL, false);
  615         if (nbp == NULL)
  616                 return ENOMEM;
  617 
  618         nbp->b_data = malloc(count, M_DEVBUF, M_NOWAIT);
  619         if (nbp->b_data == NULL) {
  620                 putiobuf(nbp);
  621                 return ENOMEM;
  622         }
  623 
  624         /* Set up the IOP to the bounce buffer */
  625         nbp->b_error = 0;
  626         nbp->b_dev = bp->b_dev;
  627         nbp->b_proc = bp->b_proc;
  628         nbp->b_bcount = count;
  629         nbp->b_bufsize = count;
  630         nbp->b_blkno = blkno;
  631         nbp->b_flags = bp->b_flags | B_READ;
  632         nbp->b_oflags = bp->b_oflags;
  633         nbp->b_cflags = bp->b_cflags;
  634         nbp->b_iodone = cd_bounce_buffer_done;
  635         nbp->b_private = priv;
  636 
  637         BIO_COPYPRIO(nbp, bp);
  638 
  639         *nbpp = nbp;
  640         return 0;
  641 }
  642 
  643 static int
  644 cd_make_bounce(struct cd_softc *cd, struct buf *bp, struct cdbounce **bouncep)
  645 {
  646         struct dk_softc *dksc = &cd->sc_dksc;
  647         unsigned secsize = dksc->sc_dkdev.dk_geom.dg_secsize;
  648         struct cdbounce *bounce;
  649         int bps, nblks, skip, total, count;
  650         daddr_t blkno;
  651         struct buf *lbp, *rbp;
  652         int error;
  653 
  654         bounce = malloc(sizeof(struct cdbounce), M_DEVBUF, M_NOWAIT|M_ZERO);
  655         if (bounce == NULL)
  656                 return ENOMEM;
  657 
  658         bps = howmany(secsize, DEV_BSIZE);
  659         nblks = howmany(bp->b_bcount, DEV_BSIZE);
  660 
  661         skip = bp->b_blkno % bps;
  662 
  663         blkno = bp->b_blkno - skip;
  664         total = roundup(nblks + skip, bps) * DEV_BSIZE;
  665 
  666         count = total;
  667         cd_iosize(dksc->sc_dev, &count);
  668 
  669         bounce->head = skip * DEV_BSIZE;
  670         bounce->lcount = imin(count - bounce->head, bp->b_bcount);
  671         bounce->rcount = bp->b_bcount - bounce->lcount;
  672 
  673         error = cd_make_bounce_buffer(cd, bp, blkno, count, &lbp, bounce);
  674         if (error)
  675                 goto bad;
  676 
  677         blkno += howmany(count, DEV_BSIZE);
  678         count = total - count;
  679 
  680         if (count > 0) {
  681                 error = cd_make_bounce_buffer(cd, bp, blkno, count, &rbp, bounce);
  682                 if (error) {
  683                         free(lbp->b_data, M_DEVBUF);
  684                         putiobuf(lbp);
  685                         goto bad;
  686                 }
  687         } else
  688                 rbp = NULL;
  689 
  690         bounce->obp = bp;
  691         bounce->lbp = lbp;
  692         bounce->rbp = rbp;
  693 
  694         *bouncep = bounce;
  695 
  696         return 0;
  697 
  698 bad:
  699         free(bounce, M_DEVBUF);
  700         return error;
  701 }
  702 
  703 /*
  704  * Actually translate the requested transfer into one the physical driver can
  705  * understand.  The transfer is described by a buf and will include only one
  706  * physical transfer.
  707  */
  708 static void
  709 cdstrategy(struct buf *bp)
  710 {
  711         struct cd_softc *cd = device_lookup_private(&cd_cd,CDUNIT(bp->b_dev));
  712         struct dk_softc *dksc = &cd->sc_dksc;
  713         struct scsipi_periph *periph = cd->sc_periph;
  714         int error;
  715 
  716         SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdstrategy "));
  717         SC_DEBUG(cd->sc_periph, SCSIPI_DB1,
  718             ("%d bytes @ blk %" PRId64 "\n", bp->b_bcount, bp->b_blkno));
  719 
  720         /*
  721          * If the device has been made invalid, error out
  722          * maybe the media changed
  723          */
  724         if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
  725                 if (periph->periph_flags & PERIPH_OPEN)
  726                         error = EIO;
  727                 else
  728                         error = ENODEV;
  729                 goto bad;
  730         }
  731 
  732         /*
  733          * If label and device don't agree in sector size use a bounce buffer
  734          */
  735         if (dksc->sc_dkdev.dk_label->d_secsize != dksc->sc_dkdev.dk_geom.dg_secsize) {
  736                 struct cdbounce *bounce = NULL;
  737 
  738                 error = cd_make_bounce(cd, bp, &bounce);
  739                 if (error)
  740                         goto bad;
  741 
  742                 dk_strategy(dksc, bounce->lbp);
  743                 if (bounce->rbp != NULL)
  744                         dk_strategy(dksc, bounce->rbp);
  745 
  746                 return;
  747         }
  748         
  749         dk_strategy(dksc, bp);
  750         return;
  751 
  752 bad:
  753         bp->b_error = error;
  754         bp->b_resid = bp->b_bcount;
  755         biodone(bp);
  756 }
  757 
  758 /*
  759  * Issue single I/O command
  760  *
  761  * Called from dk_start and implicitly from dk_strategy
  762  */
  763 static int
  764 cd_diskstart(device_t dev, struct buf *bp)
  765 {
  766         struct cd_softc *cd = device_private(dev);
  767         struct scsipi_periph *periph = cd->sc_periph;
  768         struct scsipi_channel *chan = periph->periph_channel;
  769         struct scsipi_rw_10 cmd_big;
  770         struct scsi_rw_6 cmd_small;
  771         struct scsipi_generic *cmdp;
  772         struct scsipi_xfer *xs;
  773         int error, flags, nblks, cmdlen;
  774 
  775         SC_DEBUG(periph, SCSIPI_DB2, ("cdstart "));
  776 
  777         mutex_enter(chan_mtx(chan));
  778 
  779         if (periph->periph_active >= periph->periph_openings) {
  780                 error = EAGAIN;
  781                 goto out;
  782         }
  783 
  784         /*
  785          * there is excess capacity, but a special waits
  786          * It'll need the adapter as soon as we clear out of the
  787          * way and let it run (user level wait).
  788          */
  789         if (periph->periph_flags & PERIPH_WAITING) {
  790                 periph->periph_flags &= ~PERIPH_WAITING;
  791                 cv_broadcast(periph_cv_periph(periph));
  792                 error = EAGAIN;
  793                 goto out;
  794         }
  795 
  796         /*
  797          * If the device has become invalid, abort all the
  798          * reads and writes until all files have been closed and
  799          * re-opened
  800          */
  801         if (__predict_false(
  802             (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)) {
  803                 error = EIO;
  804                 goto out;
  805         }
  806 
  807         nblks = howmany(bp->b_bcount, cd->params.blksize);
  808 
  809         /*
  810          *  Fill out the scsi command.  If the transfer will
  811          *  fit in a "small" cdb, use it.
  812          */
  813         if (((bp->b_rawblkno & 0x1fffff) == bp->b_rawblkno) &&
  814             ((nblks & 0xff) == nblks) &&
  815             !(periph->periph_quirks & PQUIRK_ONLYBIG)) {
  816                 /*
  817                  * We can fit in a small cdb.
  818                  */
  819                 memset(&cmd_small, 0, sizeof(cmd_small));
  820                 cmd_small.opcode = (bp->b_flags & B_READ) ?
  821                     SCSI_READ_6_COMMAND : SCSI_WRITE_6_COMMAND;
  822                 _lto3b(bp->b_rawblkno, cmd_small.addr);
  823                 cmd_small.length = nblks & 0xff;
  824                 cmdlen = sizeof(cmd_small);
  825                 cmdp = (struct scsipi_generic *)&cmd_small;
  826         } else {
  827                 /*
  828                  * Need a large cdb.
  829                  */
  830                 memset(&cmd_big, 0, sizeof(cmd_big));
  831                 cmd_big.opcode = (bp->b_flags & B_READ) ?
  832                     READ_10 : WRITE_10;
  833                 _lto4b(bp->b_rawblkno, cmd_big.addr);
  834                 _lto2b(nblks, cmd_big.length);
  835                 cmdlen = sizeof(cmd_big);
  836                 cmdp = (struct scsipi_generic *)&cmd_big;
  837         }
  838 
  839         /*
  840          * Figure out what flags to use.
  841          */
  842         flags = XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_SIMPLE_TAG;
  843         if (bp->b_flags & B_READ)
  844                 flags |= XS_CTL_DATA_IN;
  845         else
  846                 flags |= XS_CTL_DATA_OUT;
  847 
  848         /*
  849          * Call the routine that chats with the adapter.
  850          * Note: we cannot sleep as we may be an interrupt
  851          */
  852         xs = scsipi_make_xs_locked(periph, cmdp, cmdlen,
  853             (u_char *)bp->b_data, bp->b_bcount,
  854             CDRETRIES, 30000, bp, flags);
  855         if (__predict_false(xs == NULL)) {
  856                 /*
  857                  * out of memory. Keep this buffer in the queue, and
  858                  * retry later.
  859                  */
  860                 callout_reset(&cd->sc_callout, hz / 2, cdrestart, cd);
  861                 error = EAGAIN;
  862                 goto out;
  863         }
  864 
  865         error = scsipi_execute_xs(xs);
  866         /* with a scsipi_xfer preallocated, scsipi_command can't fail */
  867         KASSERT(error == 0);
  868 
  869 out:
  870         mutex_exit(chan_mtx(chan));
  871 
  872         return error;
  873 }
  874 
  875 /*
  876  * Recover I/O request after memory shortage
  877  *
  878  * Called from callout
  879  */
  880 static void
  881 cdrestart(void *v)
  882 {
  883         struct cd_softc *cd = v;
  884         struct dk_softc *dksc = &cd->sc_dksc;
  885 
  886         dk_start(dksc, NULL);
  887 }
  888 
  889 /*
  890  * Recover I/O request after memory shortage
  891  *
  892  * Called from scsipi midlayer when resources have been freed
  893  * with channel lock held
  894  */
  895 static void
  896 cdstart(struct scsipi_periph *periph)
  897 {
  898         struct cd_softc *cd = device_private(periph->periph_dev);
  899         struct dk_softc *dksc = &cd->sc_dksc;
  900         struct scsipi_channel *chan = periph->periph_channel;
  901 
  902         /*
  903          * release channel lock as dk_start may need to acquire
  904          * other locks
  905          *
  906          * cdstart is called from scsipi_put_xs and all its callers
  907          * release the lock afterwards. So releasing it here
  908          * doesn't matter.
  909          */
  910         mutex_exit(chan_mtx(chan));
  911 
  912         dk_start(dksc, NULL);
  913 
  914         mutex_enter(chan_mtx(chan));
  915 }
  916 
  917 static void
  918 cddone(struct scsipi_xfer *xs, int error)
  919 {
  920         struct cd_softc *cd = device_private(xs->xs_periph->periph_dev);
  921         struct dk_softc *dksc = &cd->sc_dksc;
  922         struct buf *bp = xs->bp;
  923 
  924         if (bp) {
  925                 bp->b_error = error;
  926                 bp->b_resid = xs->resid;
  927                 if (error) {
  928                         /* on a read/write error bp->b_resid is zero, so fix */
  929                         bp->b_resid = bp->b_bcount;
  930                 }
  931 
  932                 dk_done(dksc, bp);
  933                 /* dk_start is called from scsipi_complete */
  934         }
  935 }
  936 
  937 static int
  938 cd_interpret_sense(struct scsipi_xfer *xs)
  939 {
  940         struct scsipi_periph *periph = xs->xs_periph;
  941         struct scsi_sense_data *sense = &xs->sense.scsi_sense;
  942         int retval = EJUSTRETURN;
  943 
  944         /*
  945          * If it isn't an extended or extended/deferred error, let
  946          * the generic code handle it.
  947          */
  948         if (SSD_RCODE(sense->response_code) != SSD_RCODE_CURRENT &&
  949             SSD_RCODE(sense->response_code) != SSD_RCODE_DEFERRED)
  950                 return (retval);
  951 
  952         /*
  953          * If we got a "Unit not ready" (SKEY_NOT_READY) and "Logical Unit
  954          * Is In The Process of Becoming Ready" (Sense code 0x04,0x01), then
  955          * wait a bit for the drive to spin up
  956          */
  957 
  958         if ((SSD_SENSE_KEY(sense->flags) == SKEY_NOT_READY) &&
  959             (sense->asc == 0x04) && (sense->ascq == 0x01)) {
  960                 /*
  961                  * Sleep for 5 seconds to wait for the drive to spin up
  962                  */
  963 
  964                 SC_DEBUG(periph, SCSIPI_DB1, ("Waiting 5 sec for CD "
  965                                                 "spinup\n"));
  966                 if (!callout_pending(&periph->periph_callout))
  967                         scsipi_periph_freeze(periph, 1);
  968                 callout_reset(&periph->periph_callout,
  969                     5 * hz, scsipi_periph_timed_thaw, periph);
  970                 retval = ERESTART;
  971         }
  972 
  973         /*
  974          * If we got a "Unit not ready" (SKEY_NOT_READY) and "Logical Unit Not
  975          * Ready, Operation In Progress" (Sense code 0x04, 0x07),
  976          * then wait for the specified time
  977          */
  978          
  979         if ((SSD_SENSE_KEY(sense->flags) == SKEY_NOT_READY) &&
  980             (sense->asc == 0x04) && (sense->ascq == 0x07)) {
  981                 /*
  982                  * we could listen to the delay; but it looks like the skey
  983                  * data is not always returned.
  984                  */
  985                 /* cd_delay = _2btol(sense->sks.sks_bytes); */
  986 
  987                 /* wait for a half second and get going again */
  988                 if (!callout_pending(&periph->periph_callout))
  989                         scsipi_periph_freeze(periph, 1);
  990                 callout_reset(&periph->periph_callout,
  991                     hz/2, scsipi_periph_timed_thaw, periph);
  992                 retval = ERESTART;
  993         }
  994 
  995         /*
  996          * If we got a "Unit not ready" (SKEY_NOT_READY) and "Long write in
  997          * progress" (Sense code 0x04, 0x08), then wait for the specified
  998          * time
  999          */
 1000          
 1001         if ((SSD_SENSE_KEY(sense->flags) == SKEY_NOT_READY) &&
 1002             (sense->asc == 0x04) && (sense->ascq == 0x08)) {
 1003                 /*
 1004                  * long write in process; we could listen to the delay; but it
 1005                  * looks like the skey data is not always returned.
 1006                  */
 1007                 /* cd_delay = _2btol(sense->sks.sks_bytes); */
 1008 
 1009                 /* wait for a half second and get going again */
 1010                 if (!callout_pending(&periph->periph_callout))
 1011                         scsipi_periph_freeze(periph, 1);
 1012                 callout_reset(&periph->periph_callout,
 1013                     hz/2, scsipi_periph_timed_thaw, periph);
 1014                 retval = ERESTART;
 1015         }
 1016 
 1017         return (retval);
 1018 }
 1019 
 1020 static void
 1021 cdminphys(struct buf *bp)
 1022 {
 1023         struct cd_softc *cd = device_lookup_private(&cd_cd, CDUNIT(bp->b_dev));
 1024         struct dk_softc *dksc = &cd->sc_dksc;
 1025         long xmax;
 1026 
 1027         /*
 1028          * If the device is ancient, we want to make sure that
 1029          * the transfer fits into a 6-byte cdb.
 1030          *
 1031          * XXX Note that the SCSI-I spec says that 256-block transfers
 1032          * are allowed in a 6-byte read/write, and are specified
 1033          * by setting the "length" to 0.  However, we're conservative
 1034          * here, allowing only 255-block transfers in case an
 1035          * ancient device gets confused by length == 0.  A length of 0
 1036          * in a 10-byte read/write actually means 0 blocks.
 1037          */
 1038         if (cd->flags & CDF_ANCIENT) {
 1039                 xmax = dksc->sc_dkdev.dk_geom.dg_secsize * 0xff;
 1040 
 1041                 if (bp->b_bcount > xmax)
 1042                         bp->b_bcount = xmax;
 1043         }
 1044 
 1045         scsipi_adapter_minphys(cd->sc_periph->periph_channel, bp);
 1046 }
 1047 
 1048 static void
 1049 cd_iosize(device_t dev, int *count)
 1050 {
 1051         struct buf B;
 1052         int bmaj;
 1053 
 1054         bmaj       = bdevsw_lookup_major(&cd_bdevsw);
 1055         B.b_dev    = MAKECDDEV(bmaj,device_unit(dev),RAW_PART);
 1056         B.b_bcount = *count;
 1057 
 1058         cdminphys(&B);
 1059 
 1060         *count = B.b_bcount;
 1061 }
 1062 
 1063 static int
 1064 cdread(dev_t dev, struct uio *uio, int ioflag)
 1065 {
 1066         return (physio(cdstrategy, NULL, dev, B_READ, cdminphys, uio));
 1067 }
 1068 
 1069 static int
 1070 cdwrite(dev_t dev, struct uio *uio, int ioflag)
 1071 {
 1072         return (physio(cdstrategy, NULL, dev, B_WRITE, cdminphys, uio));
 1073 }
 1074 
 1075 #if 0   /* XXX Not used */
 1076 /*
 1077  * conversion between minute-seconde-frame and logical block address
 1078  * addresses format
 1079  */
 1080 static void
 1081 lba2msf(u_long lba, u_char *m, u_char *s, u_char *f)
 1082 {
 1083         u_long tmp;
 1084 
 1085         tmp = lba + CD_BLOCK_OFFSET;    /* offset of first logical frame */
 1086         tmp &= 0xffffff;                /* negative lbas use only 24 bits */
 1087         *m = tmp / (CD_SECS * CD_FRAMES);
 1088         tmp %= (CD_SECS * CD_FRAMES);
 1089         *s = tmp / CD_FRAMES;
 1090         *f = tmp % CD_FRAMES;
 1091 }
 1092 #endif /* XXX Not used */
 1093 
 1094 /*
 1095  * Convert an hour:minute:second:frame address to a logical block address. In
 1096  * theory the number of secs/minute and number of frames/second could be
 1097  * configured differently in the device  as could the block offset but in
 1098  * practice these values are rock solid and most drives don't even allow
 1099  * theses values to be changed.
 1100  */
 1101 static uint32_t
 1102 hmsf2lba(uint8_t h, uint8_t m, uint8_t s, uint8_t f)
 1103 {
 1104         return (((((uint32_t) h * 60 + m) * CD_SECS) + s) * CD_FRAMES + f)
 1105                 - CD_BLOCK_OFFSET;
 1106 }
 1107 
 1108 static int
 1109 cdreadmsaddr(struct cd_softc *cd, struct cd_formatted_toc *toc, int *addr)
 1110 {
 1111         struct scsipi_periph *periph = cd->sc_periph;
 1112         int error;
 1113         struct cd_toc_entry *cte;
 1114 
 1115         error = cd_read_toc(cd, CD_TOC_FORM, 0, 0, toc,
 1116             sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry),
 1117             0, 0x40 /* control word for "get MS info" */);
 1118 
 1119         if (error)
 1120                 return (error);
 1121 
 1122         cte = &toc->entries[0];
 1123         if (periph->periph_quirks & PQUIRK_LITTLETOC) {
 1124                 cte->addr.lba = le32toh(cte->addr.lba);
 1125                 toc->header.len = le16toh(toc->header.len);
 1126         } else {
 1127                 cte->addr.lba = be32toh(cte->addr.lba);
 1128                 toc->header.len = be16toh(toc->header.len);
 1129         }
 1130 
 1131         *addr = (toc->header.len >= 10 && cte->track > 1) ?
 1132                 cte->addr.lba : 0;
 1133         return 0;
 1134 }
 1135 
 1136 /* synchronise caches code from cd.c, move to scsipi_ioctl.c ? */
 1137 static int
 1138 cdcachesync(struct scsipi_periph *periph, int flags) {
 1139         struct scsi_synchronize_cache_10 cmd;
 1140 
 1141         /*
 1142          * Issue a SYNCHRONIZE CACHE. MMC devices have to issue with address 0
 1143          * and length 0 as it can't synchronise parts of the disc per spec.
 1144          * We ignore ILLEGAL REQUEST in the event that the command is not
 1145          * supported by the device, and poll for completion so that we know
 1146          * that the cache has actually been flushed.
 1147          *
 1148          * XXX should we handle the PQUIRK_NOSYNCCACHE ?
 1149          */
 1150 
 1151         memset(&cmd, 0, sizeof(cmd));
 1152         cmd.opcode = SCSI_SYNCHRONIZE_CACHE_10;
 1153 
 1154         return (scsipi_command(periph, (void *)&cmd, sizeof(cmd), 0, 0,
 1155             CDRETRIES, 30000, NULL, flags | XS_CTL_IGNORE_ILLEGAL_REQUEST));
 1156 }
 1157 
 1158 static int
 1159 do_cdioreadentries(struct cd_softc *cd, struct ioc_read_toc_entry *te,
 1160     struct cd_formatted_toc *toc)
 1161 {
 1162         /* READ TOC format 0 command, entries */
 1163         struct ioc_toc_header *th;
 1164         struct cd_toc_entry *cte;
 1165         u_int len = te->data_len;
 1166         int ntracks;
 1167         int error;
 1168 
 1169         th = &toc->header;
 1170 
 1171         if (len > sizeof(toc->entries) ||
 1172             len < sizeof(toc->entries[0]))
 1173                 return (EINVAL);
 1174         error = cd_read_toc(cd, CD_TOC_FORM, te->address_format,
 1175             te->starting_track, toc,
 1176             sizeof(toc->header) + len,
 1177             0, 0);
 1178         if (error)
 1179                 return (error);
 1180         if (te->address_format == CD_LBA_FORMAT)
 1181                 for (ntracks =
 1182                     th->ending_track - th->starting_track + 1;
 1183                     ntracks >= 0; ntracks--) {
 1184                         cte = &toc->entries[ntracks];
 1185                         cte->addr_type = CD_LBA_FORMAT;
 1186                         if (cd->sc_periph->periph_quirks & PQUIRK_LITTLETOC)
 1187                                 cte->addr.lba = le32toh(cte->addr.lba);
 1188                         else
 1189                                 cte->addr.lba = be32toh(cte->addr.lba);
 1190                 }
 1191         if (cd->sc_periph->periph_quirks & PQUIRK_LITTLETOC)
 1192                 th->len = le16toh(th->len);
 1193         else
 1194                 th->len = be16toh(th->len);
 1195         return 0;
 1196 }
 1197 
 1198 /*
 1199  * Perform special action on behalf of the user.
 1200  * Knows about the internals of this device
 1201  */
 1202 static int
 1203 cdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
 1204 {
 1205         struct cd_softc *cd = device_lookup_private(&cd_cd, CDUNIT(dev));
 1206         struct dk_softc *dksc = &cd->sc_dksc;
 1207         struct scsipi_periph *periph = cd->sc_periph;
 1208         struct cd_formatted_toc toc;
 1209         int part = CDPART(dev);
 1210         int error;
 1211 
 1212         SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdioctl 0x%lx ", cmd));
 1213 
 1214         /*
 1215          * If the device is not valid, some IOCTLs can still be
 1216          * handled on the raw partition. Check this here.
 1217          */
 1218         if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0 &&
 1219             part != RAW_PART)
 1220                 return (EIO);
 1221 
 1222         switch (cmd) {
 1223         case DIOCTUR: {
 1224                 /* test unit ready */
 1225                 error = scsipi_test_unit_ready(cd->sc_periph, XS_CTL_SILENT);
 1226                 *((int*)addr) = (error == 0);
 1227                 if (error == ENODEV || error == EIO || error == 0)
 1228                         return 0;                       
 1229                 return error;
 1230         }
 1231         case CDIOCPLAYTRACKS: {
 1232                 /* PLAY_MSF command */
 1233                 struct ioc_play_track *args = addr;
 1234 
 1235                 if ((error = cd_set_pa_immed(cd, 0)) != 0)
 1236                         return (error);
 1237                 return (cd_play_tracks(cd, &toc, args->start_track,
 1238                     args->start_index, args->end_track, args->end_index));
 1239         }
 1240         case CDIOCPLAYMSF: {
 1241                 /* PLAY_MSF command */
 1242                 struct ioc_play_msf *args = addr;
 1243 
 1244                 if ((error = cd_set_pa_immed(cd, 0)) != 0)
 1245                         return (error);
 1246                 return (cd_play_msf(cd, args->start_m, args->start_s,
 1247                     args->start_f, args->end_m, args->end_s, args->end_f));
 1248         }
 1249         case CDIOCPLAYBLOCKS: {
 1250                 /* PLAY command */
 1251                 struct ioc_play_blocks *args = addr;
 1252 
 1253                 if ((error = cd_set_pa_immed(cd, 0)) != 0)
 1254                         return (error);
 1255                 return (cd_play(cd, args->blk, args->len));
 1256         }
 1257         case CDIOCREADSUBCHANNEL: {
 1258                 /* READ_SUBCHANNEL command */
 1259                 struct ioc_read_subchannel *args = addr;
 1260                 struct cd_sub_channel_info data;
 1261                 u_int len = args->data_len;
 1262 
 1263                 if (len > sizeof(data) ||
 1264                     len < sizeof(struct cd_sub_channel_header))
 1265                         return (EINVAL);
 1266                 error = cd_read_subchannel(cd, args->address_format,
 1267                     args->data_format, args->track, &data, len, 0);
 1268                 if (error)
 1269                         return (error);
 1270                 len = uimin(len, _2btol(data.header.data_len) +
 1271                     sizeof(struct cd_sub_channel_header));
 1272                 return (copyout(&data, args->data, len));
 1273         }
 1274         case CDIOCREADSUBCHANNEL_BUF: {
 1275                 /* As CDIOCREADSUBCHANNEL, but without a 2nd buffer area */
 1276                 struct ioc_read_subchannel_buf *args = addr;
 1277                 if (args->req.data_len != sizeof args->info)
 1278                         return EINVAL;
 1279                 return cd_read_subchannel(cd, args->req.address_format,
 1280                     args->req.data_format, args->req.track, &args->info,
 1281                     sizeof(args->info), 0);
 1282         }
 1283         case CDIOREADTOCHEADER: {
 1284                 /* READ TOC format 0 command, static header */
 1285                 if ((error = cd_read_toc(cd, CD_TOC_FORM, 0, 0,
 1286                     &toc, sizeof(toc.header), 0, 0)) != 0)
 1287                         return (error);
 1288                 if (cd->sc_periph->periph_quirks & PQUIRK_LITTLETOC)
 1289                         toc.header.len = le16toh(toc.header.len);
 1290                 else
 1291                         toc.header.len = be16toh(toc.header.len);
 1292                 memcpy(addr, &toc.header, sizeof(toc.header));
 1293                 return (0);
 1294         }
 1295         case CDIOREADTOCENTRYS: {
 1296                 struct ioc_read_toc_entry *te = addr;
 1297                 error = do_cdioreadentries(cd, te, &toc);
 1298                 if (error != 0)
 1299                         return error;
 1300                 return copyout(toc.entries, te->data, uimin(te->data_len,
 1301                     toc.header.len - (sizeof(toc.header.starting_track)
 1302                         + sizeof(toc.header.ending_track))));
 1303         }
 1304         case CDIOREADTOCENTRIES_BUF: {
 1305                 struct ioc_read_toc_entry_buf *te = addr;
 1306                 error = do_cdioreadentries(cd, &te->req, &toc);
 1307                 if (error != 0)
 1308                         return error;
 1309                 memcpy(te->entry, toc.entries, uimin(te->req.data_len,
 1310                     toc.header.len - (sizeof(toc.header.starting_track)
 1311                         + sizeof(toc.header.ending_track))));
 1312                 return 0;
 1313         }
 1314         case CDIOREADMSADDR: {
 1315                 /* READ TOC format 0 command, length of first track only */
 1316                 int sessno = *(int*)addr;
 1317 
 1318                 if (sessno != 0)
 1319                         return (EINVAL);
 1320 
 1321                 return (cdreadmsaddr(cd, &toc, addr));
 1322         }
 1323         case CDIOCSETPATCH: {
 1324                 struct ioc_patch *arg = addr;
 1325 
 1326                 return (cd_setchan(cd, arg->patch[0], arg->patch[1],
 1327                     arg->patch[2], arg->patch[3], 0));
 1328         }
 1329         case CDIOCGETVOL: {
 1330                 /* MODE SENSE command (AUDIO page) */
 1331                 struct ioc_vol *arg = addr;
 1332 
 1333                 return (cd_getvol(cd, arg, 0));
 1334         }
 1335         case CDIOCSETVOL: {
 1336                 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
 1337                 struct ioc_vol *arg = addr;
 1338 
 1339                 return (cd_setvol(cd, arg, 0));
 1340         }
 1341         case CDIOCSETMONO:
 1342                 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
 1343                 return (cd_setchan(cd, BOTH_CHANNEL, BOTH_CHANNEL,
 1344                     MUTE_CHANNEL, MUTE_CHANNEL, 0));
 1345 
 1346         case CDIOCSETSTEREO:
 1347                 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
 1348                 return (cd_setchan(cd, LEFT_CHANNEL, RIGHT_CHANNEL,
 1349                     MUTE_CHANNEL, MUTE_CHANNEL, 0));
 1350 
 1351         case CDIOCSETMUTE:
 1352                 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
 1353                 return (cd_setchan(cd, MUTE_CHANNEL, MUTE_CHANNEL,
 1354                     MUTE_CHANNEL, MUTE_CHANNEL, 0));
 1355 
 1356         case CDIOCSETLEFT:
 1357                 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
 1358                 return (cd_setchan(cd, LEFT_CHANNEL, LEFT_CHANNEL,
 1359                     MUTE_CHANNEL, MUTE_CHANNEL, 0));
 1360 
 1361         case CDIOCSETRIGHT:
 1362                 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
 1363                 return (cd_setchan(cd, RIGHT_CHANNEL, RIGHT_CHANNEL,
 1364                     MUTE_CHANNEL, MUTE_CHANNEL, 0));
 1365 
 1366         case CDIOCRESUME:
 1367                 /* PAUSE command */
 1368                 return (cd_pause(cd, PA_RESUME));
 1369         case CDIOCPAUSE:
 1370                 /* PAUSE command */
 1371                 return (cd_pause(cd, PA_PAUSE));
 1372         case CDIOCSTART:
 1373                 return (scsipi_start(periph, SSS_START, 0));
 1374         case CDIOCSTOP:
 1375                 return (scsipi_start(periph, SSS_STOP, 0));
 1376         case CDIOCCLOSE:
 1377                 return (scsipi_start(periph, SSS_START|SSS_LOEJ,
 1378                     XS_CTL_IGNORE_NOT_READY | XS_CTL_IGNORE_MEDIA_CHANGE));
 1379         case DIOCEJECT:
 1380                 if (*(int *)addr == 0) {
 1381                         int pmask = __BIT(part);
 1382                         /*
 1383                          * Don't force eject: check that we are the only
 1384                          * partition open. If so, unlock it.
 1385                          */
 1386                         if (DK_BUSY(dksc, pmask) == 0) {
 1387                                 error = scsipi_prevent(periph, SPAMR_ALLOW,
 1388                                     XS_CTL_IGNORE_NOT_READY);
 1389                                 if (error)
 1390                                         return (error);
 1391                         } else {
 1392                                 return (EBUSY);
 1393                         }
 1394                 }
 1395                 /* FALLTHROUGH */
 1396         case CDIOCEJECT: /* FALLTHROUGH */
 1397         case ODIOCEJECT:
 1398                 error = scsipi_start(periph, SSS_STOP|SSS_LOEJ, 0);
 1399                 if (error == 0)
 1400                         /* Make sure cdclose() will do silent operations */
 1401                         cd->flags |= CDF_EJECTED;
 1402                 return error;
 1403         case DIOCCACHESYNC:
 1404                 /* SYNCHRONISE CACHES command */
 1405                 return (cdcachesync(periph, 0));
 1406         case CDIOCALLOW:
 1407                 return (scsipi_prevent(periph, SPAMR_ALLOW, 0));
 1408         case CDIOCPREVENT:
 1409                 return (scsipi_prevent(periph, SPAMR_PREVENT_DT, 0));
 1410         case DIOCLOCK:
 1411                 return (scsipi_prevent(periph,
 1412                     (*(int *)addr) ? SPAMR_PREVENT_DT : SPAMR_ALLOW, 0));
 1413         case CDIOCSETDEBUG:
 1414                 cd->sc_periph->periph_dbflags |= (SCSIPI_DB1 | SCSIPI_DB2);
 1415                 return (0);
 1416         case CDIOCCLRDEBUG:
 1417                 cd->sc_periph->periph_dbflags &= ~(SCSIPI_DB1 | SCSIPI_DB2);
 1418                 return (0);
 1419         case CDIOCRESET:
 1420         case SCIOCRESET:
 1421                 return (cd_reset(cd));
 1422         case CDIOCLOADUNLOAD:
 1423                 /* LOAD_UNLOAD command */
 1424                 return (cd_load_unload(cd, addr));
 1425         case DVD_AUTH:
 1426                 /* GPCMD_REPORT_KEY or GPCMD_SEND_KEY command */
 1427                 return (dvd_auth(cd, addr));
 1428         case DVD_READ_STRUCT:
 1429                 /* GPCMD_READ_DVD_STRUCTURE command */
 1430                 return (dvd_read_struct(cd, addr));
 1431         case MMCGETDISCINFO:
 1432                 /*
 1433                  * GET_CONFIGURATION, READ_DISCINFO, READ_TRACKINFO,
 1434                  * (READ_TOCf2, READ_CD_CAPACITY and GET_CONFIGURATION) commands
 1435                  */
 1436                 return mmc_getdiscinfo(periph, (struct mmc_discinfo *) addr);
 1437         case MMCGETTRACKINFO:
 1438                 /* READ TOCf2, READ_CD_CAPACITY and READ_TRACKINFO commands */
 1439                 return mmc_gettrackinfo(periph, (struct mmc_trackinfo *) addr);
 1440         case MMCOP:
 1441                 /*
 1442                  * CLOSE TRACK/SESSION, RESERVE_TRACK, REPAIR_TRACK,
 1443                  * SYNCHRONISE_CACHE commands
 1444                  */
 1445                 return mmc_do_op(periph, (struct mmc_op *) addr);
 1446         case MMCSETUPWRITEPARAMS :
 1447                 /* MODE SENSE page 5, MODE_SELECT page 5 commands */
 1448                 return mmc_setup_writeparams(periph, (struct mmc_writeparams *) addr);
 1449         default:
 1450                 error = dk_ioctl(dksc, dev, cmd, addr, flag, l); 
 1451                 if (error == ENOTTY)
 1452                         error = scsipi_do_ioctl(periph, dev, cmd, addr, flag, l);
 1453                 return (error);
 1454         }
 1455 
 1456 #ifdef DIAGNOSTIC
 1457         panic("cdioctl: impossible");
 1458 #endif
 1459 }
 1460 
 1461 static void
 1462 cd_label(device_t self, struct disklabel *lp)
 1463 {
 1464         struct cd_softc *cd = device_private(self);
 1465         struct scsipi_periph *periph = cd->sc_periph;
 1466         struct cd_formatted_toc toc;
 1467         int lastsession = 0;
 1468 
 1469         strncpy(lp->d_typename, "optical media", 16);
 1470         lp->d_rpm = 300;
 1471         lp->d_flags |= D_REMOVABLE;
 1472 
 1473         if ((periph->periph_flags & PERIPH_MEDIA_LOADED) != 0) {
 1474                 lp->d_flags |= D_SCSI_MMC;
 1475                 (void) cdreadmsaddr(cd, &toc, &lastsession);
 1476         }
 1477 
 1478         lp->d_partitions[0].p_offset = 0;
 1479         lp->d_partitions[0].p_size = lp->d_secperunit;
 1480         lp->d_partitions[0].p_cdsession = lastsession;
 1481         lp->d_partitions[0].p_fstype = FS_ISO9660;
 1482 
 1483         lp->d_partitions[RAW_PART].p_offset = 0;
 1484         lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
 1485         lp->d_partitions[RAW_PART].p_fstype = FS_UDF;
 1486 }
 1487 
 1488 /*
 1489  * Reading a disc's total capacity is apparently a very difficult issue for the
 1490  * SCSI standardisation group. Every disc type seems to have its own
 1491  * (re)invented size request method and modifiers. The failsafe way of
 1492  * determining the total (max) capacity i.e. not the recorded capacity but the
 1493  * total maximum capacity is to request the info on the last track and
 1494  * calculate the last lba.
 1495  *
 1496  * For ROM drives, we go for the CD recorded capacity. For recordable devices
 1497  * we count.
 1498  */
 1499 static int
 1500 read_cd_capacity(struct scsipi_periph *periph, uint32_t *blksize, u_long *last_lba)
 1501 {
 1502         struct scsipi_read_cd_capacity    cap_cmd;
 1503         /*
 1504          * XXX: see PR 48550 and PR 48754:
 1505          * the ahcisata(4) driver can not deal with unaligned
 1506          * data, so align this "a bit"
 1507          */
 1508         struct scsipi_read_cd_cap_data    cap __aligned(2);
 1509         struct scsipi_read_discinfo       di_cmd;
 1510         struct scsipi_read_discinfo_data  di __aligned(2);
 1511         struct scsipi_read_trackinfo      ti_cmd;
 1512         struct scsipi_read_trackinfo_data ti __aligned(2);
 1513         uint32_t track_start, track_size;
 1514         int error, flags, msb, lsb, last_track;
 1515 
 1516         /* if the device doesn't grok capacity, return the dummies */
 1517         if (periph->periph_quirks & PQUIRK_NOCAPACITY)
 1518                 return 0;
 1519 
 1520         /* first try read CD capacity for blksize and last recorded lba */
 1521         /* issue the cd capacity request */
 1522         flags = XS_CTL_DATA_IN;
 1523         memset(&cap_cmd, 0, sizeof(cap_cmd));
 1524         memset(&cap, 0, sizeof(cap));
 1525         cap_cmd.opcode = READ_CD_CAPACITY;
 1526 
 1527         error = scsipi_command(periph,
 1528             (void *) &cap_cmd, sizeof(cap_cmd),
 1529             (void *) &cap,     sizeof(cap),
 1530             CDRETRIES, 30000, NULL, flags);
 1531         if (error)
 1532                 return error;
 1533 
 1534         /* retrieve values and sanity check them */
 1535         *blksize  = _4btol(cap.length);
 1536         *last_lba = _4btol(cap.addr);
 1537 
 1538         /* blksize is 2048 for CD, but some drives give gibberish */
 1539         if ((*blksize < 512) || ((*blksize & 511) != 0)
 1540             || (*blksize > 16*1024)) {
 1541                 if (*blksize > 16*1024)
 1542                         aprint_error("read_cd_capacity: extra large block "
 1543                             "size %u found - limiting to 2kByte\n",
 1544                             *blksize);
 1545                 *blksize = 2048;        /* some drives lie ! */
 1546         }
 1547 
 1548         /* recordables have READ_DISCINFO implemented */
 1549         flags = XS_CTL_DATA_IN | XS_CTL_SILENT;
 1550         memset(&di_cmd, 0, sizeof(di_cmd));
 1551         di_cmd.opcode = READ_DISCINFO;
 1552         _lto2b(READ_DISCINFO_BIGSIZE, di_cmd.data_len);
 1553 
 1554         error = scsipi_command(periph,
 1555             (void *) &di_cmd,  sizeof(di_cmd),
 1556             (void *) &di,      READ_DISCINFO_BIGSIZE,
 1557             CDRETRIES, 30000, NULL, flags);
 1558         if (error == 0) {
 1559                 msb = di.last_track_last_session_msb;
 1560                 lsb = di.last_track_last_session_lsb;
 1561                 last_track = (msb << 8) | lsb;
 1562 
 1563                 /* request info on last track */
 1564                 memset(&ti_cmd, 0, sizeof(ti_cmd));
 1565                 ti_cmd.opcode = READ_TRACKINFO;
 1566                 ti_cmd.addr_type = 1;                   /* on tracknr */
 1567                 _lto4b(last_track, ti_cmd.address);     /* tracknr    */
 1568                 _lto2b(sizeof(ti), ti_cmd.data_len);
 1569 
 1570                 error = scsipi_command(periph,
 1571                     (void *) &ti_cmd,  sizeof(ti_cmd),
 1572                     (void *) &ti,      sizeof(ti),
 1573                     CDRETRIES, 30000, NULL, flags);
 1574                 if (error == 0) {
 1575                         track_start = _4btol(ti.track_start);
 1576                         track_size  = _4btol(ti.track_size);
 1577 
 1578                         /* overwrite only with a sane value */
 1579                         if (track_start + track_size >= 100)
 1580                                 *last_lba = (u_long) track_start + track_size -1;
 1581                 }
 1582         }
 1583 
 1584         /* sanity check for lba_size */
 1585         if (*last_lba < 100)
 1586                 *last_lba = 400000-1;
 1587 
 1588         return 0;
 1589 }
 1590 
 1591 /*
 1592  * Find out from the device what its capacity is
 1593  */
 1594 static u_long
 1595 cd_size(struct cd_softc *cd, int flags)
 1596 {
 1597         uint32_t blksize = 2048;
 1598         u_long last_lba = 0, size;
 1599         int error;
 1600 
 1601         error = read_cd_capacity(cd->sc_periph, &blksize, &last_lba);
 1602         if (error)
 1603                 goto error;
 1604 
 1605         if (blksize != 2048) {
 1606                 if (cd_setblksize(cd) == 0) {
 1607                         blksize = 2048;
 1608                         error = read_cd_capacity(cd->sc_periph,
 1609                             &blksize, &last_lba);
 1610                         if (error)
 1611                                 goto error;
 1612                 }
 1613         }
 1614 
 1615         size = last_lba + 1;
 1616         cd->params.blksize     = blksize;
 1617         cd->params.disksize    = size;
 1618         cd->params.disksize512 = ((u_int64_t)cd->params.disksize * blksize) / DEV_BSIZE;
 1619 
 1620         SC_DEBUG(cd->sc_periph, SCSIPI_DB2,
 1621             ("cd_size: %u %lu\n", blksize, size));
 1622 
 1623         return size;
 1624 
 1625 error:
 1626         /* something went wrong */
 1627         cd->params.blksize     = 2048;
 1628         cd->params.disksize    = 0;
 1629         cd->params.disksize512 = 0;
 1630 
 1631         SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cd_size: failed\n"));
 1632 
 1633         return 0;
 1634 }
 1635 
 1636 /*
 1637  * Get scsi driver to send a "start playing" command
 1638  */
 1639 static int
 1640 cd_play(struct cd_softc *cd, int blkno, int nblks)
 1641 {
 1642         struct scsipi_play cmd;
 1643 
 1644         memset(&cmd, 0, sizeof(cmd));
 1645         cmd.opcode = PLAY;
 1646         _lto4b(blkno, cmd.blk_addr);
 1647         _lto2b(nblks, cmd.xfer_len);
 1648 
 1649         return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
 1650             CDRETRIES, 30000, NULL, 0));
 1651 }
 1652 
 1653 /*
 1654  * Get scsi driver to send a "start playing" command
 1655  */
 1656 static int
 1657 cd_play_tracks(struct cd_softc *cd, struct cd_formatted_toc *toc, int strack,
 1658     int sindex, int etrack, int eindex)
 1659 {
 1660         int error;
 1661 
 1662         if (!etrack)
 1663                 return (EIO);
 1664         if (strack > etrack)
 1665                 return (EINVAL);
 1666 
 1667         error = cd_load_toc(cd, CD_TOC_FORM, toc, 0);
 1668         if (error)
 1669                 return (error);
 1670 
 1671         if (++etrack > (toc->header.ending_track+1))
 1672                 etrack = toc->header.ending_track+1;
 1673 
 1674         strack -= toc->header.starting_track;
 1675         etrack -= toc->header.starting_track;
 1676         if (strack < 0)
 1677                 return (EINVAL);
 1678 
 1679         return (cd_play_msf(cd, toc->entries[strack].addr.msf.minute,
 1680             toc->entries[strack].addr.msf.second,
 1681             toc->entries[strack].addr.msf.frame,
 1682             toc->entries[etrack].addr.msf.minute,
 1683             toc->entries[etrack].addr.msf.second,
 1684             toc->entries[etrack].addr.msf.frame));
 1685 }
 1686 
 1687 /*
 1688  * Get scsi driver to send a "play msf" command
 1689  */
 1690 static int
 1691 cd_play_msf(struct cd_softc *cd, int startm, int starts, int startf, int endm,
 1692     int ends, int endf)
 1693 {
 1694         struct scsipi_play_msf cmd;
 1695 
 1696         memset(&cmd, 0, sizeof(cmd));
 1697         cmd.opcode = PLAY_MSF;
 1698         cmd.start_m = startm;
 1699         cmd.start_s = starts;
 1700         cmd.start_f = startf;
 1701         cmd.end_m = endm;
 1702         cmd.end_s = ends;
 1703         cmd.end_f = endf;
 1704 
 1705         return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
 1706             CDRETRIES, 30000, NULL, 0));
 1707 }
 1708 
 1709 /*
 1710  * Get scsi driver to send a "start up" command
 1711  */
 1712 static int
 1713 cd_pause(struct cd_softc *cd, int go)
 1714 {
 1715         struct scsipi_pause cmd;
 1716 
 1717         memset(&cmd, 0, sizeof(cmd));
 1718         cmd.opcode = PAUSE;
 1719         cmd.resume = go & 0xff;
 1720 
 1721         return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
 1722             CDRETRIES, 30000, NULL, 0));
 1723 }
 1724 
 1725 /*
 1726  * Get scsi driver to send a "RESET" command
 1727  */
 1728 static int
 1729 cd_reset(struct cd_softc *cd)
 1730 {
 1731 
 1732         return (scsipi_command(cd->sc_periph, 0, 0, 0, 0,
 1733             CDRETRIES, 30000, NULL, XS_CTL_RESET));
 1734 }
 1735 
 1736 /*
 1737  * Read subchannel
 1738  */
 1739 static int
 1740 cd_read_subchannel(struct cd_softc *cd, int mode, int format, int track,
 1741     struct cd_sub_channel_info *data, int len, int flags)
 1742 {
 1743         struct scsipi_read_subchannel cmd;
 1744 
 1745         memset(&cmd, 0, sizeof(cmd));
 1746         cmd.opcode = READ_SUBCHANNEL;
 1747         if (mode == CD_MSF_FORMAT)
 1748                 cmd.byte2 |= CD_MSF;
 1749         cmd.byte3 = SRS_SUBQ;
 1750         cmd.subchan_format = format;
 1751         cmd.track = track;
 1752         _lto2b(len, cmd.data_len);
 1753 
 1754         return (scsipi_command(cd->sc_periph,
 1755             (void *)&cmd, sizeof(struct scsipi_read_subchannel),
 1756             (void *)data, len,
 1757             CDRETRIES, 30000, NULL, flags | XS_CTL_DATA_IN | XS_CTL_SILENT));
 1758 }
 1759 
 1760 /*
 1761  * Read table of contents
 1762  */
 1763 static int
 1764 cd_read_toc(struct cd_softc *cd, int respf, int mode, int start,
 1765     struct cd_formatted_toc *toc, int len, int flags, int control)
 1766 {
 1767         struct scsipi_read_toc cmd;
 1768         int ntoc;
 1769 
 1770         memset(&cmd, 0, sizeof(cmd));
 1771 #if 0
 1772         if (len != sizeof(struct ioc_toc_header))
 1773                 ntoc = ((len) - sizeof(struct ioc_toc_header)) /
 1774                     sizeof(struct cd_toc_entry);
 1775         else
 1776 #endif
 1777         ntoc = len;
 1778         cmd.opcode = READ_TOC;
 1779         if (mode == CD_MSF_FORMAT)
 1780                 cmd.addr_mode |= CD_MSF;
 1781         cmd.resp_format = respf;
 1782         cmd.from_track = start;
 1783         _lto2b(ntoc, cmd.data_len);
 1784         cmd.control = control;
 1785 
 1786         return (scsipi_command(cd->sc_periph,
 1787             (void *)&cmd, sizeof(cmd), (void *)toc, len, CDRETRIES,
 1788             30000, NULL, flags | XS_CTL_DATA_IN));
 1789 }
 1790 
 1791 static int
 1792 cd_load_toc(struct cd_softc *cd, int respf, struct cd_formatted_toc *toc, int flags)
 1793 {
 1794         int ntracks, len, error;
 1795 
 1796         if ((error = cd_read_toc(cd, respf, 0, 0, toc, sizeof(toc->header),
 1797             flags, 0)) != 0)
 1798                 return (error);
 1799 
 1800         ntracks = toc->header.ending_track - toc->header.starting_track + 1;
 1801         len = (ntracks + 1) * sizeof(struct cd_toc_entry) +
 1802             sizeof(toc->header);
 1803         if ((error = cd_read_toc(cd, respf, CD_MSF_FORMAT, 0, toc, len,
 1804             flags, 0)) != 0)
 1805                 return (error);
 1806         return (0);
 1807 }
 1808 
 1809 /*
 1810  * Get the scsi driver to send a full inquiry to the device and use the
 1811  * results to fill out the disk parameter structure.
 1812  */
 1813 static int
 1814 cd_get_parms(struct cd_softc *cd, int flags)
 1815 {
 1816 
 1817         /*
 1818          * give a number of sectors so that sec * trks * cyls
 1819          * is <= disk_size
 1820          */
 1821         if (cd_size(cd, flags) == 0)
 1822                 return (ENXIO);
 1823         return (0);
 1824 }
 1825 
 1826 static int
 1827 cdsize(dev_t dev)
 1828 {
 1829 
 1830         /* CD-ROMs are read-only. */
 1831         return (-1);
 1832 }
 1833 
 1834 static int
 1835 cddump(dev_t dev, daddr_t blkno, void *va, size_t size)
 1836 {
 1837 
 1838         /* Not implemented. */
 1839         return (ENXIO);
 1840 }
 1841 
 1842 #define dvd_copy_key(dst, src)          memcpy((dst), (src), sizeof(dvd_key))
 1843 #define dvd_copy_challenge(dst, src)    memcpy((dst), (src), sizeof(dvd_challenge))
 1844 
 1845 static int
 1846 dvd_auth(struct cd_softc *cd, dvd_authinfo *a)
 1847 {
 1848         struct scsipi_generic cmd;
 1849         u_int8_t bf[20];
 1850         int error;
 1851 
 1852         memset(cmd.bytes, 0, 15);
 1853         memset(bf, 0, sizeof(bf));
 1854 
 1855         switch (a->type) {
 1856         case DVD_LU_SEND_AGID:
 1857                 cmd.opcode = GPCMD_REPORT_KEY;
 1858                 cmd.bytes[8] = 8;
 1859                 cmd.bytes[9] = 0 | (0 << 6);
 1860                 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 8,
 1861                     CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 1862                 if (error)
 1863                         return (error);
 1864                 a->lsa.agid = bf[7] >> 6;
 1865                 return (0);
 1866 
 1867         case DVD_LU_SEND_CHALLENGE:
 1868                 cmd.opcode = GPCMD_REPORT_KEY;
 1869                 cmd.bytes[8] = 16;
 1870                 cmd.bytes[9] = 1 | (a->lsc.agid << 6);
 1871                 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 16,
 1872                     CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 1873                 if (error)
 1874                         return (error);
 1875                 dvd_copy_challenge(a->lsc.chal, &bf[4]);
 1876                 return (0);
 1877 
 1878         case DVD_LU_SEND_KEY1:
 1879                 cmd.opcode = GPCMD_REPORT_KEY;
 1880                 cmd.bytes[8] = 12;
 1881                 cmd.bytes[9] = 2 | (a->lsk.agid << 6);
 1882                 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 12,
 1883                     CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 1884                 if (error)
 1885                         return (error);
 1886                 dvd_copy_key(a->lsk.key, &bf[4]);
 1887                 return (0);
 1888 
 1889         case DVD_LU_SEND_TITLE_KEY:
 1890                 cmd.opcode = GPCMD_REPORT_KEY;
 1891                 _lto4b(a->lstk.lba, &cmd.bytes[1]);
 1892                 cmd.bytes[8] = 12;
 1893                 cmd.bytes[9] = 4 | (a->lstk.agid << 6);
 1894                 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 12,
 1895                     CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 1896                 if (error)
 1897                         return (error);
 1898                 a->lstk.cpm = (bf[4] >> 7) & 1;
 1899                 a->lstk.cp_sec = (bf[4] >> 6) & 1;
 1900                 a->lstk.cgms = (bf[4] >> 4) & 3;
 1901                 dvd_copy_key(a->lstk.title_key, &bf[5]);
 1902                 return (0);
 1903 
 1904         case DVD_LU_SEND_ASF:
 1905                 cmd.opcode = GPCMD_REPORT_KEY;
 1906                 cmd.bytes[8] = 8;
 1907                 cmd.bytes[9] = 5 | (a->lsasf.agid << 6);
 1908                 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 8,
 1909                     CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 1910                 if (error)
 1911                         return (error);
 1912                 a->lsasf.asf = bf[7] & 1;
 1913                 return (0);
 1914 
 1915         case DVD_HOST_SEND_CHALLENGE:
 1916                 cmd.opcode = GPCMD_SEND_KEY;
 1917                 cmd.bytes[8] = 16;
 1918                 cmd.bytes[9] = 1 | (a->hsc.agid << 6);
 1919                 bf[1] = 14;
 1920                 dvd_copy_challenge(&bf[4], a->hsc.chal);
 1921                 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 16,
 1922                     CDRETRIES, 30000, NULL, XS_CTL_DATA_OUT);
 1923                 if (error)
 1924                         return (error);
 1925                 a->type = DVD_LU_SEND_KEY1;
 1926                 return (0);
 1927 
 1928         case DVD_HOST_SEND_KEY2:
 1929                 cmd.opcode = GPCMD_SEND_KEY;
 1930                 cmd.bytes[8] = 12;
 1931                 cmd.bytes[9] = 3 | (a->hsk.agid << 6);
 1932                 bf[1] = 10;
 1933                 dvd_copy_key(&bf[4], a->hsk.key);
 1934                 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 12,
 1935                     CDRETRIES, 30000, NULL, XS_CTL_DATA_OUT);
 1936                 if (error) {
 1937                         a->type = DVD_AUTH_FAILURE;
 1938                         return (error);
 1939                 }
 1940                 a->type = DVD_AUTH_ESTABLISHED;
 1941                 return (0);
 1942 
 1943         case DVD_INVALIDATE_AGID:
 1944                 cmd.opcode = GPCMD_REPORT_KEY;
 1945                 cmd.bytes[9] = 0x3f | (a->lsa.agid << 6);
 1946                 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 16,
 1947                     CDRETRIES, 30000, NULL, 0);
 1948                 if (error)
 1949                         return (error);
 1950                 return (0);
 1951 
 1952         case DVD_LU_SEND_RPC_STATE:
 1953                 cmd.opcode = GPCMD_REPORT_KEY;
 1954                 cmd.bytes[8] = 8;
 1955                 cmd.bytes[9] = 8 | (0 << 6);
 1956                 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 8,
 1957                     CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 1958                 if (error)
 1959                         return (error);
 1960                 a->lrpcs.type = (bf[4] >> 6) & 3;
 1961                 a->lrpcs.vra = (bf[4] >> 3) & 7;
 1962                 a->lrpcs.ucca = (bf[4]) & 7;
 1963                 a->lrpcs.region_mask = bf[5];
 1964                 a->lrpcs.rpc_scheme = bf[6];
 1965                 return (0);
 1966 
 1967         case DVD_HOST_SEND_RPC_STATE:
 1968                 cmd.opcode = GPCMD_SEND_KEY;
 1969                 cmd.bytes[8] = 8;
 1970                 cmd.bytes[9] = 6 | (0 << 6);
 1971                 bf[1] = 6;
 1972                 bf[4] = a->hrpcs.pdrc;
 1973                 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 8,
 1974                     CDRETRIES, 30000, NULL, XS_CTL_DATA_OUT);
 1975                 if (error)
 1976                         return (error);
 1977                 return (0);
 1978 
 1979         default:
 1980                 return (ENOTTY);
 1981         }
 1982 }
 1983 
 1984 static int
 1985 dvd_read_physical(struct cd_softc *cd, dvd_struct *s)
 1986 {
 1987         struct scsipi_generic cmd;
 1988         u_int8_t bf[4 + 4 * 20], *bufp;
 1989         int error;
 1990         struct dvd_layer *layer;
 1991         int i;
 1992 
 1993         memset(cmd.bytes, 0, 15);
 1994         memset(bf, 0, sizeof(bf));
 1995         cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
 1996         cmd.bytes[6] = s->type;
 1997         _lto2b(sizeof(bf), &cmd.bytes[7]);
 1998 
 1999         cmd.bytes[5] = s->physical.layer_num;
 2000         error = scsipi_command(cd->sc_periph, &cmd, 12, bf, sizeof(bf),
 2001             CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 2002         if (error)
 2003                 return (error);
 2004         for (i = 0, bufp = &bf[4], layer = &s->physical.layer[0]; i < 4;
 2005              i++, bufp += 20, layer++) {
 2006                 memset(layer, 0, sizeof(*layer));
 2007                 layer->book_version = bufp[0] & 0xf;
 2008                 layer->book_type = bufp[0] >> 4;
 2009                 layer->min_rate = bufp[1] & 0xf;
 2010                 layer->disc_size = bufp[1] >> 4;
 2011                 layer->layer_type = bufp[2] & 0xf;
 2012                 layer->track_path = (bufp[2] >> 4) & 1;
 2013                 layer->nlayers = (bufp[2] >> 5) & 3;
 2014                 layer->track_density = bufp[3] & 0xf;
 2015                 layer->linear_density = bufp[3] >> 4;
 2016                 layer->start_sector = _4btol(&bufp[4]);
 2017                 layer->end_sector = _4btol(&bufp[8]);
 2018                 layer->end_sector_l0 = _4btol(&bufp[12]);
 2019                 layer->bca = bufp[16] >> 7;
 2020         }
 2021         return (0);
 2022 }
 2023 
 2024 static int
 2025 dvd_read_copyright(struct cd_softc *cd, dvd_struct *s)
 2026 {
 2027         struct scsipi_generic cmd;
 2028         u_int8_t bf[8];
 2029         int error;
 2030 
 2031         memset(cmd.bytes, 0, 15);
 2032         memset(bf, 0, sizeof(bf));
 2033         cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
 2034         cmd.bytes[6] = s->type;
 2035         _lto2b(sizeof(bf), &cmd.bytes[7]);
 2036 
 2037         cmd.bytes[5] = s->copyright.layer_num;
 2038         error = scsipi_command(cd->sc_periph, &cmd, 12, bf, sizeof(bf),
 2039             CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 2040         if (error)
 2041                 return (error);
 2042         s->copyright.cpst = bf[4];
 2043         s->copyright.rmi = bf[5];
 2044         return (0);
 2045 }
 2046 
 2047 static int
 2048 dvd_read_disckey(struct cd_softc *cd, dvd_struct *s)
 2049 {
 2050         struct scsipi_generic cmd;
 2051         u_int8_t *bf;
 2052         int error;
 2053 
 2054         bf = malloc(4 + 2048, M_TEMP, M_WAITOK|M_ZERO);
 2055         if (bf == NULL)
 2056                 return EIO;
 2057         memset(cmd.bytes, 0, 15);
 2058         cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
 2059         cmd.bytes[6] = s->type;
 2060         _lto2b(4 + 2048, &cmd.bytes[7]);
 2061 
 2062         cmd.bytes[9] = s->disckey.agid << 6;
 2063         error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 4 + 2048,
 2064             CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 2065         if (error == 0)
 2066                 memcpy(s->disckey.value, &bf[4], 2048);
 2067         free(bf, M_TEMP);
 2068         return error;
 2069 }
 2070 
 2071 static int
 2072 dvd_read_bca(struct cd_softc *cd, dvd_struct *s)
 2073 {
 2074         struct scsipi_generic cmd;
 2075         u_int8_t bf[4 + 188];
 2076         int error;
 2077 
 2078         memset(cmd.bytes, 0, 15);
 2079         memset(bf, 0, sizeof(bf));
 2080         cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
 2081         cmd.bytes[6] = s->type;
 2082         _lto2b(sizeof(bf), &cmd.bytes[7]);
 2083 
 2084         error = scsipi_command(cd->sc_periph, &cmd, 12, bf, sizeof(bf),
 2085             CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 2086         if (error)
 2087                 return (error);
 2088         s->bca.len = _2btol(&bf[0]);
 2089         if (s->bca.len < 12 || s->bca.len > 188)
 2090                 return (EIO);
 2091         memcpy(s->bca.value, &bf[4], s->bca.len);
 2092         return (0);
 2093 }
 2094 
 2095 static int
 2096 dvd_read_manufact(struct cd_softc *cd, dvd_struct *s)
 2097 {
 2098         struct scsipi_generic cmd;
 2099         u_int8_t *bf;
 2100         int error;
 2101 
 2102         bf = malloc(4 + 2048, M_TEMP, M_WAITOK|M_ZERO);
 2103         if (bf == NULL)
 2104                 return (EIO);
 2105         memset(cmd.bytes, 0, 15);
 2106         cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
 2107         cmd.bytes[6] = s->type;
 2108         _lto2b(4 + 2048, &cmd.bytes[7]);
 2109 
 2110         error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 4 + 2048,
 2111             CDRETRIES, 30000, NULL, XS_CTL_DATA_IN);
 2112         if (error == 0) {
 2113                 s->manufact.len = _2btol(&bf[0]);
 2114                 if (s->manufact.len >= 0 && s->manufact.len <= 2048)
 2115                         memcpy(s->manufact.value, &bf[4], s->manufact.len);
 2116                 else
 2117                         error = EIO;
 2118         }
 2119         free(bf, M_TEMP);
 2120         return error;
 2121 }
 2122 
 2123 static int
 2124 dvd_read_struct(struct cd_softc *cd, dvd_struct *s)
 2125 {
 2126 
 2127         switch (s->type) {
 2128         case DVD_STRUCT_PHYSICAL:
 2129                 return (dvd_read_physical(cd, s));
 2130         case DVD_STRUCT_COPYRIGHT:
 2131                 return (dvd_read_copyright(cd, s));
 2132         case DVD_STRUCT_DISCKEY:
 2133                 return (dvd_read_disckey(cd, s));
 2134         case DVD_STRUCT_BCA:
 2135                 return (dvd_read_bca(cd, s));
 2136         case DVD_STRUCT_MANUFACT:
 2137                 return (dvd_read_manufact(cd, s));
 2138         default:
 2139                 return (EINVAL);
 2140         }
 2141 }
 2142 
 2143 static int
 2144 cd_mode_sense(struct cd_softc *cd, u_int8_t byte2, void *sense, size_t size,
 2145     int page, int flags, int *big)
 2146 {
 2147 
 2148         if (cd->sc_periph->periph_quirks & PQUIRK_ONLYBIG) {
 2149                 *big = 1;
 2150                 return scsipi_mode_sense_big(cd->sc_periph, byte2, page, sense,
 2151                     size + sizeof(struct scsi_mode_parameter_header_10),
 2152                     flags, CDRETRIES, 20000);
 2153         } else {
 2154                 *big = 0;
 2155                 return scsipi_mode_sense(cd->sc_periph, byte2, page, sense,
 2156                     size + sizeof(struct scsi_mode_parameter_header_6),
 2157                     flags, CDRETRIES, 20000);
 2158         }
 2159 }
 2160 
 2161 static int
 2162 cd_mode_select(struct cd_softc *cd, u_int8_t byte2, void *sense, size_t size,
 2163     int flags, int big)
 2164 {
 2165 
 2166         if (big) {
 2167                 struct scsi_mode_parameter_header_10 *header = sense;
 2168 
 2169                 _lto2b(0, header->data_length);
 2170                 return scsipi_mode_select_big(cd->sc_periph, byte2, sense,
 2171                     size + sizeof(struct scsi_mode_parameter_header_10),
 2172                     flags, CDRETRIES, 20000);
 2173         } else {
 2174                 struct scsi_mode_parameter_header_6 *header = sense;
 2175 
 2176                 header->data_length = 0;
 2177                 return scsipi_mode_select(cd->sc_periph, byte2, sense,
 2178                     size + sizeof(struct scsi_mode_parameter_header_6),
 2179                     flags, CDRETRIES, 20000);
 2180         }
 2181 }
 2182 
 2183 static int
 2184 cd_set_pa_immed(struct cd_softc *cd, int flags)
 2185 {
 2186         struct {
 2187                 union {
 2188                         struct scsi_mode_parameter_header_6 small;
 2189                         struct scsi_mode_parameter_header_10 big;
 2190                 } header;
 2191                 struct cd_audio_page page;
 2192         } data;
 2193         int error;
 2194         uint8_t oflags;
 2195         int big, byte2;
 2196         struct cd_audio_page *page;
 2197 
 2198         byte2 = SMS_DBD;
 2199 try_again:
 2200         if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page),
 2201             AUDIO_PAGE, flags, &big)) != 0) {
 2202                 if (byte2 == SMS_DBD) {
 2203                         /* Device may not understand DBD; retry without */
 2204                         byte2 = 0;
 2205                         goto try_again;
 2206                 }
 2207                 return (error);
 2208         }
 2209 
 2210         if (big)
 2211                 page = (void *)((u_long)&data.header.big +
 2212                                 sizeof data.header.big +
 2213                                 _2btol(data.header.big.blk_desc_len));
 2214         else
 2215                 page = (void *)((u_long)&data.header.small +
 2216                                 sizeof data.header.small +
 2217                                 data.header.small.blk_desc_len);
 2218 
 2219         oflags = page->flags;
 2220         page->flags &= ~CD_PA_SOTC;
 2221         page->flags |= CD_PA_IMMED;
 2222         if (oflags == page->flags)
 2223                 return (0);
 2224 
 2225         return (cd_mode_select(cd, SMS_PF, &data,
 2226             sizeof(struct scsi_mode_page_header) + page->pg_length,
 2227             flags, big));
 2228 }
 2229 
 2230 static int
 2231 cd_setchan(struct cd_softc *cd, int p0, int p1, int p2, int p3, int flags)
 2232 {
 2233         struct {
 2234                 union {
 2235                         struct scsi_mode_parameter_header_6 small;
 2236                         struct scsi_mode_parameter_header_10 big;
 2237                 } header;
 2238                 struct cd_audio_page page;
 2239         } data;
 2240         int error;
 2241         int big, byte2;
 2242         struct cd_audio_page *page;
 2243 
 2244         byte2 = SMS_DBD;
 2245 try_again:
 2246         if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page),
 2247             AUDIO_PAGE, flags, &big)) != 0) {
 2248                 if (byte2 == SMS_DBD) {
 2249                         /* Device may not understand DBD; retry without */
 2250                         byte2 = 0;
 2251                         goto try_again;
 2252                 }
 2253                 return (error);
 2254         }
 2255 
 2256         if (big)
 2257                 page = (void *)((u_long)&data.header.big +
 2258                                 sizeof data.header.big +
 2259                                 _2btol(data.header.big.blk_desc_len));
 2260         else
 2261                 page = (void *)((u_long)&data.header.small +
 2262                                 sizeof data.header.small +
 2263                                 data.header.small.blk_desc_len);
 2264 
 2265         page->port[0].channels = p0;
 2266         page->port[1].channels = p1;
 2267         page->port[2].channels = p2;
 2268         page->port[3].channels = p3;
 2269 
 2270         return (cd_mode_select(cd, SMS_PF, &data,
 2271             sizeof(struct scsi_mode_page_header) + page->pg_length,
 2272             flags, big));
 2273 }
 2274 
 2275 static int
 2276 cd_getvol(struct cd_softc *cd, struct ioc_vol *arg, int flags)
 2277 {
 2278         struct {
 2279                 union {
 2280                         struct scsi_mode_parameter_header_6 small;
 2281                         struct scsi_mode_parameter_header_10 big;
 2282                 } header;
 2283                 struct cd_audio_page page;
 2284         } data;
 2285         int error;
 2286         int big, byte2;
 2287         struct cd_audio_page *page;
 2288 
 2289         byte2 = SMS_DBD;
 2290 try_again:
 2291         if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page),
 2292             AUDIO_PAGE, flags, &big)) != 0) {
 2293                 if (byte2 == SMS_DBD) {
 2294                         /* Device may not understand DBD; retry without */
 2295                         byte2 = 0;
 2296                         goto try_again;
 2297                 }
 2298                 return (error);
 2299         }
 2300 
 2301         if (big)
 2302                 page = (void *)((u_long)&data.header.big +
 2303                                 sizeof data.header.big +
 2304                                 _2btol(data.header.big.blk_desc_len));
 2305         else
 2306                 page = (void *)((u_long)&data.header.small +
 2307                                 sizeof data.header.small +
 2308                                 data.header.small.blk_desc_len);
 2309 
 2310         arg->vol[0] = page->port[0].volume;
 2311         arg->vol[1] = page->port[1].volume;
 2312         arg->vol[2] = page->port[2].volume;
 2313         arg->vol[3] = page->port[3].volume;
 2314 
 2315         return (0);
 2316 }
 2317 
 2318 static int
 2319 cd_setvol(struct cd_softc *cd, const struct ioc_vol *arg, int flags)
 2320 {
 2321         struct {
 2322                 union {
 2323                         struct scsi_mode_parameter_header_6 small;
 2324                         struct scsi_mode_parameter_header_10 big;
 2325                 } header;
 2326                 struct cd_audio_page page;
 2327         } data, mask;
 2328         int error;
 2329         int big, byte2;
 2330         struct cd_audio_page *page, *page2;
 2331 
 2332         byte2 = SMS_DBD;
 2333 try_again:
 2334         if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page),
 2335             AUDIO_PAGE, flags, &big)) != 0) {
 2336                 if (byte2 == SMS_DBD) {
 2337                         /* Device may not understand DBD; retry without */
 2338                         byte2 = 0;
 2339                         goto try_again;
 2340                 }
 2341                 return (error);
 2342         }
 2343         if ((error = cd_mode_sense(cd, byte2, &mask, sizeof(mask.page),
 2344             AUDIO_PAGE|SMS_PCTRL_CHANGEABLE, flags, &big)) != 0)
 2345                 return (error);
 2346 
 2347         if (big) {
 2348                 page = (void *)((u_long)&data.header.big +
 2349                                 sizeof data.header.big +
 2350                                 _2btol(data.header.big.blk_desc_len));
 2351                 page2 = (void *)((u_long)&mask.header.big +
 2352                                 sizeof mask.header.big +
 2353                                 _2btol(mask.header.big.blk_desc_len));
 2354         } else {
 2355                 page = (void *)((u_long)&data.header.small +
 2356                                 sizeof data.header.small +
 2357                                 data.header.small.blk_desc_len);
 2358                 page2 = (void *)((u_long)&mask.header.small +
 2359                                 sizeof mask.header.small +
 2360                                 mask.header.small.blk_desc_len);
 2361         }
 2362 
 2363         page->port[0].volume = arg->vol[0] & page2->port[0].volume;
 2364         page->port[1].volume = arg->vol[1] & page2->port[1].volume;
 2365         page->port[2].volume = arg->vol[2] & page2->port[2].volume;
 2366         page->port[3].volume = arg->vol[3] & page2->port[3].volume;
 2367 
 2368         page->port[0].channels = CHANNEL_0;
 2369         page->port[1].channels = CHANNEL_1;
 2370 
 2371         return (cd_mode_select(cd, SMS_PF, &data,
 2372             sizeof(struct scsi_mode_page_header) + page->pg_length,
 2373             flags, big));
 2374 }
 2375 
 2376 static int
 2377 cd_load_unload(struct cd_softc *cd, struct ioc_load_unload *args)
 2378 {
 2379         struct scsipi_load_unload cmd;
 2380 
 2381         memset(&cmd, 0, sizeof(cmd));
 2382         cmd.opcode = LOAD_UNLOAD;
 2383         cmd.options = args->options;    /* ioctl uses MMC values */
 2384         cmd.slot = args->slot;
 2385 
 2386         return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
 2387             CDRETRIES, 200000, NULL, 0));
 2388 }
 2389 
 2390 static int
 2391 cd_setblksize(struct cd_softc *cd)
 2392 {
 2393         struct {
 2394                 union {
 2395                         struct scsi_mode_parameter_header_6 small;
 2396                         struct scsi_mode_parameter_header_10 big;
 2397                 } header;
 2398                 struct scsi_general_block_descriptor blk_desc;
 2399         } data;
 2400         int error;
 2401         int big, bsize;
 2402         struct scsi_general_block_descriptor *bdesc;
 2403 
 2404         if ((error = cd_mode_sense(cd, 0, &data, sizeof(data.blk_desc), 0, 0,
 2405             &big)) != 0)
 2406                 return (error);
 2407 
 2408         if (big) {
 2409                 bdesc = (void *)(&data.header.big + 1);
 2410                 bsize = _2btol(data.header.big.blk_desc_len);
 2411         } else {
 2412                 bdesc = (void *)(&data.header.small + 1);
 2413                 bsize = data.header.small.blk_desc_len;
 2414         }
 2415 
 2416         if (bsize == 0) {
 2417 printf("cd_setblksize: trying to change bsize, but no blk_desc\n");
 2418                 return (EINVAL);
 2419         }
 2420         if (_3btol(bdesc->blklen) == 2048) {
 2421 printf("cd_setblksize: trying to change bsize, but blk_desc is correct\n");
 2422                 return (EINVAL);
 2423         }
 2424 
 2425         _lto3b(2048, bdesc->blklen);
 2426 
 2427         return (cd_mode_select(cd, SMS_PF, &data, sizeof(data.blk_desc), 0,
 2428             big));
 2429 }
 2430 
 2431 
 2432 static int
 2433 mmc_profile2class(uint16_t mmc_profile)
 2434 {
 2435         switch (mmc_profile) {
 2436         case 0x01 : /* SCSI discs */
 2437         case 0x02 :
 2438                 /* this can't happen really, cd.c wouldn't have matched */
 2439                 return MMC_CLASS_DISC;
 2440         case 0x03 : /* Magneto Optical with sector erase */
 2441         case 0x04 : /* Magneto Optical write once        */
 2442         case 0x05 : /* Advance Storage Magneto Optical   */
 2443                 return MMC_CLASS_MO;
 2444         case 0x00 : /* Unknown MMC profile, can also be CD-ROM */
 2445         case 0x08 : /* CD-ROM  */
 2446         case 0x09 : /* CD-R    */
 2447         case 0x0a : /* CD-RW   */
 2448                 return MMC_CLASS_CD;
 2449         case 0x10 : /* DVD-ROM */
 2450         case 0x11 : /* DVD-R   */
 2451         case 0x12 : /* DVD-RAM */
 2452         case 0x13 : /* DVD-RW restricted overwrite */
 2453         case 0x14 : /* DVD-RW sequential */
 2454         case 0x1a : /* DVD+RW  */
 2455         case 0x1b : /* DVD+R   */
 2456         case 0x2a : /* DVD+RW Dual layer */
 2457         case 0x2b : /* DVD+R Dual layer */
 2458         case 0x50 : /* HD DVD-ROM */
 2459         case 0x51 : /* HD DVD-R   */
 2460         case 0x52 : /* HD DVD-RW; DVD-RAM like */
 2461                 return MMC_CLASS_DVD;
 2462         case 0x40 : /* BD-ROM  */
 2463         case 0x41 : /* BD-R Sequential recording (SRM) */
 2464         case 0x42 : /* BD-R Random Recording (RRM) */
 2465         case 0x43 : /* BD-RE */
 2466                 return MMC_CLASS_BD;
 2467         }
 2468         return MMC_CLASS_UNKN;
 2469 }
 2470 
 2471 
 2472 /*
 2473  * Drive/media combination is reflected in a series of features that can
 2474  * either be current or dormant. We try to make sense out of them to create a
 2475  * set of easy to use flags that abstract the device/media capabilities.
 2476  */
 2477 
 2478 static void
 2479 mmc_process_feature(struct mmc_discinfo *mmc_discinfo,
 2480                     uint16_t feature, int cur, uint8_t *rpos)
 2481 {
 2482         uint32_t blockingnr;
 2483         uint64_t flags;
 2484 
 2485         if (cur == 1) {
 2486                 flags = mmc_discinfo->mmc_cur;
 2487         } else {
 2488                 flags = mmc_discinfo->mmc_cap;
 2489         }
 2490 
 2491         switch (feature) {
 2492         case 0x0010 :   /* random readable feature */
 2493                 blockingnr  =  rpos[5] | (rpos[4] << 8);
 2494                 if (blockingnr > 1)
 2495                         flags |= MMC_CAP_PACKET;
 2496 
 2497                 /* RW error page */
 2498                 break;
 2499         case 0x0020 :   /* random writable feature */
 2500                 flags |= MMC_CAP_RECORDABLE;
 2501                 flags |= MMC_CAP_REWRITABLE;
 2502                 blockingnr  =  rpos[9] | (rpos[8] << 8);
 2503                 if (blockingnr > 1)
 2504                         flags |= MMC_CAP_PACKET;
 2505                 break;
 2506         case 0x0021 :   /* incremental streaming write feature */
 2507                 flags |= MMC_CAP_RECORDABLE;
 2508                 flags |= MMC_CAP_SEQUENTIAL;
 2509                 if (cur)
 2510                         mmc_discinfo->link_block_penalty = rpos[4];
 2511                 if (rpos[2] & 1)
 2512                         flags |= MMC_CAP_ZEROLINKBLK;
 2513                 break;
 2514         case 0x0022 :   /* (obsolete) erase support feature */
 2515                 flags |= MMC_CAP_RECORDABLE;
 2516                 flags |= MMC_CAP_ERASABLE;
 2517                 break;
 2518         case 0x0023 :   /* formatting media support feature */
 2519                 flags |= MMC_CAP_RECORDABLE;
 2520                 flags |= MMC_CAP_FORMATTABLE;
 2521                 break;
 2522         case 0x0024 :   /* hardware assised defect management feature */
 2523                 flags |= MMC_CAP_HW_DEFECTFREE;
 2524                 break;
 2525         case 0x0025 :   /* write once */
 2526                 flags |= MMC_CAP_RECORDABLE;
 2527                 break;
 2528         case 0x0026 :   /* restricted overwrite feature */
 2529                 flags |= MMC_CAP_RECORDABLE;
 2530                 flags |= MMC_CAP_REWRITABLE;
 2531                 flags |= MMC_CAP_STRICTOVERWRITE;
 2532                 break;
 2533         case 0x0028 :   /* MRW formatted media support feature */
 2534                 flags |= MMC_CAP_MRW;
 2535                 break;
 2536         case 0x002b :   /* DVD+R read (and opt. write) support */
 2537                 flags |= MMC_CAP_SEQUENTIAL;
 2538                 if (rpos[0] & 1) /* write support */
 2539                         flags |= MMC_CAP_RECORDABLE;
 2540                 break;
 2541         case 0x002c :   /* rigid restricted overwrite feature */
 2542                 flags |= MMC_CAP_RECORDABLE;
 2543                 flags |= MMC_CAP_REWRITABLE;
 2544                 flags |= MMC_CAP_STRICTOVERWRITE;
 2545                 if (rpos[0] & 1) /* blank bit */
 2546                         flags |= MMC_CAP_BLANKABLE;
 2547                 break;
 2548         case 0x002d :   /* track at once recording feature */
 2549                 flags |= MMC_CAP_RECORDABLE;
 2550                 flags |= MMC_CAP_SEQUENTIAL;
 2551                 break;
 2552         case 0x002f :   /* DVD-R/-RW write feature */
 2553                 flags |= MMC_CAP_RECORDABLE;
 2554                 if (rpos[0] & 2) /* DVD-RW bit */
 2555                         flags |= MMC_CAP_BLANKABLE;
 2556                 break;
 2557         case 0x0038 :   /* BD-R SRM with pseudo overwrite */
 2558                 flags |= MMC_CAP_PSEUDOOVERWRITE;
 2559                 break;
 2560         default :
 2561                 /* ignore */
 2562                 break;
 2563         }
 2564 
 2565         if (cur == 1) {
 2566                 mmc_discinfo->mmc_cur = flags;
 2567         } else {
 2568                 mmc_discinfo->mmc_cap = flags;
 2569         }
 2570 }
 2571 
 2572 static int
 2573 mmc_getdiscinfo_cdrom(struct scsipi_periph *periph,
 2574                       struct mmc_discinfo *mmc_discinfo)
 2575 {
 2576         struct scsipi_read_toc      gtoc_cmd;
 2577         struct scsipi_toc_header   *toc_hdr;
 2578         struct scsipi_toc_msinfo   *toc_msinfo;
 2579         const uint32_t buffer_size = 1024;
 2580         uint32_t req_size;
 2581         uint8_t  *buffer;
 2582         int error, flags;
 2583 
 2584         buffer = malloc(buffer_size, M_TEMP, M_WAITOK);
 2585         /*
 2586          * Fabricate mmc_discinfo for CD-ROM. Some values are really `dont
 2587          * care' but others might be of interest to programs.
 2588          */
 2589 
 2590         mmc_discinfo->disc_state         = MMC_STATE_FULL;
 2591         mmc_discinfo->last_session_state = MMC_STATE_FULL;
 2592         mmc_discinfo->bg_format_state    = MMC_BGFSTATE_COMPLETED;
 2593         mmc_discinfo->link_block_penalty = 7;   /* not relevant */
 2594 
 2595         /* get number of sessions and first tracknr in last session */
 2596         flags = XS_CTL_DATA_IN;
 2597         memset(&gtoc_cmd, 0, sizeof(gtoc_cmd));
 2598         gtoc_cmd.opcode      = READ_TOC;
 2599         gtoc_cmd.addr_mode   = CD_MSF;          /* not relevant        */
 2600         gtoc_cmd.resp_format = CD_TOC_MSINFO;   /* multisession info   */
 2601         gtoc_cmd.from_track  = 0;               /* reserved, must be 0 */
 2602         req_size = sizeof(*toc_hdr) + sizeof(*toc_msinfo);
 2603         _lto2b(req_size, gtoc_cmd.data_len);
 2604 
 2605         error = scsipi_command(periph,
 2606                 (void *)&gtoc_cmd, sizeof(gtoc_cmd),
 2607                 (void *)buffer,    req_size,
 2608                 CDRETRIES, 30000, NULL, flags);
 2609         if (error)
 2610                 goto out;
 2611         toc_hdr    = (struct scsipi_toc_header *)  buffer;
 2612         toc_msinfo = (struct scsipi_toc_msinfo *) (buffer + 4);
 2613         mmc_discinfo->num_sessions = toc_hdr->last - toc_hdr->first + 1;
 2614         mmc_discinfo->first_track  = toc_hdr->first;
 2615         mmc_discinfo->first_track_last_session = toc_msinfo->tracknr;
 2616 
 2617         /* get last track of last session */
 2618         flags = XS_CTL_DATA_IN;
 2619         gtoc_cmd.resp_format  = CD_TOC_FORM;    /* formatted toc */
 2620         req_size = sizeof(*toc_hdr);
 2621         _lto2b(req_size, gtoc_cmd.data_len);
 2622 
 2623         error = scsipi_command(periph,
 2624                 (void *)&gtoc_cmd, sizeof(gtoc_cmd),
 2625                 (void *)buffer,    req_size,
 2626                 CDRETRIES, 30000, NULL, flags);
 2627         if (error)
 2628                 goto out;
 2629         toc_hdr    = (struct scsipi_toc_header *) buffer;
 2630         mmc_discinfo->last_track_last_session = toc_hdr->last;
 2631         mmc_discinfo->num_tracks = toc_hdr->last - toc_hdr->first + 1;
 2632 
 2633         /* TODO how to handle disc_barcode and disc_id */
 2634         /* done */
 2635 
 2636 out:
 2637         free(buffer, M_TEMP);
 2638         return error;
 2639 }
 2640 
 2641 static int
 2642 mmc_getdiscinfo_dvdrom(struct scsipi_periph *periph,
 2643                        struct mmc_discinfo *mmc_discinfo)
 2644 {
 2645         struct scsipi_read_toc   gtoc_cmd;
 2646         struct scsipi_toc_header toc_hdr;
 2647         uint32_t req_size;
 2648         int error, flags;
 2649 
 2650         /*
 2651          * Fabricate mmc_discinfo for DVD-ROM. Some values are really `dont
 2652          * care' but others might be of interest to programs.
 2653          */
 2654 
 2655         mmc_discinfo->disc_state         = MMC_STATE_FULL;
 2656         mmc_discinfo->last_session_state = MMC_STATE_FULL;
 2657         mmc_discinfo->bg_format_state    = MMC_BGFSTATE_COMPLETED;
 2658         mmc_discinfo->link_block_penalty = 16;  /* not relevant */
 2659 
 2660         /* get number of sessions and first tracknr in last session */
 2661         flags = XS_CTL_DATA_IN;
 2662         memset(&gtoc_cmd, 0, sizeof(gtoc_cmd));
 2663         gtoc_cmd.opcode      = READ_TOC;
 2664         gtoc_cmd.addr_mode   = 0;               /* LBA                 */
 2665         gtoc_cmd.resp_format = CD_TOC_FORM;     /* multisession info   */
 2666         gtoc_cmd.from_track  = 1;               /* first track         */
 2667         req_size = sizeof(toc_hdr);
 2668         _lto2b(req_size, gtoc_cmd.data_len);
 2669 
 2670         error = scsipi_command(periph,
 2671                 (void *)&gtoc_cmd, sizeof(gtoc_cmd),
 2672                 (void *)&toc_hdr,  req_size,
 2673                 CDRETRIES, 30000, NULL, flags);
 2674         if (error)
 2675                 return error;
 2676 
 2677         /* DVD-ROM squashes the track/session space */
 2678         mmc_discinfo->num_sessions = toc_hdr.last - toc_hdr.first + 1;
 2679         mmc_discinfo->num_tracks   = mmc_discinfo->num_sessions;
 2680         mmc_discinfo->first_track  = toc_hdr.first;
 2681         mmc_discinfo->first_track_last_session = toc_hdr.last;
 2682         mmc_discinfo->last_track_last_session  = toc_hdr.last;
 2683 
 2684         /* TODO how to handle disc_barcode and disc_id */
 2685         /* done */
 2686         return 0;
 2687 }
 2688 
 2689 static int
 2690 mmc_getdiscinfo(struct scsipi_periph *periph,
 2691                 struct mmc_discinfo *mmc_discinfo)
 2692 {
 2693         struct scsipi_get_configuration   gc_cmd;
 2694         struct scsipi_get_conf_data      *gc;
 2695         struct scsipi_get_conf_feature   *gcf;
 2696         struct scsipi_read_discinfo       di_cmd;
 2697         struct scsipi_read_discinfo_data  di __aligned(2);
 2698         const uint32_t buffer_size = 0x200; /* XXX RPZ USB3 SCSI size issue */
 2699         uint32_t pos;
 2700         u_long   last_lba = 0;
 2701         uint8_t  *buffer, *fpos;
 2702         int feature, last_feature, features_len, feature_cur, feature_len;
 2703         int lsb, msb, error, flags;
 2704 
 2705         buffer = malloc(buffer_size, M_TEMP, M_WAITOK);
 2706 
 2707         /* initialise structure */
 2708         memset(mmc_discinfo, 0, sizeof(struct mmc_discinfo));
 2709         mmc_discinfo->mmc_profile = 0x00;       /* unknown */
 2710         mmc_discinfo->mmc_class   = MMC_CLASS_UNKN;
 2711         mmc_discinfo->mmc_cur     = 0;
 2712         mmc_discinfo->mmc_cap     = 0;
 2713         mmc_discinfo->link_block_penalty = 0;
 2714 
 2715         /* determine mmc profile and class */
 2716         flags = XS_CTL_DATA_IN;
 2717         memset(&gc_cmd, 0, sizeof(gc_cmd));
 2718         gc_cmd.opcode = GET_CONFIGURATION;
 2719         _lto2b(GET_CONF_NO_FEATURES_LEN, gc_cmd.data_len);
 2720 
 2721         gc = (struct scsipi_get_conf_data *) buffer;
 2722 
 2723         error = scsipi_command(periph,
 2724                 (void *)&gc_cmd, sizeof(gc_cmd),
 2725                 (void *) gc,     GET_CONF_NO_FEATURES_LEN,
 2726                 CDRETRIES, 30000, NULL, flags);
 2727         if (error)
 2728                 goto out;
 2729 
 2730         mmc_discinfo->mmc_profile = _2btol(gc->mmc_profile);
 2731         mmc_discinfo->mmc_class = mmc_profile2class(mmc_discinfo->mmc_profile);
 2732 
 2733         /* assume 2048 sector size unless told otherwise */
 2734         mmc_discinfo->sector_size = 2048;
 2735         error = read_cd_capacity(periph, &mmc_discinfo->sector_size, &last_lba);
 2736         if (error)
 2737                 goto out;
 2738 
 2739         mmc_discinfo->last_possible_lba = (uint32_t) last_lba;
 2740 
 2741         /* Read in all features to determine device capabilities */
 2742         last_feature = feature = 0;
 2743         do {
 2744                 /* determine mmc profile and class */
 2745                 flags = XS_CTL_DATA_IN;
 2746                 memset(&gc_cmd, 0, sizeof(gc_cmd));
 2747                 gc_cmd.opcode = GET_CONFIGURATION;
 2748                 _lto2b(last_feature, gc_cmd.start_at_feature);
 2749                 _lto2b(buffer_size, gc_cmd.data_len);
 2750                 memset(gc, 0, buffer_size);
 2751 
 2752                 error = scsipi_command(periph,
 2753                         (void *)&gc_cmd, sizeof(gc_cmd),
 2754                         (void *) gc,     buffer_size,
 2755                         CDRETRIES, 30000, NULL, flags);
 2756                 if (error) {
 2757                         /* ieeek... break out of loop... i dunno what to do */
 2758                         break;
 2759                 }
 2760 
 2761                 features_len = _4btol(gc->data_len);
 2762                 if (features_len < 4 || features_len > buffer_size)
 2763                         break;
 2764 
 2765                 pos  = 0;
 2766                 fpos = &gc->feature_desc[0];
 2767                 while (pos < features_len - 4) {
 2768                         gcf = (struct scsipi_get_conf_feature *) fpos;
 2769 
 2770                         feature     = _2btol(gcf->featurecode);
 2771                         feature_cur = gcf->flags & 1;
 2772                         feature_len = gcf->additional_length;
 2773 
 2774                         mmc_process_feature(mmc_discinfo,
 2775                                             feature, feature_cur,
 2776                                             gcf->feature_dependent);
 2777 
 2778                         last_feature = MAX(last_feature, feature);
 2779 #ifdef DIAGNOSTIC
 2780                         /* assert((feature_len & 3) == 0); */
 2781                         if ((feature_len & 3) != 0) {
 2782                                 printf("feature %d having length %d\n",
 2783                                         feature, feature_len);
 2784                         }
 2785 #endif
 2786 
 2787                         pos  += 4 + feature_len;
 2788                         fpos += 4 + feature_len;
 2789                 }
 2790                 /* unlikely to ever grow past our 1kb buffer */
 2791         } while (features_len >= 0xffff);
 2792 
 2793         /*
 2794          * Fixup CD-RW drives that are on crack.
 2795          *
 2796          * Some drives report the capability to incrementally write
 2797          * sequentially on CD-R(W) media...  nice, but this should not be
 2798          * active for a fixed packet formatted CD-RW media. Other report the
 2799          * ability of HW_DEFECTFREE even when the media is NOT MRW
 2800          * formatted....
 2801          */
 2802         if (mmc_discinfo->mmc_profile == 0x0a) {
 2803                 if ((mmc_discinfo->mmc_cur & MMC_CAP_SEQUENTIAL) == 0)
 2804                         mmc_discinfo->mmc_cur |= MMC_CAP_STRICTOVERWRITE;
 2805                 if (mmc_discinfo->mmc_cur & MMC_CAP_STRICTOVERWRITE)
 2806                         mmc_discinfo->mmc_cur &= ~MMC_CAP_SEQUENTIAL;
 2807                 if (mmc_discinfo->mmc_cur & MMC_CAP_MRW) {
 2808                         mmc_discinfo->mmc_cur &= ~MMC_CAP_SEQUENTIAL;
 2809                         mmc_discinfo->mmc_cur &= ~MMC_CAP_STRICTOVERWRITE;
 2810                 } else {
 2811                         mmc_discinfo->mmc_cur &= ~MMC_CAP_HW_DEFECTFREE;
 2812                 }
 2813         }
 2814         if (mmc_discinfo->mmc_profile == 0x09) {
 2815                 mmc_discinfo->mmc_cur &= ~MMC_CAP_REWRITABLE;
 2816         }
 2817 
 2818 #ifdef DEBUG
 2819         printf("CD mmc %d, mmc_cur 0x%"PRIx64", mmc_cap 0x%"PRIx64"\n",
 2820                 mmc_discinfo->mmc_profile,
 2821                 mmc_discinfo->mmc_cur, mmc_discinfo->mmc_cap);
 2822 #endif
 2823 
 2824         /* read in disc state and number of sessions and tracks */
 2825         flags = XS_CTL_DATA_IN | XS_CTL_SILENT;
 2826         memset(&di_cmd, 0, sizeof(di_cmd));
 2827         di_cmd.opcode = READ_DISCINFO;
 2828         di_cmd.data_len[1] = READ_DISCINFO_BIGSIZE;
 2829 
 2830         error = scsipi_command(periph,
 2831                 (void *)&di_cmd, sizeof(di_cmd),
 2832                 (void *)&di,     READ_DISCINFO_BIGSIZE,
 2833                 CDRETRIES, 30000, NULL, flags);
 2834 
 2835         if (error) {
 2836                 /* discinfo call failed, emulate for cd-rom/dvd-rom */
 2837                 if (mmc_discinfo->mmc_profile == 0x08) /* CD-ROM */
 2838                         error = mmc_getdiscinfo_cdrom(periph, mmc_discinfo);
 2839                 else if (mmc_discinfo->mmc_profile == 0x10) /* DVD-ROM */
 2840                         error = mmc_getdiscinfo_dvdrom(periph, mmc_discinfo);
 2841                 else /* CD/DVD drive is violating specs */
 2842                         error = EIO;
 2843                 goto out;
 2844         }
 2845 
 2846         /* call went OK */
 2847         mmc_discinfo->disc_state         =  di.disc_state & 3;
 2848         mmc_discinfo->last_session_state = (di.disc_state >> 2) & 3;
 2849         mmc_discinfo->bg_format_state    = (di.disc_state2 & 3);
 2850 
 2851         lsb = di.num_sessions_lsb;
 2852         msb = di.num_sessions_msb;
 2853         mmc_discinfo->num_sessions = lsb | (msb << 8);
 2854 
 2855         mmc_discinfo->first_track = di.first_track;
 2856         lsb = di.first_track_last_session_lsb;
 2857         msb = di.first_track_last_session_msb;
 2858         mmc_discinfo->first_track_last_session = lsb | (msb << 8);
 2859         lsb = di.last_track_last_session_lsb;
 2860         msb = di.last_track_last_session_msb;
 2861         mmc_discinfo->last_track_last_session  = lsb | (msb << 8);
 2862 
 2863         mmc_discinfo->num_tracks = mmc_discinfo->last_track_last_session -
 2864                 mmc_discinfo->first_track + 1;
 2865 
 2866         /* set misc. flags and parameters from this disc info */
 2867         if (di.disc_state  &  16)
 2868                 mmc_discinfo->mmc_cur |= MMC_CAP_BLANKABLE;
 2869 
 2870         if (di.disc_state2 & 128) {
 2871                 mmc_discinfo->disc_id = _4btol(di.discid);
 2872                 mmc_discinfo->disc_flags |= MMC_DFLAGS_DISCIDVALID;
 2873         }
 2874         if (di.disc_state2 &  64) {
 2875                 mmc_discinfo->disc_barcode = _8btol(di.disc_bar_code);
 2876                 mmc_discinfo->disc_flags |= MMC_DFLAGS_BARCODEVALID;
 2877         }
 2878         if (di.disc_state2 &  32)
 2879                 mmc_discinfo->disc_flags |= MMC_DFLAGS_UNRESTRICTED;
 2880 
 2881         if (di.disc_state2 &  16) {
 2882                 mmc_discinfo->application_code = di.application_code;
 2883                 mmc_discinfo->disc_flags |= MMC_DFLAGS_APPCODEVALID;
 2884         }
 2885 
 2886         /* done */
 2887 
 2888 out:
 2889         free(buffer, M_TEMP);
 2890         return error;
 2891 }
 2892 
 2893 static int
 2894 mmc_gettrackinfo_cdrom(struct scsipi_periph *periph,
 2895                        struct mmc_trackinfo *trackinfo)
 2896 {
 2897         struct scsipi_read_toc            gtoc_cmd;
 2898         struct scsipi_toc_header         *toc_hdr;
 2899         struct scsipi_toc_rawtoc         *rawtoc;
 2900         uint32_t track_start, track_size;
 2901         uint32_t last_recorded, next_writable;
 2902         uint32_t lba, next_track_start, lead_out;
 2903         const uint32_t buffer_size = 4 * 1024;  /* worst case TOC estimate */
 2904         uint8_t *buffer;
 2905         uint8_t track_sessionnr, sessionnr, adr, tno, point;
 2906         uint8_t control, tmin, tsec, tframe, pmin, psec, pframe;
 2907         int size, req_size;
 2908         int error, flags;
 2909 
 2910         buffer = malloc(buffer_size, M_TEMP, M_WAITOK);
 2911 
 2912         /*
 2913          * Emulate read trackinfo for CD-ROM using the raw-TOC.
 2914          *
 2915          * Not all information is present and this presents a problem.  Track
 2916          * starts are known for each track but other values are deducted.
 2917          *
 2918          * For a complete overview of `magic' values used here, see the
 2919          * SCSI/ATAPI MMC documentation. Note that the `magic' values have no
 2920          * names, they are specified as numbers.
 2921          */
 2922 
 2923         /* get raw toc to process, first header to check size */
 2924         flags = XS_CTL_DATA_IN | XS_CTL_SILENT;
 2925         memset(&gtoc_cmd, 0, sizeof(gtoc_cmd));
 2926         gtoc_cmd.opcode      = READ_TOC;
 2927         gtoc_cmd.addr_mode   = CD_MSF;          /* not relevant     */
 2928         gtoc_cmd.resp_format = CD_TOC_RAW;      /* raw toc          */
 2929         gtoc_cmd.from_track  = 1;               /* first session    */
 2930         req_size = sizeof(*toc_hdr);
 2931         _lto2b(req_size, gtoc_cmd.data_len);
 2932 
 2933         error = scsipi_command(periph,
 2934                 (void *)&gtoc_cmd, sizeof(gtoc_cmd),
 2935                 (void *)buffer,    req_size,
 2936                 CDRETRIES, 30000, NULL, flags);
 2937         if (error)
 2938                 goto out;
 2939         toc_hdr = (struct scsipi_toc_header *) buffer;
 2940         if (_2btol(toc_hdr->length) > buffer_size - 2) {
 2941 #ifdef DIAGNOSTIC
 2942                 printf("increase buffersize in mmc_readtrackinfo_cdrom\n");
 2943 #endif
 2944                 error = ENOBUFS;
 2945                 goto out;
 2946         }
 2947 
 2948         /* read in complete raw toc */
 2949         req_size = _2btol(toc_hdr->length);
 2950         req_size = 2*((req_size + 1) / 2);      /* for ATAPI */
 2951         _lto2b(req_size, gtoc_cmd.data_len);
 2952 
 2953         error = scsipi_command(periph,
 2954                 (void *)&gtoc_cmd, sizeof(gtoc_cmd),
 2955                 (void *)buffer,    req_size,
 2956                 CDRETRIES, 30000, NULL, flags);
 2957         if (error)
 2958                 goto out;
 2959 
 2960         toc_hdr = (struct scsipi_toc_header *) buffer;
 2961         rawtoc  = (struct scsipi_toc_rawtoc *) (buffer + 4);
 2962 
 2963         track_start      = 0;
 2964         track_size       = 0;
 2965         last_recorded    = 0;
 2966         next_writable    = 0;
 2967         flags            = 0;
 2968 
 2969         next_track_start = 0;
 2970         track_sessionnr  = MAXTRACK;    /* by definition */
 2971         lead_out         = 0;
 2972 
 2973         size = req_size - sizeof(struct scsipi_toc_header) + 1;
 2974         while (size > 0) {
 2975                 /* get track start and session end */
 2976                 tno       = rawtoc->tno;
 2977                 sessionnr = rawtoc->sessionnr;
 2978                 adr       = rawtoc->adrcontrol >> 4;
 2979                 control   = rawtoc->adrcontrol & 0xf;
 2980                 point     = rawtoc->point;
 2981                 tmin      = rawtoc->min;
 2982                 tsec      = rawtoc->sec;
 2983                 tframe    = rawtoc->frame;
 2984                 pmin      = rawtoc->pmin;
 2985                 psec      = rawtoc->psec;
 2986                 pframe    = rawtoc->pframe;
 2987 
 2988                 if (tno == 0 && sessionnr && adr == 1) {
 2989                         lba = hmsf2lba(0, pmin, psec, pframe);
 2990                         if (point == trackinfo->tracknr) {
 2991                                 track_start = lba;
 2992                                 track_sessionnr = sessionnr;
 2993                         }
 2994                         if (point == trackinfo->tracknr + 1) {
 2995                                 /* estimate size */
 2996                                 track_size = lba - track_start;
 2997                                 next_track_start = lba;
 2998                         }
 2999                         if (point == 0xa2) {
 3000                                 lead_out = lba;
 3001                         }
 3002                         if (point <= 0x63) {
 3003                                 /* CD's ok, DVD are glued */
 3004                                 /* last_tracknr = point; */
 3005                         }
 3006                         if (sessionnr == track_sessionnr) {
 3007                                 last_recorded = lead_out;
 3008                         }
 3009                 }
 3010                 if (tno == 0 && sessionnr && adr == 5) {
 3011                         lba = hmsf2lba(0, tmin, tsec, tframe);
 3012                         if (sessionnr == track_sessionnr) {
 3013                                 next_writable = lba;
 3014                         }
 3015                 }
 3016 
 3017                 if ((control & (3<<2)) == 4)            /* 01xxb */
 3018                         flags |= MMC_TRACKINFO_DATA;
 3019                 if ((control & (1<<2)) == 0) {          /* x0xxb */
 3020                         flags |= MMC_TRACKINFO_AUDIO;
 3021                         if (control & 1)                /* xxx1b */
 3022                                 flags |= MMC_TRACKINFO_PRE_EMPH;
 3023                 }
 3024 
 3025                 rawtoc++;
 3026                 size -= sizeof(struct scsipi_toc_rawtoc);
 3027         }
 3028 
 3029         /* process found values; some voodoo */
 3030         /* if no tracksize tracknr is the last of the disc */
 3031         if ((track_size == 0) && last_recorded) {
 3032                 track_size = last_recorded - track_start;
 3033         }
 3034         /* if last_recorded < tracksize, tracksize is overestimated */
 3035         if (last_recorded) {
 3036                 if (last_recorded - track_start <= track_size) {
 3037                         track_size = last_recorded - track_start;
 3038                         flags |= MMC_TRACKINFO_LRA_VALID;
 3039                 }
 3040         }
 3041         /* check if its a the last track of the sector */
 3042         if (next_writable) {
 3043                 if (next_track_start > next_writable)
 3044                         flags |= MMC_TRACKINFO_NWA_VALID;
 3045         }
 3046 
 3047         /* no flag set -> no values */
 3048         if ((flags & MMC_TRACKINFO_LRA_VALID) == 0)
 3049                 last_recorded = 0;
 3050         if ((flags & MMC_TRACKINFO_NWA_VALID) == 0)
 3051                 next_writable = 0;
 3052 
 3053         /* fill in */
 3054         /* trackinfo->tracknr preserved */
 3055         trackinfo->sessionnr  = track_sessionnr;
 3056         trackinfo->track_mode = 7;      /* data, incremental  */
 3057         trackinfo->data_mode  = 8;      /* 2048 bytes mode1   */
 3058 
 3059         trackinfo->flags = flags;
 3060         trackinfo->track_start   = track_start;
 3061         trackinfo->next_writable = next_writable;
 3062         trackinfo->free_blocks   = 0;
 3063         trackinfo->packet_size   = 1;
 3064         trackinfo->track_size    = track_size;
 3065         trackinfo->last_recorded = last_recorded;
 3066 
 3067 out:
 3068         free(buffer, M_TEMP);
 3069         return error;
 3070 
 3071 }
 3072 
 3073 static int
 3074 mmc_gettrackinfo_dvdrom(struct scsipi_periph *periph, 
 3075                         struct mmc_trackinfo *trackinfo)
 3076 {
 3077         struct scsipi_read_toc            gtoc_cmd;
 3078         struct scsipi_toc_header         *toc_hdr;
 3079         struct scsipi_toc_formatted      *toc;
 3080         uint32_t tracknr, track_start, track_size;
 3081         uint32_t lba, lead_out;
 3082         const uint32_t buffer_size = 4 * 1024;  /* worst case TOC estimate */
 3083         uint8_t *buffer;
 3084         uint8_t control, last_tracknr;
 3085         int size, req_size;
 3086         int error, flags;
 3087 
 3088         
 3089         buffer = malloc(buffer_size, M_TEMP, M_WAITOK);
 3090         /*
 3091          * Emulate read trackinfo for DVD-ROM. We can't use the raw-TOC as the
 3092          * CD-ROM emulation uses since the specification tells us that no such
 3093          * thing is defined for DVD's. The reason for this is due to the large
 3094          * number of tracks and that would clash with the `magic' values. This
 3095          * suxs.
 3096          *
 3097          * Not all information is present and this presents a problem.
 3098          * Track starts are known for each track but other values are
 3099          * deducted.
 3100          */
 3101 
 3102         /* get formatted toc to process, first header to check size */
 3103         flags = XS_CTL_DATA_IN | XS_CTL_SILENT;
 3104         memset(&gtoc_cmd, 0, sizeof(gtoc_cmd));
 3105         gtoc_cmd.opcode      = READ_TOC;
 3106         gtoc_cmd.addr_mode   = 0;               /* lba's please     */
 3107         gtoc_cmd.resp_format = CD_TOC_FORM;     /* formatted toc    */
 3108         gtoc_cmd.from_track  = 1;               /* first track      */
 3109         req_size = sizeof(*toc_hdr);
 3110         _lto2b(req_size, gtoc_cmd.data_len);
 3111 
 3112         error = scsipi_command(periph,
 3113                 (void *)&gtoc_cmd, sizeof(gtoc_cmd),
 3114                 (void *)buffer,    req_size,
 3115                 CDRETRIES, 30000, NULL, flags);
 3116         if (error)
 3117                 goto out;
 3118         toc_hdr = (struct scsipi_toc_header *) buffer;
 3119         if (_2btol(toc_hdr->length) > buffer_size - 2) {
 3120 #ifdef DIAGNOSTIC
 3121                 printf("increase buffersize in mmc_readtrackinfo_dvdrom\n");
 3122 #endif
 3123                 error = ENOBUFS;
 3124                 goto out;
 3125         }
 3126 
 3127         /* read in complete formatted toc */
 3128         req_size = _2btol(toc_hdr->length);
 3129         _lto2b(req_size, gtoc_cmd.data_len);
 3130 
 3131         error = scsipi_command(periph,
 3132                 (void *)&gtoc_cmd, sizeof(gtoc_cmd),
 3133                 (void *)buffer,    req_size,
 3134                 CDRETRIES, 30000, NULL, flags);
 3135         if (error)
 3136                 goto out;
 3137 
 3138         toc_hdr = (struct scsipi_toc_header *)     buffer;
 3139         toc     = (struct scsipi_toc_formatted *) (buffer + 4);
 3140 
 3141         /* as in read disc info, all sessions are converted to tracks      */
 3142         /* track 1..  -> offsets, sizes can be (roughly) estimated (16 ECC) */
 3143         /* last track -> we got the size from the lead-out                 */
 3144 
 3145         tracknr      = 0;
 3146         last_tracknr = toc_hdr->last;
 3147         track_start  = 0;
 3148         track_size   = 0;
 3149         lead_out     = 0;
 3150         flags        = 0;
 3151 
 3152         size = req_size - sizeof(struct scsipi_toc_header) + 1;
 3153         while (size > 0) {
 3154                 /* remember, DVD-ROM: tracknr == sessionnr */
 3155                 lba     = _4btol(toc->msf_lba);
 3156                 tracknr = toc->tracknr;
 3157                 control = toc->adrcontrol & 0xf;
 3158 
 3159                 if (trackinfo->tracknr == tracknr) {
 3160                         track_start = lba;
 3161                 }
 3162                 if (trackinfo->tracknr == tracknr+1) {
 3163                         track_size  = lba - track_start;
 3164                         track_size -= 16;       /* link block ? */
 3165                 }
 3166                 if (tracknr == 0xAA) {
 3167                         lead_out = lba;
 3168                 }
 3169 
 3170                 if ((control & (3<<2)) == 4)            /* 01xxb */
 3171                         flags |= MMC_TRACKINFO_DATA;
 3172                 if ((control & (1<<2)) == 0) {          /* x0xxb */
 3173                         flags |= MMC_TRACKINFO_AUDIO;
 3174                         if (control & (1<<3))           /* 10xxb */
 3175                                 flags |= MMC_TRACKINFO_AUDIO_4CHAN;
 3176                         if (control & 1)                /* xxx1b */
 3177                                 flags |= MMC_TRACKINFO_PRE_EMPH;
 3178                 }
 3179 
 3180                 toc++;
 3181                 size -= sizeof(struct scsipi_toc_formatted);
 3182         }
 3183         if (trackinfo->tracknr == last_tracknr) {
 3184                 track_size = lead_out - track_start;
 3185         }
 3186 
 3187         /* fill in */
 3188         /* trackinfo->tracknr preserved */
 3189         trackinfo->sessionnr  = trackinfo->tracknr;
 3190         trackinfo->track_mode = 0;      /* unknown */
 3191         trackinfo->data_mode  = 8;      /* 2048 bytes mode1   */
 3192 
 3193         trackinfo->flags         = flags;
 3194         trackinfo->track_start   = track_start;
 3195         trackinfo->next_writable = 0;
 3196         trackinfo->free_blocks   = 0;
 3197         trackinfo->packet_size   = 16;  /* standard length 16 blocks ECC */
 3198         trackinfo->track_size    = track_size;
 3199         trackinfo->last_recorded = 0;
 3200 
 3201 out:
 3202         free(buffer, M_TEMP);
 3203         return error;
 3204 }
 3205 
 3206 static int
 3207 mmc_gettrackinfo(struct scsipi_periph *periph, 
 3208                  struct mmc_trackinfo *trackinfo)
 3209 {
 3210         struct scsipi_read_trackinfo      ti_cmd;
 3211         struct scsipi_read_trackinfo_data ti __aligned(2);
 3212         struct scsipi_get_configuration   gc_cmd;
 3213         struct scsipi_get_conf_data       gc __aligned(2);
 3214         int error, flags;
 3215         int mmc_profile;
 3216 
 3217         /* set up SCSI call with track number from trackinfo.tracknr */
 3218         flags = XS_CTL_DATA_IN | XS_CTL_SILENT;
 3219         memset(&ti_cmd, 0, sizeof(ti_cmd));
 3220         ti_cmd.opcode    = READ_TRACKINFO;
 3221         ti_cmd.addr_type = READ_TRACKINFO_ADDR_TRACK;
 3222         ti_cmd.data_len[1] = READ_TRACKINFO_RETURNSIZE;
 3223 
 3224         /* trackinfo.tracknr contains number of tracks to query */
 3225         _lto4b(trackinfo->tracknr, ti_cmd.address);
 3226         error = scsipi_command(periph,
 3227                 (void *)&ti_cmd, sizeof(ti_cmd),
 3228                 (void *)&ti,     READ_TRACKINFO_RETURNSIZE,
 3229                 CDRETRIES, 30000, NULL, flags);
 3230 
 3231         if (error) {
 3232                 /* trackinfo call failed, emulate for cd-rom/dvd-rom */
 3233                 /* first determine mmc profile */
 3234                 flags = XS_CTL_DATA_IN;
 3235                 memset(&gc_cmd, 0, sizeof(gc_cmd));
 3236                 gc_cmd.opcode = GET_CONFIGURATION;
 3237                 _lto2b(GET_CONF_NO_FEATURES_LEN, gc_cmd.data_len);
 3238 
 3239                 error = scsipi_command(periph,
 3240                         (void *)&gc_cmd, sizeof(gc_cmd),
 3241                         (void *)&gc,     GET_CONF_NO_FEATURES_LEN,
 3242                         CDRETRIES, 30000, NULL, flags);
 3243                 if (error)
 3244                         return error;
 3245                 mmc_profile = _2btol(gc.mmc_profile);
 3246 
 3247                 /* choose emulation */
 3248                 if (mmc_profile == 0x08) /* CD-ROM */
 3249                         return mmc_gettrackinfo_cdrom(periph, trackinfo);
 3250                 if (mmc_profile == 0x10) /* DVD-ROM */
 3251                         return mmc_gettrackinfo_dvdrom(periph, trackinfo);
 3252                 /* CD/DVD drive is violating specs */
 3253                 return EIO;
 3254         }
 3255 
 3256         /* (re)initialise structure */
 3257         memset(trackinfo, 0, sizeof(struct mmc_trackinfo));
 3258 
 3259         /* account for short returns screwing up track and session msb */
 3260         if ((ti.data_len[1] | (ti.data_len[0] << 8)) <= 32) {
 3261                 ti.track_msb   = 0;
 3262                 ti.session_msb = 0;
 3263         }
 3264 
 3265         trackinfo->tracknr    = ti.track_lsb   | (ti.track_msb   << 8);
 3266         trackinfo->sessionnr  = ti.session_lsb | (ti.session_msb << 8);
 3267         trackinfo->track_mode = ti.track_info_1 & 0xf;
 3268         trackinfo->data_mode  = ti.track_info_2 & 0xf;
 3269 
 3270         flags = 0;
 3271         if (ti.track_info_1 & 0x10)
 3272                 flags |= MMC_TRACKINFO_COPY;
 3273         if (ti.track_info_1 & 0x20)
 3274                 flags |= MMC_TRACKINFO_DAMAGED;
 3275         if (ti.track_info_2 & 0x10)
 3276                 flags |= MMC_TRACKINFO_FIXED_PACKET;
 3277         if (ti.track_info_2 & 0x20)
 3278                 flags |= MMC_TRACKINFO_INCREMENTAL;
 3279         if (ti.track_info_2 & 0x40)
 3280                 flags |= MMC_TRACKINFO_BLANK;
 3281         if (ti.track_info_2 & 0x80)
 3282                 flags |= MMC_TRACKINFO_RESERVED;
 3283         if (ti.data_valid   & 0x01)
 3284                 flags |= MMC_TRACKINFO_NWA_VALID;
 3285         if (ti.data_valid   & 0x02)
 3286                 flags |= MMC_TRACKINFO_LRA_VALID;
 3287         if ((trackinfo->track_mode & (3<<2)) == 4)              /* 01xxb */
 3288                 flags |= MMC_TRACKINFO_DATA;
 3289         if ((trackinfo->track_mode & (1<<2)) == 0) {            /* x0xxb */
 3290                 flags |= MMC_TRACKINFO_AUDIO;
 3291                 if (trackinfo->track_mode & (1<<3))             /* 10xxb */
 3292                         flags |= MMC_TRACKINFO_AUDIO_4CHAN;
 3293                 if (trackinfo->track_mode & 1)                  /* xxx1b */
 3294                         flags |= MMC_TRACKINFO_PRE_EMPH;
 3295         }
 3296 
 3297         trackinfo->flags = flags;
 3298         trackinfo->track_start    = _4btol(ti.track_start);
 3299         trackinfo->next_writable  = _4btol(ti.next_writable);
 3300         trackinfo->free_blocks    = _4btol(ti.free_blocks);
 3301         trackinfo->packet_size    = _4btol(ti.packet_size);
 3302         trackinfo->track_size     = _4btol(ti.track_size);
 3303         trackinfo->last_recorded  = _4btol(ti.last_recorded);
 3304 
 3305         return 0;
 3306 }
 3307 
 3308 static int
 3309 mmc_doclose(struct scsipi_periph *periph, int param, int func) {
 3310         struct scsipi_close_tracksession close_cmd;
 3311         int error, flags;
 3312 
 3313         /* set up SCSI call with track number */
 3314         flags = XS_CTL_DATA_OUT;
 3315         memset(&close_cmd, 0, sizeof(close_cmd));
 3316         close_cmd.opcode    = CLOSE_TRACKSESSION;
 3317         close_cmd.function  = func;
 3318         _lto2b(param, close_cmd.tracksessionnr);
 3319 
 3320         error = scsipi_command(periph,
 3321                 (void *) &close_cmd, sizeof(close_cmd),
 3322                 NULL, 0,
 3323                 CDRETRIES, 120000, NULL, flags);
 3324 
 3325         return error;
 3326 }
 3327 
 3328 static int
 3329 mmc_do_closetrack(struct scsipi_periph *periph, struct mmc_op *mmc_op)
 3330 {
 3331         int mmc_profile = mmc_op->mmc_profile;
 3332 
 3333         switch (mmc_profile) {
 3334         case 0x12 : /* DVD-RAM */
 3335         case 0x1a : /* DVD+RW  */
 3336         case 0x2a : /* DVD+RW Dual layer */
 3337         case 0x42 : /* BD-R Random Recording (RRM) */
 3338         case 0x43 : /* BD-RE */
 3339         case 0x52 : /* HD DVD-RW ; DVD-RAM like */
 3340                 return EINVAL;
 3341         }
 3342 
 3343         return mmc_doclose(periph, mmc_op->tracknr, 1);
 3344 }
 3345 
 3346 static int
 3347 mmc_do_close_or_finalise(struct scsipi_periph *periph, struct mmc_op *mmc_op)
 3348 {
 3349         uint8_t blob[MS5LEN], *page5;
 3350         int mmc_profile = mmc_op->mmc_profile;
 3351         int func, close, flags;
 3352         int error;
 3353 
 3354         close = (mmc_op->operation == MMC_OP_CLOSESESSION);
 3355 
 3356         switch (mmc_profile) {
 3357         case 0x09 : /* CD-R       */
 3358         case 0x0a : /* CD-RW      */
 3359                 /* Special case : need to update MS field in mode page 5 */
 3360                 memset(blob, 0, sizeof(blob));
 3361                 page5 = blob+8;
 3362 
 3363                 flags = XS_CTL_DATA_IN;
 3364                 error = scsipi_mode_sense_big(periph, SMS_PF, 5,
 3365                     (void *)blob, sizeof(blob), flags, CDRETRIES, 20000);
 3366                 if (error)
 3367                         return error;
 3368 
 3369                 /* set multi session field when closing a session only */
 3370                 page5[3] &= 63;
 3371                 if (close)
 3372                         page5[3] |= 3 << 6;
 3373 
 3374                 flags = XS_CTL_DATA_OUT;
 3375                 error = scsipi_mode_select_big(periph, SMS_PF,
 3376                     (void *)blob, sizeof(blob), flags, CDRETRIES, 20000);
 3377                 if (error)
 3378                         return error;
 3379                 /* and use function 2 */
 3380                 func = 2;
 3381                 break;
 3382         case 0x11 : /* DVD-R (DL) */
 3383         case 0x13 : /* DVD-RW restricted overwrite */
 3384         case 0x14 : /* DVD-RW sequential */
 3385                 func = close ? 2 : 3;
 3386                 break;
 3387         case 0x1b : /* DVD+R   */
 3388         case 0x2b : /* DVD+R Dual layer */
 3389         case 0x51 : /* HD DVD-R   */
 3390         case 0x41 : /* BD-R Sequential recording (SRM) */
 3391                 func = close ? 2 : 6;
 3392                 break;
 3393         case 0x12 : /* DVD-RAM */
 3394         case 0x1a : /* DVD+RW  */
 3395         case 0x2a : /* DVD+RW Dual layer */
 3396         case 0x42 : /* BD-R Random Recording (RRM) */
 3397         case 0x43 : /* BD-RE */
 3398         case 0x52 : /* HD DVD-RW; DVD-RAM like */
 3399                 return EINVAL;
 3400         default:
 3401                 printf("MMC close/finalise passed wrong device type! (%d)\n",
 3402                     mmc_profile);
 3403                 return EINVAL;
 3404         }
 3405 
 3406         return mmc_doclose(periph, mmc_op->sessionnr, func);
 3407 }
 3408 
 3409 static int
 3410 mmc_do_reserve_track(struct scsipi_periph *periph, struct mmc_op *mmc_op)
 3411 {
 3412         struct scsipi_reserve_track reserve_cmd;
 3413         uint32_t extent;
 3414         int error, flags;
 3415 
 3416         /* TODO make mmc safeguards? */
 3417         extent = mmc_op->extent;
 3418         /* TODO min/max support? */
 3419 
 3420         /* set up SCSI call with requested space */
 3421         flags = XS_CTL_DATA_OUT;
 3422         memset(&reserve_cmd, 0, sizeof(reserve_cmd));
 3423         reserve_cmd.opcode = RESERVE_TRACK;
 3424         _lto4b(extent, reserve_cmd.reservation_size);
 3425 
 3426         error = scsipi_command(periph,
 3427                 (void *) &reserve_cmd, sizeof(reserve_cmd),
 3428                 NULL, 0,
 3429                 CDRETRIES, 30000, NULL, flags);
 3430 
 3431         return error;
 3432 }
 3433 
 3434 static int
 3435 mmc_do_reserve_track_nwa(struct scsipi_periph *periph, struct mmc_op *mmc_op)
 3436 {
 3437         /* XXX assumes that NWA given is valid */
 3438         switch (mmc_op->mmc_profile) {
 3439         case 0x09 : /* CD-R       */
 3440                 /* XXX unknown boundary checks XXX */
 3441                 if (mmc_op->extent <= 152)
 3442                         return EINVAL;
 3443                 /* CD-R takes 152 sectors to close track */
 3444                 mmc_op->extent -= 152;
 3445                 return mmc_do_reserve_track(periph, mmc_op);
 3446         case 0x11 : /* DVD-R (DL) */
 3447         case 0x1b : /* DVD+R   */
 3448         case 0x2b : /* DVD+R Dual layer */
 3449                 if (mmc_op->extent % 16)
 3450                         return EINVAL;
 3451                 /* upto one ECC block of 16 sectors lost */
 3452                 mmc_op->extent -= 16;
 3453                 return mmc_do_reserve_track(periph, mmc_op);
 3454         case 0x41 : /* BD-R Sequential recording (SRM) */
 3455         case 0x51 : /* HD DVD-R   */
 3456                 if (mmc_op->extent % 32)
 3457                         return EINVAL;
 3458                 /* one ECC block of 32 sectors lost (AFAIK) */
 3459                 mmc_op->extent -= 32;
 3460                 return mmc_do_reserve_track(periph, mmc_op);
 3461         }
 3462 
 3463         /* unknown behaviour or invalid disc type */
 3464         return EINVAL;
 3465 }
 3466 
 3467 static int
 3468 mmc_do_repair_track(struct scsipi_periph *periph, struct mmc_op *mmc_op)
 3469 {
 3470         struct scsipi_repair_track repair_cmd;
 3471         int error, flags;
 3472 
 3473         /* TODO make mmc safeguards? */
 3474 
 3475         /* set up SCSI call with track number */
 3476         flags = XS_CTL_DATA_OUT;
 3477         memset(&repair_cmd, 0, sizeof(repair_cmd));
 3478         repair_cmd.opcode = REPAIR_TRACK;
 3479         _lto2b(mmc_op->tracknr, repair_cmd.tracknr);
 3480 
 3481         error = scsipi_command(periph,
 3482                 (void *) &repair_cmd, sizeof(repair_cmd),
 3483                 NULL, 0,
 3484                 CDRETRIES, 30000, NULL, flags);
 3485 
 3486         return error;
 3487 }
 3488 
 3489 static int
 3490 mmc_do_op(struct scsipi_periph *periph, struct mmc_op *mmc_op)
 3491 {
 3492         /* guard operation value */
 3493         if (mmc_op->operation < 1 || mmc_op->operation > MMC_OP_MAX)
 3494                 return EINVAL;
 3495 
 3496         /* synchronise cache is special since it doesn't rely on mmc_profile */
 3497         if (mmc_op->operation == MMC_OP_SYNCHRONISECACHE)
 3498                 return cdcachesync(periph, 0);
 3499 
 3500         /* zero mmc_profile means unknown disc so operations are not defined */
 3501         if (mmc_op->mmc_profile == 0) {
 3502 #ifdef DEBUG
 3503                 printf("mmc_do_op called with mmc_profile = 0\n");
 3504 #endif
 3505                 return EINVAL;
 3506         }
 3507 
 3508         /* do the operations */
 3509         switch (mmc_op->operation) {
 3510         case MMC_OP_CLOSETRACK   :
 3511                 return mmc_do_closetrack(periph, mmc_op);
 3512         case MMC_OP_CLOSESESSION :
 3513         case MMC_OP_FINALISEDISC :
 3514                 return mmc_do_close_or_finalise(periph, mmc_op);
 3515         case MMC_OP_RESERVETRACK :
 3516                 return mmc_do_reserve_track(periph, mmc_op);
 3517         case MMC_OP_RESERVETRACK_NWA :
 3518                 return mmc_do_reserve_track_nwa(periph, mmc_op);
 3519         case MMC_OP_REPAIRTRACK  :
 3520                 return mmc_do_repair_track(periph, mmc_op);
 3521         case MMC_OP_UNCLOSELASTSESSION :
 3522                 /* TODO unclose last session support */
 3523                 return EINVAL;
 3524         default :
 3525                 printf("mmc_do_op: unhandled operation %d\n", mmc_op->operation);
 3526         }
 3527 
 3528         return EINVAL;
 3529 }
 3530 
 3531 static int
 3532 mmc_setup_writeparams(struct scsipi_periph *periph,
 3533                       struct mmc_writeparams *mmc_writeparams)
 3534 {
 3535         struct mmc_trackinfo trackinfo;
 3536         uint8_t blob[MS5LEN];
 3537         uint8_t *page5;
 3538         int flags, error;
 3539         int track_mode, data_mode;
 3540 
 3541         /* setup mode page 5 for CD only */
 3542         if (mmc_writeparams->mmc_class != MMC_CLASS_CD)
 3543                 return 0;
 3544 
 3545         memset(blob, 0, sizeof(blob));
 3546         page5 = blob+8;
 3547 
 3548         /* read mode page 5 (with header) */
 3549         flags = XS_CTL_DATA_IN;
 3550         error = scsipi_mode_sense_big(periph, SMS_PF, 5, (void *)blob,
 3551             sizeof(blob), flags, CDRETRIES, 20000);
 3552         if (error)
 3553                 return error;
 3554 
 3555         /* set page length for reassurance */
 3556         page5[1] = P5LEN;       /* page length */
 3557 
 3558         /* write type packet/incremental */
 3559         page5[2] &= 0xf0;
 3560 
 3561         /* set specified mode parameters */
 3562         track_mode = mmc_writeparams->track_mode;
 3563         data_mode  = mmc_writeparams->data_mode;
 3564         if (track_mode <= 0 || track_mode > 15)
 3565                 return EINVAL;
 3566         if (data_mode < 1 || data_mode > 2)
 3567                 return EINVAL;
 3568 
 3569         /* if a tracknr is passed, setup according to the track */
 3570         if (mmc_writeparams->tracknr > 0) {
 3571                 trackinfo.tracknr = mmc_writeparams->tracknr;
 3572                 error = mmc_gettrackinfo(periph, &trackinfo);
 3573                 if (error)
 3574                         return error;
 3575                 if ((trackinfo.flags & MMC_TRACKINFO_BLANK) == 0) {
 3576                         track_mode = trackinfo.track_mode;
 3577                         data_mode  = trackinfo.data_mode;
 3578                 }
 3579                 mmc_writeparams->blockingnr = trackinfo.packet_size;
 3580         }
 3581 
 3582         /* copy track mode and data mode from trackinfo */
 3583         page5[3] &= 16;         /* keep only `Copy' bit */
 3584         page5[3] |= (3 << 6) | track_mode;
 3585         page5[4] &= 0xf0;       /* wipe data block type */
 3586         if (data_mode == 1) {
 3587                 /* select ISO mode 1 (CD only) */
 3588                 page5[4] |= 8;
 3589                 /* select session format normal disc (CD only) */
 3590                 page5[8] = 0;
 3591         } else {
 3592                 /* select ISO mode 2; XA form 1 (CD only) */
 3593                 page5[4] |= 10;
 3594                 /* select session format CD-ROM XA disc (CD only) */
 3595                 page5[8] = 0x20;
 3596         }
 3597         if (mmc_writeparams->mmc_cur & MMC_CAP_SEQUENTIAL) {
 3598                 if (mmc_writeparams->mmc_cur & MMC_CAP_ZEROLINKBLK) {
 3599                         /* set BUFE buffer underrun protection */
 3600                         page5[2] |= 1<<6;
 3601                 }
 3602                 /* allow for multi session */
 3603                 page5[3] |= 3 << 6;
 3604         } else {
 3605                 /* select fixed packets */
 3606                 page5[3] |= 1<<5;
 3607                 _lto4b(mmc_writeparams->blockingnr, &(page5[10]));
 3608         }
 3609 
 3610         /* write out updated mode page 5 (with header) */
 3611         flags = XS_CTL_DATA_OUT;
 3612         error = scsipi_mode_select_big(periph, SMS_PF, (void *)blob,
 3613             sizeof(blob), flags, CDRETRIES, 20000);
 3614         if (error)
 3615                 return error;
 3616 
 3617         return 0;
 3618 }
 3619 
 3620 static void
 3621 cd_set_geometry(struct cd_softc *cd)
 3622 {
 3623         struct dk_softc *dksc = &cd->sc_dksc;
 3624         struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
 3625 
 3626         memset(dg, 0, sizeof(*dg));
 3627 
 3628         dg->dg_secperunit = cd->params.disksize;
 3629         dg->dg_secsize = cd->params.blksize;
 3630         dg->dg_nsectors = 100;
 3631         dg->dg_ntracks = 1;
 3632 
 3633         disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
 3634 }

Cache object: 88e4b831a96a569deaeba296d4990537


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